Total Pageviews

Showing posts with label nginx. Show all posts
Showing posts with label nginx. Show all posts

Tuesday, 13 January 2026

nginx的缓存配置

 

    在浏览器里面访问时:
    在nginx没有特意配置缓存的情况下,前端项目可能会走浏览器的默认缓存策略 (启发式缓存 heuritic cache), 但是某些情况下nginx也默认会自动为静态文件生成etag和last-modified头信息。

    这种情况下,会缓存所有文件(包括html入口文件和资源文件),代码更新以后,页面简单的刷新有时候更新不过来(因为html入口被缓存了)。所以当用户反馈自己浏览器看到的还是旧版本,一般会让用户强按ctrl+f5 (Hard Reloads 硬加载) 来清除缓存拿到最新代码版本。

    这种硬加载,会给request header带上cache-control:no-cache, 从而可确保浏览器绕过缓存,从服务器请求所有资源的新副本; 这和在dev-tool勾选"Disable cache" 是一个效果。

    被嵌入到其它应用程序里面访问时:
    这种情况,用户强按ctrl+f5一般无法生效,应用程序有自己的缓存策略,在移动端甚至无法这样操作。
    这种情况下,缓存严重的情况下,一般只能让用户去手动清除应用程序的缓存。 但是这种方案很不太合理:一是不可能每次更新代码版本让用户去清除缓存; 二是当前前端项目可能只是大应用程序里面的一个业务模块而已,不可能其中一个模块更新了,就让用户去清除缓存。

SPA 缓存策略

入口 HTML 禁用缓存,静态资源长期缓存。

这样代码版本更新以后,用户只需要简单的刷新即可获取到最新版本。 因为SPA一般只有一个index.html入口,而该入口我们并没有缓存;html的更新会导致引用的js、css等资源的更新。

   root /root/aaaa;  # 全局定义一次root

    # 1. HTML入口 - 禁用缓存
    location ~* \.html$ {
        gzip_static on; #
        access_log off;

        add_header Last-Modified $date_gmt;
        add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
        
        if_modified_since off;
        expires 0;
        etag off;
    }

    # 2. 静态资源 - 长期缓存
    location ~* \.(?:js|css|png|jpg|jpeg|gif|ico|woff2?|ttf|eot|svg|webp)$ {
        add_header Cache-Control "public, max-age=31536000, immutable";
        expires 1y;
        access_log off;
    }

    location  / {
        try_files $uri $uri/ /index.html;
    }

当然也可以使用 指纹网址(Fingerprinted URLs) 来实现类似的效果,比如给首页后面添加?t=时间戳。 但是一方面某些系统的url是固定的;另外一方面一些比较正式的系统上比如toG系统,这种动态url显的不专业。

如果进一步提升用户体验,还可以在当检测到更新时,以弹窗形式通知那些长时间停留没有刷新的用户(相当于一个主动推送更新机制):
在前端代码版本更新以后 → 用户没有刷新页面的情况下 → 弹窗提示用户"页面内容已更新,请点击确定刷新页面" → 用户点击确认 → 调用window.location.reload()


额外的话

这里说的只是nginx缓存,如果使用了cdn,代码版本更新以后,还要走cdn刷新和预热。

Saturday, 22 March 2025

在nginx的配置文件里的某个server段里,可以添加多个域名

 比如:

 server {

        listen       80;

        server_name  zl.briten.top brite.zone.id luckypoem.netlib.re;


 location / {

            root   /usr/local/zola-site/public;

            index  index.html index.htm;

        }

}

然后重启nginx,这样,访问zl.briten.top或brite.zone.id 或luckypoem.netlib.re都可访问我的zola blog.

相关帖子:

Friday, 21 March 2025

如何修复Nginx的502 Bad Gateway错误?

 

A 502 Bad Gateway error implies that the server (Nginx) can’t properly communicate with the upstream web application server. A sign of more severe problems, such as server overload, improper configuration, or network failure, a 502 Bad Gateway error can cause service interruption, which can translate to revenue loss. Fortunately, you can easily resolve the error in Nginx once you identify the causes.

In this post, we’ll examine the 502 Bad Gateway error in Nginx, what causes the error, and how to both fix and prevent occurrence.

What Is Error 502 Bad Gateway in Nginx?

Nginx is a popular web server that also functions as a reverse proxy, load balancer, and HTTP cache. A 502 Bad Gateway error in Nginx is a status code that says that the server (Nginx) acting as a gateway or proxy is not able to connect to, or received an invalid response from an upstream server. When you use Nginx as a reverse proxy server to forward client requests to back-end servers, Nginx should relay responses from the servers back to the client. Thus, when a 502 Bad Gateway returns, it signals that Nginx cannot reach the server, resulting in a failed request.

For example, in a microservice architecture, using Nginx to forward requests to an offline or crushed service can result in a bad gateway error. To resolve this, you’ll need to ensure that the upstream service – in this case, the microservice – is running and able to receive requests.

A 502 Bad Gateway error is very similar to 503 Service Unavailable and 504 Gateway Timeout errors, so be careful. Correct and timely root cause analysis is key for effective issue resolution, so, always pay close attention to error messages and the associated context.

What Causes 502 Bad Gateway in Nginx?

Some of the common causes of a bad gateway error in Nginx include the following:

Misconfiguration

If Nginx is misconfigured and trying to communicate with the wrong upstream server, you’re likely to get a bad gateway error. Additionally, if the Nginx configuration points to an invalid IP address or port, Nginx will forward requests to the wrong port or a server that isn’t correctly set up to handle those requests and will return a 502 error.

Server Overload

When the upstream server is too busy and overwhelmed with requests, it’s bound to experience resource exhaustion. As a result, the server might stop accepting new requests, start dropping accepted requests, and, and return an invalid response to Nginx with a 502 Bad Gateway error.

Timeouts

If the upstream server is slow to respond beyond the configured timeout limit in Nginx, a 502 error can occur. Ordinarily timeouts cause a 504 Gateway Timeout error, so be sure which you’re dealing with. Either way, network delays or server overload are the likely causes.

Upstream Server Down

Another common cause is the server being offline or unreachable, because of crushing or not starting. That way, when Nginx forwards requests to the upstream server, it doesn’t get any response from the upstream server and, as a result, returns a bad gateway error. In addition, an upstream server may send a 502 status code to Nginx when having problems routing requests to target applications. Be sure to check for all possibilities when troubleshooting.

DNS Issues

Sometimes Nginx can use a domain name to route traffic to an upstream server. If the DNS server experiences any resolution issues, it could prevent Nginx from finding the correct IP address, causing a 502 error.

SSL/TLS Handshake Failure

Suppose Nginx tries to establish a secure connection with the upstream server, but there are incompatibilities between them. The handshake will fail, leading to a bad gateway error.

How to Identify a Bad Gateway Error

Here are some ways to identify and troubleshoot the bad gateway error in Nginx:

Check the Nginx Error Logs

The first step is always to check the error logs. These will point out the error that caused Nginx to fail to communicate with the upstream server. Typically, you can find these logs in a file at the location: /var/log/nginx/error.log. However, be sure to check the nginx.conf or sites-enabled/<>.conf file to identify the correct path to the log file.

Once you open the error log file, search for entries that correspond to the time when the 502 error occurred. Look for lines containing “502” or phrases like “upstream” or “bad gateway.”

These logs often provide clues, such as whether the upstream server is unreachable, timed out, or returned an invalid response.

Ensure the Upstream Server Is Running

A 502 error occurs because Nginx cannot communicate with the upstream server. Make sure the upstream server is functioning properly. You can use tools like curl to test connectivity directly from the Nginx server to ensure that the upstream server is reachable. If it’s unresponsive, you may need to restart or troubleshoot it.

Monitor Performance

Monitoring performance includes checking for CPU, memory, and network bottlenecks on both Nginx and the upstream servers. High server load on either Nginx or the upstream server can cause slow responses or timeouts, leading to 502 errors.

How Can I Fix a Bad Gateway Error?

After identifying what caused the bad gateway error, here’s how you can fix it:

Check Nginx Configuration

Verify Nginx’s configuration to ensure that it’s correctly pointing to the right upstream server and port. Make sure the IP address and port are correct.

Check for Network Issues

Check for network issues between Nginx and the upstream server and verify that the Nginx server can reach it. You can also check firewall rules and network configurations that might be blocking traffic between Nginx and the upstream server.

Verify SSL Certificates

If Nginx uses HTTPS to communicate with the upstream server, correctly configure the SSL certificates and verify that they’re not expired. Ensure that the SSL settings in both Nginx and the upstream server are compatible.

Review DNS Settings

If Nginx uses domain names to resolve upstream server addresses and the DNS resolution is slow, consider using IP addresses instead of domain names in the Nginx configuration.

Review Application Server Code

Sometimes the upstream server might return invalid responses because of bugs or misconfigurations in the application. Check the upstream server’s logs to identify any errors and fix bugs that might cause the server to crash or return invalid responses.

Restart Nginx

If none of the above solutions work, consider restarting Nginx to resolve issues.

How Do You Bypass 502 Bad Gateway in Nginx?

Bypassing gives you a temporary solution to keep the system running while you work on fixing the root cause. Here are some approaches you can use:

Serve Cached Content

If your application supports caching, you can serve cached versions of the website or content until the upstream server is back online or responsive. Set up Nginx to serve cached static files when the upstream server is unavailable.

Have a Backup Upstream Server

Consider a secondary or backup server where you can configure Nginx to route traffic to when the primary upstream server is unavailable.

Use Content Delivery Network (CDN)

If you consistently encounter 502 errors because of upstream server overloads, consider using a CDN to distribute traffic more effectively and reduce server load.

Show a Maintenance Page

If you’re fixing the upstream server and need a temporary solution, you can return a custom maintenance page to inform users of the downtime in case of 502 errors.

How to Prevent the 502 Bad Gateway in Nginx

You can use the following strategies to prevent 502 errors in Nginx:

  • Adjust timeout settings in Nginx to accommodate slow responses from upstream servers, especially if they perform heavy processing
  • Optimize the performance of the applications running on the upstream servers to prevent them from becoming slow or unresponsive
  • Continuously monitor the health and performance of Nginx, the upstream servers, and the network connecting them
  • Update Nginx, upstream servers, and their dependencies regularly to ensure they have the latest security patches

How Stackify APM Logging Helps Identify and Resolve Error 502 in Nginx

Stackify APM offers centralized logging, which gathers logs from different parts of your infrastructure, such as Nginx, application servers, and databases. When you get a 502 error, Stackify’s aggregated server and application logs speed up effective identification of the root causes, so you can resolve issues quickly. Stackify APM provides real-time visibility into application health and actionable insights on optimizing performance and resolving errors, like a 502 Bad Gateway in Nginx.

 来自 https://stackify.com/error-502-bad-gateway-in-nginx-what-it-is-and-how-to-fix-it/

 

Sunday, 16 February 2025

Nginx Location的匹配

 

一、语法:

location [=|~|~*|^~] /uri/ { … }

二、修饰符:

修饰符 类型 说明 示例
= 普通匹配 精确匹配 location = /url/
^~ 普通匹配 普通字符串前缀匹配,忽略后续正则匹配 location ^~ /url/
普通匹配 普通字符串前缀匹配 location /url/
~ 正则匹配 正则匹配,区分大小写 location ~ .*.(js
~* 正则匹配 正则匹配,忽略大小写 location ~* .*.(js

三、顺序(先查找最长普通匹配,再顺序进行正则匹配):

image

1、找到精确匹配(=),不再往下查找

2、找到最长普通匹配,没有前缀(^~),往下顺序查找正则匹配

(1)找到符合的正则匹配,不再查找

(2)没有符合的正则匹配,使用最长普通匹配

3、找到最长普通匹配,有前缀(^~),不再往下查找

4、顺序查找正则匹配

四、示例

在线测试:https://nginx.viraptor.info/

1、

server {
 listen       80;
 server_name  test.com www.test.com;

 # A
 location ^~ /static/ {}

 # B
 location /static/js {}

 # C
 location ~* /(static|public)/ {}

 # D
 location = / {}
}

http://test.com/ -> D http://test.com/static -> A http://test.com/static/js -> C 这里B永远匹配不上,因为能匹配B的情况下,也都能匹配C

2、

server {
 listen       80;
 server_name  test.com www.test.com;

 # A
 location = / { }

 # B
 location / { }

 # C
 location /user/ { }

 # D
 location ^~ /images/ { }

 # E
 location ~* \.(gif|jpg|jpeg)$ { }
}

http://test.com/index.html -> B http://test.com/documents/about.html -> B http://test.com/user/index.html -> C http://test.com/user/abc.jpg -> E http://test.com/images/abc.jpg -> D http://test.com/ -> A

Tuesday, 4 February 2025

Nginx 正确设置 default_server 避免恶意解析和IP访问

 

Nginx 默认 Server

默认情况下 nginx 的 default_server 指令可以处理没有匹配到 server_name 的请求,如果没有显式定义 default_server,则 nginx 会选取第一个定义的 server 作为 default_server。

默认 Server 存在的问题

这样的规则会导致两个问题:

  1. 当有任何域名解析到我们的服务器,我们的 default_server 都会处理它,如果我们没有设置 default_server 则我们的第一个 server 会处理这些域名,无论这些 server 是否绑定 server_name;
  2. 如果我们没有绑定 IP 到 server,当使用 IP 访问我们的服务器时,也会被 default_server 处理;

这两个问题会带来什么样的灾难,大家都明白,这里就不再赘述了;

如何规避默认 Server 带来的问题

取消 80 端口的 default_server

解决默认 Server 最简单的办法就是取消默认 Server 就行了;

但是 nginx 中我们无法取消,因为不显示申明,也会默认第一个 Server 作为隐式申明

既然不能取消,那我们就只能修改默认 Server 的表现行为了;

我们可以通过如下配置,让 default_server 直接返回 444 状态;

server {
listen 80 default_server;
server_name _;
return 444;
}

444 No Response

Nginx上HTTP服务器扩展。服务器不向客户端返回任何信息,并关闭连接(有助于阻止恶意软件)。

取消 443 端口的 default_server

由于 443 需要 ssl 证书,所以还需要再 80 的配置上增加关于 ssl 的配置;

server {
listen 443 default_server;
server_name _;

ssl_certificate /etc/nginx/ssl/nginx.crt; # 证书配置
ssl_certificate_key /etc/nginx/ssl/nginx.key; # 证书配置

return 444;
}

上述配置中的证书配置可以采用任意证书,因为我们本就不会处理匹配的请求,所以不需要正确的证书来获取浏览器的信任,但是 nginx 的 443 端口 server 又必须配置 ssl 证书,所以这里我们自己生成一个证书就可以了,不建议使用自有的真实证书,这会暴露域名;

生成证书:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt

HTTP 自动跳转到 HTTPS

有时候我们需要使用 default_server 为我们带来便利,例如:实际网站的 server 中仅配置 443 端口,80 端口的请求统一跳转到对应的 443 服务;

server {
listen 80 default_server;
server_name _;
return 301 https://$host$request_uri;
}

那么这时候,未受理的域名和ip访问均会跳转到 443 端口,我们只需要对 443 的默认 Server 输出 HTTP Status 444 就行了;

server {
listen 443 default_server;
server_name _;

ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;

return 444;
}

完整配置

不自动强制 HTTPS

server {
listen 80 default_server;
server_name _;
return 444;
}
server {
listen 443 default_server;
server_name _;

ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;

return 444;
}

需要 HTTP 自动跳转到 HTTPS

server {
listen 80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
server {
listen 443 default_server;
server_name _;

ssl_certificate /etc/nginx/ssl/nginx.crt;
ssl_certificate_key /etc/nginx/ssl/nginx.key;

return 444;
}

Sunday, 1 December 2024

VeryNginx, nginx的加强版

 A very powerful and friendly nginx base on lua-nginx-module( openresty ) which provide WAF, Control Panel, and Dashboards.

VeryNginx is a very powerful and friendly nginx .

中文文档

Notice

After v0.2 , The entry uri of control panel was moved to /verynginx/index.html

Description

VeryNginx is based on lua_nginx_module(openrestry). It implements advanced firewall(waf), access statistics and some other features. It strengthens the Nginx's functions, and provides a friendly Web interface.

VeryNginx online demo

User / Password: verynginx / verynginx

The full version of config guide can be found on: VeryNginx Wiki .

from https://github.com/alexazhou/VeryNginx

 

Saturday, 30 November 2024

lua-openresty-lor-blog

 luajit openresty lor web blog。

依赖

OpenResty 一个基于 Nginx 与Lua 的高性能 Web 平台

Lor a fast, minimalist web framework for lua based on OpenResty

如何使用LOR,并导入项目代码

数据库MYSQL

表结构

+---------+------------------+------+-----+---------+----------------+
| Field   | Type             | Null | Key | Default | Extra          |
+---------+------------------+------+-----+---------+----------------+
| id      | int(11) unsigned | NO   | PRI | NULL    | auto_increment |
| title   | varchar(255)     | NO   |     |         |                |
| content | text             | NO   |     | NULL    |                |
| created | datetime         | NO   |     | NULL    |                |
+---------+------------------+------+-----+---------+----------------+

MySql 个人感觉比较“重量级”,更偏向使用 sqlite 做数据迁移较为方便,专心记录一些东西。

配置文件

lua-blog/config$ config.lua

return{
  page_config = {
    post_page_size = 10
  },
  -- 生成session的secret,请一定要修改此值为一复杂的字符串,用于加密session
  session_secret = "vMG94;WslOxfCL[tHoY,UqZ`+ndJhr=X",

  -- 用于存储密码的盐,请一定要修改此值, 一旦使用不能修改,用户也可自行实现其他密码方案
  pwd_secret = "_&e=wTXW",

  view_config = {
    engine = "tmpl",
    ext = "html",
    views = "./app/views"
  },
  -- mysql config
  mysql = {
    timeout = 5000,

    connect_config = {
      host = "127.0.0.1",
      port = 3306,
      database = "blog",
      user = "root",
      password = "root",
      max_packet_size = 1024 * 1024
    },

    pool_config = {
      max_idle_timeout = 20000, -- 20s
            pool_size = 50 -- connection pool size
    }
  },
  auth = {
    username = "sha256用户名",
    password = "sha256密码"
  }
}

from https://github.com/blackstorm/lua-openresty-lor-blog

Sunday, 17 November 2024

Nginx的进程模型


Nginx其实有两种进程结构,一种是单进程结构,一种是多进程结构。单进程结构只适合我们做开发调试,在生产环境下,为了保持 Nginx 足够健壮,以及可以利用到 CPU 的多核特性,我们用到的是多进程架构的Nginx。

多进程架构的Nginx,有一个父进程 master process,master 会有很多子进程,这些子进程分为两类,一类是worker 进程,一类是 cache 相关的进程。

在一个四核的Linux服务器上查看Nginx进程:    

$ ps -ef --forest | grep nginx
mazhen     20875   13073  0 15:25 pts/0    00:00:00          |   \_ grep --color=auto nginx
mazhen     20862       1  0 15:25 ?        00:00:00 nginx: master process ./sbin/nginx
mazhen     20863   20862  0 15:25 ?        00:00:00  \_ nginx: worker process
mazhen     20864   20862  0 15:25 ?        00:00:00  \_ nginx: worker process
mazhen     20865   20862  0 15:25 ?        00:00:00  \_ nginx: worker process
mazhen     20866   20862  0 15:25 ?        00:00:00  \_ nginx: worker process
mazhen     20867   20862  0 15:25 ?        00:00:00  \_ nginx: cache manager process
mazhen     20868   20862  0 15:25 ?        00:00:00  \_ nginx: cache loader process

可以看到,Nginx 的 master 进程创建了4个 worker 进程,以及用来管理磁盘内容缓存的缓存helper进程。

为什么Nginx使用的是多进程结构,而不是多线程结构呢?因为多线程结构,线程之间是共享同一个进程地址空间,当某一个第三方模块出现了地址空间的断错误时,会导致整个Nginx进程挂掉,而多进程模型就不会出现这样的问题,Nginx的第三方模块通常不会在 master 进程中加入自己的功能代码。

master 进程执行一些特权操作,比如读取配置以及绑定端口,它管理 worker 进程的,负责监控每个 worke进程是否在正常工作,是否需要重载配置文件,以及做热部署等。

worker 进程处理真正的请求,从磁盘读取内容或往磁盘中写入内容,以及与上游服务器通信。

cache manager 进程会周期性地运行,从磁盘缓存中删除条目,以保证缓存没有超过配置的大小。

cache loader 进程在启动时运行,用于将磁盘上的缓存加载到内存中,随后退出。

Nginx 采用了事件驱动的模型,它希望 worker 进程的数量和 CPU 一致,并且每一个 worker 进程与某一颗CPU绑定,worker 进程以非阻塞的方式处理多个连接,减少了上下文切换,同时更好的利用到了 CPU 缓存,减少缓存失效。
#
请求处理流程


Nginx 使用的是非阻塞的事件驱动处理引擎,需要用状态机来把这个请求正确的识别和处理。Nginx 内部有三个状态机,分别是处理4层 TCP 流量的传输层状态机,处理7层流量的HTTP状态机和处理邮件的email 状态机。

worker 进程首先等待监听套接字上的事件,新接入的连接会触发事件,然后连接分配到一个状态机。

state machine

状态机本质上是告诉 Nginx 如何处理请求的指令集。解析出的请求是要访问静态资源,那么就去磁盘加载静态资源,更多的时候 Nginx 是作为负载均衡或者反向代理使用,这个时候请求会通过4层或7层协议,传输到上游服务器。对于每一个处理完成的请求,Nginx会记录 access 日志和 error 日志。
#
Nginx 进程管理

Linux 上多进程之间进行通讯,可以使用共享内存和信号。Nginx 在做进程间的管理时,使用了信号。我们可以使用 kill 命令直接向 master 进程和 worker 进程发送信号,也可以使用 nginx 命令行。

master 进程接收处理的信号:

    CHLD 在 Linux 系统中,当子进程终止的时候,会向父进程发送 CHLD 信号。master 进程启动的 worker 进程,所以 master 是 worker 的父进程。如果 worker 进程由于一些原因意外退出,那么 master 进程会立刻收到通知,可以重新启动一个新的 worker进程。

    TERM 和 INT 立刻终止 worker 和 master 进程。

    QUIT 优雅的停止 worker 和 master 进程。worker 不会向客户端发送 reset 立即结束连接。

    HUP 重新加载配置文件

    USR1 重新打开日志文件,做日志文件的切割

    USR2 通知 master 开始进行热部署

    WINCH 在热部署过程中,通知旧的 master ,让它优雅关闭 worker 进程

我们也可以通过 nginx -s 命令向 master 进程发送信号。在 Nginx 启动过程中, Nginx 会把 master 的 PID 记录在文件中,这个文件的默认位置是 $nginx/logs/nginx.pid 。 当我们执行 nginx -s 命令时,nginx 命令会去读取 nginx.pid 文件中 master 进程的 PID,然后向 master 进程发送对应的信号。下面是 nginx -s 命令对应的信号:

    reload - HUP
    reopen - USR1
    stop - TERM
    quit - QUIT

使用 nginx -s 和 直接使用 kill 命令向 master 进程发送信号,效果是一样的。

注意,USR2 和 WINCH 没有对应的 nginx -s 命令,只能通过 kill 命令直接向 master 进程发送。

worker 进程能接收的信号:

    TERM 和 INT
    QUIT
    USR1
    WINCH

worker 进程收到这些信号,会产生和发给 master 一样的效果。但我们通常不会直接向 worker 进程发送信号,而是通过 master 进程来管理 worker 进程,master 进程收到信号以后,会再把信号转发给 worker 进程。
#
Nginx 配置更新流程


当更改了 Nginx 配置文件后,我们都会执行 nginx -s reload 命令重新加载配置文件。Nginx 不会停止服务,在处理新的请求的同时,平滑的进行配置文件的更新。

执行 nginx -s reload 命令,会向 master 进程发送 SIGHUP 信号。当 master 进程接收 SIGHUP信号后,会做如下处理:

    检查配置文件语法是否正确。
    master 加载配置,启动一组新的 worker 进程。这些 worker 进程马上开始接收新连接和处理网络请求。子进程可以共享使用父进程已经打开的端口,所以新的 worker 可以和老的worker监听同样的端口。
    master 向旧的 worker 发送 QUIT 信号,让旧的 worker 优雅退出。
    旧的 worker 进程停止接收新连接,完成现有连接的处理后结束进程。

#
Nginx 热部署流程

Nginx 支持热部署,在升级的过程中也实现了高可用性,不导致任何连接丢失,停机时间或服务中断。热部署的流程如下:

    备份旧的 nginx 二进制文件,将新的nginx二进制文件拷贝到 $nginx_home/sbin目录。
    向 master 进程发送 USR2 信号。
    master 进程用新的nginx文件启动新的master进程,新的master进程会启动新的worker进程。
    向旧的 master 进程发送 WINCH 信号,让它优雅的关闭旧的 worker 进程。此时旧的 master 仍然在运行。
    如果想回滚到旧版本,可以向旧的 master 发送 HUP 信号,向新的master 发送QUIT信号。
    如果一切正常,可以向旧的 master 发送 QUIT 信号,关闭旧的 master。

用Nginx配置静态资源

配置文件语法

Nginx的配置文件是一个文本文件,由指令和指令块构成。
#
指令

指令以分号 ; 结尾,指令和参数间以空格分割。

指令块作为容器,将相关的指令组合在一起,用大括号 {} 将它们包围起来。
 
http {
    include       mime.types;
    default_type  application/octet-stream;

    server {
        listen       8080;
        server_name  localhost;
        location / {
            root   html;
            index  index.html index.htm;
        }
  }
}

上面配置中的http、server、location等都是指令块。指令块配置项之后是否如参数(例如 location /),取决于解析这个块配置项的模块。

指令块配置项是可以嵌套的。内层块会继承父级块包含的指令的设置。有些指令可以出现在多层指令块内,你可以通过在内层指令块包含该指令,来覆盖从父级继承的设置。
#
Context

一些 top-level 指令被称为 context,将适用于不同流量类型的指令组合在一起。

    events – 通用的连接处理
    http – HTTP流量
    mail – Mail 流量
    stream – TCP 和 UDP 流量

放在这些 context 之外的指令是在 main context中。

在每个流量处理 context 中,可以包括一个或多个 server 块,用来定义控制请求处理的虚拟服务器。

对于HTTP流量,每个 server 指令块是对特定域名或IP地址访问的控制。通过一个活多个 location 定义如何处理特定的URI。

对于 Mail 和 TCP/UDP 流量,server 指令块是对特定 TCP 端口流量的控制。
#
静态资源服务

将个人网站的静态资源 clone 到 nginx 根目录:
git clone https://github.com/mz1999/mazhen.git

在 conf/nginx.conf 文件中配置监听端口和 location:

http {
    server {
        listen       8080;
        server_name  localhost;
        
        #charset koi8-r;
        #access_log  logs/host.access.log  main;
        
        location / {
            alias   mazhen/;
            #index  index.html index.htm;
        }

}

location 的语法格式为:

location [ = | ~ | ~* | ^~ ] uri { ... }

location 会尝试根据用户请求中的 URI 来匹配上面的 uri 表达式,如果可以匹配,就选择这个 location 块中的配置来处理用户请求。

location 指定文件路径有两种方式:root和alias。

root 与alias 会以不同的方式将请求映射到服务器的文件上,它们的主要区别在于如何解释 location 后面的 uri 。

    root的处理结果是,root+location uri。
    alias的处理结果是,使用 alias 替换 location uri。 alias 作为一个目录别名的定义。

例如:

location /i/ {
    root /data/w3;
}

如果一个请求的 URI 是 /i/top.gif ,Nginx 将会返回服务器上的 /data/w3/i/top.gif 文件。

location /i/ {
    alias /data/w3/images/;
}

如果一个请求的 URI 是 /i/top.gif,Nginx 将会返回服务器上的 /data/w3/images/top.gif文件。alias 会把 location 后面配置的 uri 替换为 alias 定义的目录。

最后要注意,使用 alias 时,目录名后面一定要加 /。
#
开启gzip

Nginx 的 ngx_http_gzip_module 模块是一个过滤器,它使用 “gzip “方法压缩响应。可以在 http context 下配置 gzip:

http {
    ...
    gzip  on;
    gzip_min_length 1000;
    gzip_comp_level 2;
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
 
    server {
        ...
    }
}

    gzip_min_length:设置允许压缩的页面最小字节数
    gzip_comp_level: 设置 gzip 压缩比,1 压缩比最小处理速度最快,9 压缩比最大但处理最慢
    gzip_types:匹配MIME类型进行压缩。

更多的配置项,可以参考官方文档。
#
autoindex

Nginx 的 ngx_http_autoindex_module 模块处理以斜线字符 / 结尾的请求,并产生一个目录列表。通常情况下,当 ngx_http_index_module 模块找不到index文件时,请求会被传递给 ngx_http_autoindex_module 模块。

autoindex 的配置很简单:
location / {
    alias   mazhen/;
    autoindex on;
}

注意,只有 index 模块找不到index文件时,请求才会被 autoindex 模块处理。我们可以把 mazhen 目录下的 index 文件删掉,或者为 index 指令配置一个不存在的文件。
#
limit_rate

由于带宽的限制,我们有时候需要限制某些资源向客户端传输响应的速率,例如可以对大文件限速,避免传输大文件占用过多带宽,从而影响其他更重要的小文件(css,js)的传输。我们可以使用 set 指令配合内置变量 $limit_rate 实现这个功能:
location / {
    ...
    set $limit_rate 1k;
}

上面的指令限制了Nginx向客户端发送响应的速率为 1k/秒。

$limit_rate是Nginx的内置变量,Nginx的文档详细列出了每个模块的内置变量。

ngx_http_core_module 为例,在 Nginx文档首页的 Modules reference 部分,点击进入 ngx_http_core_module 

ngx_http_core_module 文档目录的最下方,点击 Embedded Variables ,会跳转到 ngx_http_core_module 内置变量列表。

这里有 http module 所有内置变量的说明,包括我们刚才使用 $limit_rate

access log

Nginx 的 access log 功能由 ngx_http_log_module 模块提供。ngx_http_log_module 提供了两个指令:

  • log_format 指定日志格式
  • access_log 设置日志写入的路径

举例说明:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
http {
    ...
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    server {
        ...
        access_log  logs/mazhen.access.log  main;
    }
}

log_format 使用内置变量定义日志格式,示例中的 log_format 可以使用 http module 定义的内置变量。log_format 还指定了这个日志格式的名称为 main,这样让我们定义多种格式的日志,为不同的 server 配置特定的日志格式。

access_log 设置了日志路径为 logs/mazhen.access.log,并指定了日志格式为 main。示例中的 access_log 定义在 server 下,那所有发往这个 server 的请求日志都使用 main 格式,被记录在 logs/mazhen.access.log文件中。

 




Nginx做反向代理的配置

 

upstream

作为反向代理,一般都需要向上游服务器的集群转发请求。upstream 块定义了一个上游服务器的集群,便于反向代理中的 proxy_pass使用。

1
2
3
4
5
6
7
http {
    ...
    upstream backend {
        server 127.0.0.1:8080;
    }
    ...
}

upstream 定义了一组上游服务器,并命名为 backend

proxy_pass

proxy_pass 指令设置代理服务器的协议和地址。协议可以指定 “http “或 “https”。地址可以指定为域名或IP地址,也可以配置为 upstream 定义的上游服务器:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
http {
    server {
        listen       6888;
        server_name  localhost;

        location / {
            proxy_pass http://backend;
        }
    }
}

proxy_set_header

在传递给上游服务器的请求头中,可以使用proxy_set_header 重新定义或添加字段。一般我们使用 proxy_set_header 向上游服务器传递一些必要的信息。

1
2
3
4
5
6
location / {
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://backend;
}

上面的配置使用 proxy_set_header 添加了三个 HTTP header:

  • Host

Host 是表明请求的主机名。默认情况下,Nginx 向上游服务器发送请求时,请求头中的 Host 字段是上游真实服务器的IP和端口号。如果我们想让传递给上游服务器的 Host 字段,包含的是用户访问反向代理时使用的域名,就需要通过 proxy_set_header 设置 Host 字段,值可以为 $host$http_host,区别是前者只包含IP,而后者包含IP和端口号。

  • X-Real-IP

经过反向代理后,上游服务器无法直接拿到客户端的 ip,也就是说,在应用中使用request.getRemoteAddr() 获得的是 Nginx 的地址。通过 proxy_set_header X-Real-IP $remote_addr;,将客户端的 ip 添加到了 HTTP header中,让应用可以使用 request.getHeader(“X-Real-IP”) 获取客户端的真实ip。

  • X-Forwarded-For

如果配置了多层反向代理,当一个请求经过多层代理到达上游服务器时,上游服务器通过 X-Real-IP 获得的就不是客户端的真实IP了。那么这个时候就要用到 X-Forwarded-For ,设置 X-Forwarded-For 时是增加,而不是覆盖,从客户的真实IP为起点,穿过多层级代理 ,最终到达上游服务器,都会被记录下来。

Nginx 作为反向代理支持的所有特性和内置变量都可以在 ngx_http_proxy_module 的文档页面找到。

示例:https://briteming.blogspot.com/2024/11/nodemdblog.html 

-----

参考:

https://server.51cto.com/article/770062.html

https://www.cnblogs.com/wenxuehai/p/14974657.html#autoid-h2-3-1-0

 

Tuesday, 15 October 2024

简易nginx TCP反向代理设置



nginx从1.9.0开始支持TCP反向代理,之前只支持HTTP。这是示意图:



为何需要?

为什么需要反向代理?主要是:

    负载均衡
    方便管控

比如我现在要更新后端服务器,如果不用负载均衡的话,在更新过程中,用户会出现无法连接服务器的情况,而一旦用了负载均衡,用户此时的连接请求将会分配到别的没在更新的后端服务器去,尽可能地确保了服务的可用性;再考虑这么种情况,我有多个服务器后端,那么就需要打开多个不同的监听端口,我需要在系统防火墙里做多个配置,如果它们与客户端的连接使用了SSL/TLS,那么得给它们各自配置证书,现在用了反向代理的话这些都简化了,服务器只需要打开一个对外监听端口,证书也只需要给反向代理配置好即可,就是我说的方便管控,当然了,还能方便的管控流量,设置一些额外的访问策略什么的。

那么反向代理的缺点是什么?我想如果后端多了起来,连接多了起来之后,对nginx来说是一个很大的挑战,毕竟TCP和HTTP不一样,TCP通常是“长连接”,要一直维持着的。到时候如果nginx撑不下去,就考虑用硬件负载均衡吧(不过听说这玩意儿不便宜)。
安装nginx

安装nginx的旧方法当然是去官网下载tar包,解压缩,configure,make,现在我们不妨改进一下——用yum安装,这样更省事。我用的CentOS7的默认yum容器貌似并没有nginx,需要自己加装一下,其实很简单,改一下配置即可。在/etc/yum.repo.d底下创建文件nginx.repo,内容为:

[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=0
enabled=1

然后:

#yum install nginx

nginx默认安装在/usr/sbin/nginx,检验下是否我们需要的nginx版本:

#/usr/sbin/nginx -v

我安装的是1.9.11,没问题!再看看--with-stream和--with-stream_ssl_module这两个参数是否存在:

#/usr/sbin/nginx -V

如果没有看到这两个参数,那就只好走老路来安装nginx了。

允许开机自动运行:

#systemctl enable nginx

启动:

#systemctl start nginx

对应着以前的service nginx start

查看nginx状态:

#systemctl status nginx

对应着以前的service nginx status

发现了没有,使用yum安装管理起来也简单了。
nginx配置

编辑/etc/nginx/nginx.conf

stream{
    upstream backend{                                         
        hash $remote_addr consistent;
        server 127.0.0.1:7397 max_fails=3 fail_timeout=10s;   
        server 127.0.0.1:7398 max_fails=3 fail_timeout=10s;
    }

    server{
        listen 1268 ssl;                                     
        ssl_certificate     /home/guogangj/certs/cert1268.pem;
        ssl_certificate_key  /home/guogangj/certs/key1268.pem;
        ssl_session_cache    shared:SSL:10m;                  
        ssl_session_timeout  10m;                            
        ssl_ciphers  HIGH:!aNULL:!MD5;                       
        ssl_prefer_server_ciphers  on;                       
        proxy_connect_timeout 20s;                            
        proxy_timeout 5m;                                     
        proxy_pass backend;                                   
    }
}


配置说明:

1) 设置一个叫“backend”的后端配置

2) 我有两个后端服务器,其中之一监听在7397端口,nginx尝试连接之,(10秒钟为判定失败的时长,这个我暂时也不太明白)最多失败3次,超过则不再重试

3) nginx监听在1268端口,使用SSL安全连接

注意:有必要的话,调整firewalld或iptables来允许这个端口的外部访问,对firewalld来说,可以添加这样的策略

firewall-cmd --zone=public --add-port=1268/tcp --permanent
firewall-cmd --reload

查看一下firewalld的策略列表:

firewall-cmd --permanent --zone=public --list-all

4) 所使用的X.509证书文件(PEM格式).对于使用TCP协议的服务器端,其实是可以用自签的证书的,(如何生成自签证书,刚提到的文章里也有说明)你客户端“认”它就是了,反正我们的目的就是防范中间人攻击,不像做网站,我们得让浏览器“认”证书才行

5) 证书私钥文件

6) 设置SSL Session Cache使用“shared”方式更有利于提高资源的利用率,“SSL”是给缓存起的名字,你可以改成别的(这个名字如何用我现在不太清楚),“10m”为缓存大小(1M的缓存大约可以存放4000个session)

7) SSL Session的失效时间,默认5分钟,我设为10分钟

8) 指定SSL加密算法,照写即可(我一看数学就头大,所以至今仍未明白RSA的数学原理)

9) 更偏向于使用服务器的加密算法(这个我不太明白什么意思)

10) 指定nginx连接后端服务器超时的时间,指定为20秒

11) 距离上一次成功访问(连接或读写)后端服务器的时间超过了5分钟就判定为超时,断开此连接

12) 将TCP连接及数据收发转向叫“backend”的后端(这句话很关键)
完成

好像没啥好说的了,客户端连接1268这个端口完事。哦,对了,改好配置了别忘记重启下nginx:
#systemctl restart nginx



Thursday, 13 June 2024

Nginx之stream模块初体验

 stream模块通过复制流并按照规则进行转发以实现TCP或者UDP代理,进而实现负载均衡.对于https协议,因为没有加解密证书,因此能保证性能和数据安全性,需要Nginx版本不低于1.11.5,且在编译Nginx时需要配置:

1
2
3
--with-stream \
–with-stream_ssl_module \
--with-stream_ssl_preread_module \

参数方可。对于Nginx的编译安装,网上一大把,我这里就不再赘述了,值得一提的时官方提供有编译好的最新版二进制文件,懒得编译安装的童鞋(比如我)可以戳这里:https://nginx.org/en/linux_packages.html(Mainline版为开发版,对于stream模块,直接使用默认的nginx包即可,官方有如下解释:“Main nginx package is built with all modules that do not require additional libraries to avoid extra dependencies.”),二进制安装后Nginx默认配置文件位置为/etc/nginx/nginx.conf

接下来就是配置Nginx了,一种比较比较危险但简单粗暴的配置:

1
2
3
4
5
6
7
8
stream {
    server {
        listen 443;
        ssl_preread on;
        resolver 8.8.8.8;
        proxy_pass $ssl_preread_server_name:$server_port;
    }
}

当然你也可以指定被负载均衡的域名、超时时间、缓冲区大小、IP黑白名单等、限制连接数等等操作,具体如何实现请参看官方文档(stream模块在下方):
https://nginx.org/en/docs/