Skip to content

Nginx

部署

1、执行安装环境命令

shell
yum install -y gcc-c++ pcre pcre-devel zlib zlib-devel openssl openssl-devel

2、下载Nginx,解压至服务器

nginx: download

shell
tar -zxvf nginx-1.26.2.tar.gz

3、进入解压缩后的目录执行命令

shell
cd ./nginx-1.26.2/

./configure
 
make && make install

4、查看nginx安装目录

shell
whereis nginx

cd /usr/local/nginx/

5、Nginx常用命令

进入到Nginx安装目录 sbin目录下,可以执行以下命令

命令作用
./nginx启动Nginx
./nginx -s stop终止Nginx
./nginx -s reopen重启Nginx
./nginx -s reload重新加载配置文件
./nginx -v查看Nginx版本
./nginx -t查看当前Nginx配置文件是否存在问题

6、开放80端口

shell
# 3306 端口对外开放
firewall-cmd --permanent --add-port=80/tcp
# 重启防火墙
firewall-cmd --reload
# 查询端口开放情况
firewall-cmd --query-port=80/tcp

Nginx配置

配置概述

总体结构

shell
main        # 全局配置,对全局生效
├── events  # 配置影响 Nginx 服务器或与用户的网络连接
├── http    # 配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置
│   ├── upstream # 配置后端服务器具体地址,负载均衡配置不可或缺的部分
│   ├── server   # 配置虚拟主机的相关参数,一个 http 块中可以有多个 server 块
│   ├── server
│   │   ├── location  # server 块可以包含多个 location 块,location 指令用于匹配 uri
│   │   ├── location
│   │   └── ...
│   └── ...
└── ...

基本配置

nginx
#运行用户,可以不进行设置
#user  nobody;  
worker_processes  1; # Nginx 进程数,一般设置为和 CPU 核数一样


# Nginx 的错误日志存放目录
#level(日志等级):
#具体如下:[ debug | info | notice | warn | error | crit(默认) ]
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;


# Nginx 服务启动时的 pid 存放位置
#pid        logs/nginx.pid;


events {
	# 每个进程允许最大并发数,作为反向代理服务器,每个并发会建立与客户端的连接和与后端服务的连接,会占用两个连接。
    worker_connections  1024;
}


http {
    # 文件扩展名与类型映射表,用于设置响应请求的Content-Type,如下方映射
    # text/html                                        html htm shtml;
    include       mime.types;
    
    #如果 不能从mime.types找到映射的话,使用以下作为默认值
    default_type  application/octet-stream;

	#日志格式
    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

	# Nginx访问日志存放位置
    #access_log  logs/access.log  main;

    #开启从磁盘直接到网络的文件传输,适用于有大文件上传下载的情况,提高IO效率。
    sendfile        on;
    
    # 减少网络报文段的数量
    #tcp_nopush     on;

	#一个请求完成之后还要保持连接多久
    #keepalive_timeout  0;
    keepalive_timeout  65;
    
 	#开启或者关闭gzip压缩
    #gzip  on;

	# 加载子配置项,会将该路径下,以.conf结尾的文件全部引入配置	
	# include /etc/nginx/conf.d/*.conf;  
    
    server {
     	# 配置监听的端口
        listen       80;
        # 配置的域名
        server_name  localhost;
        
        # 定义响应数据的传输速度,默认bytes/s
    	limit_rate 20;
        
        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
    		root   /usr/share/nginx/html;  # 网站根目录
    		index  index.html index.htm;   # 默认首页文件
    		deny 172.168.22.11;   # 禁止访问的ip地址,可以为all
    		allow 172.168.33.44; # 允许访问的ip地址,可以为all
    	}

        #error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        # 默认50x对应的访问页面
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

全局变量

全局变量名功能
$host请求信息中的 Host,如果请求中没有 Host 行,则等于设置的服务器名,不包含端口
$request_method客户端请求类型,如 GETPOST
$remote_addr客户端的 IP 地址
$args请求中的参数
$arg_PARAMETERGET 请求中变量名 PARAMETER 参数的值,例如:$http_user_agent(Uaer-Agent 值), $http_referer...
$content_length请求头中的 Content-length 字段
$http_user_agent客户端agent信息
$http_cookie客户端cookie信息
$remote_port客户端的端口
$http_user_agent客户端agent信息
$server_protocol请求使用的协议,如 HTTP/1.0HTTP/1.1
$server_addr服务器地址
$server_name服务器名称
$server_port服务器的端口号
$schemeHTTP 方法(如http,https)
$time_local请求时间

路径匹配

匹配符作用
=精准匹配,要求请求路径与 uri 严格匹配,如果匹配成功,就停止继续向下搜索并立即处理该请求。
^~带参前缀匹配,匹配成功则立即停止其他类型匹配
~正则匹配(区分大小写)。当同时有多个正则匹配时,按其在配置文件中出现的先后顺序优先匹配,命中则立即停止其他类型匹配
~*正则匹配(不区分大小写)
/任何没有匹配成功的,都会匹配这里处理

反向代理

基本配置

正向代理 和反向代理的主要区别是他们提供服务的对象不同

  • 正向代理是为客户端做事隐藏客户端,去请求服务器,最终服务器是不知道这个请求一开始是哪个客户端发起的
  • 反向代理是为服务器做事隐藏服务器,反向代理服务器转发客户请求,客户端不知道这个数据是哪个最终服务器处理的
nginx
server {
  # 监听端口号
  listen 9001;
  # 监听地址为本机
  server_name localhost;
	
  # 正则匹配/edu/的请求,将转发给 http://127.0.0.1:8080;
  location ~ /edu/ {
    proxy_pass http://127.0.0.1:8080;
  }
  
  location ~ /vod/ {
    proxy_pass http://127.0.0.1:8081;
  }
}

跨域问题

跨域是浏览器受同源(协议、域名、端口)策略的限制,不允许不同源的站点之间进行某些操作,如Ajax请求、读取cookie等。是浏览器不允许,不是服务器不允许,服务器通过添加请求头告诉浏览器他是允许的

CORS解决方案(服务器端配置)

后端项目中,通过继承HandlerInterceptorAdapter类、实现WebMvcConfigurer接口、添加@CrossOrgin注解的方式实现接口之间的跨域配置。

简单请求(get、post等请求)

浏览器在请求头中自动加入origin字段,用来说明本次请求来自哪个源(协议+域名+端口),服务器根据这个值,决定是否同意这次请求。

  • 如果origin指定的源,不在服务器许可范围内,服务器会返回一个正常的http回应。这个回应的头信息没有包含 Access-Control-Allow-Origin 字段,浏览器借此就可以知道不支持跨域请求,报错
  • 如果Origin指定的域名在服务器许可范围内,服务器返回的头字段中会包含Access-Control-Allow-Origin,请求成功
非简单请求(put、delete等请求)

非简单请求需要先发出一个预检请求(OPTIONS),用来获知服务器是否允许该实际请求跨域,可以避免跨域请求对服务器的用户数据产生未预期的影响(PUT、delete)

如果你在请求中添加了自定义请求头(例如 token),浏览器会发送预检请求来确认服务器是否允许这些头,需要在响应头中添加字段:"Access-Control-Allow-Headers: Content-Type, token\r\n"向浏览器声明可以接受请求头

  • 如果预检请求未通过,比如origin不在信任名单内,会返回一个正常的HTTP回应,但是没有任何CORS相关的头信息字段。浏览器就会报错
  • 如果预检请求通过,浏览器才会发送真正的请求,且以后每次浏览器正常的CORS请求,就都跟简单请求一样
nginx解决方案(前端配置)
反向代理

由Nginx实现反向代理,客户端的请求不再发向服务器,而是法向Nginx,这样就不存在不同源问题了

Nginx添加请求头
nginx
server {
  listen       80;
  server_name  localhost
  
    # 添加响应头
    add_header 'Access-Control-Allow-Origin' $http_origin;   # 全局变量获得当前请求origin,带cookie的请求不支持*
    add_header 'Access-Control-Allow-Credentials' 'true';    # 为 true 可带上 cookie
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';  # 允许请求方法
    add_header 'Access-Control-Allow-Headers' $http_access_control_request_headers;  # 允许请求的 header,可以为 *
    add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
	
  # 如果是预检请求,添加下方配置
  if ($request_method = 'OPTIONS') {
		add_header 'Access-Control-Max-Age' 1728000;   # OPTIONS 请求的有效期,在有效期内不用发出另一条预检请求
		add_header 'Content-Type' 'text/plain; charset=utf-8';
		add_header 'Content-Length' 0;
    
		return 204;                  # 200 也可以
	}
  
	location / {
		root  /usr/share/nginx/html/be;
		index index.html;
	}
}

GZIP压缩

GZIP检测 - 网页GZIP压缩检测 (bmcx.com)

  • 请求 html 和 css 等静态资源的时候,浏览器在请求消息头中包含 Accept-Encoding: gzip(大部分浏览器的默认设置),表示自己支持 gzip 的压缩方式。
  • Nginx 若开启gzip压缩,且浏览器支持gzip,就会返回经过 gzip 压缩过的文件给浏览器,并在 response 相应的时候加上 content-encoding: gzip 来告诉浏览器自己采用的压缩方式(因为浏览器在传给服务器的时候一般还告诉服务器自己支持好几种压缩方式)。

以下配置可以添加到http全局块中,也可以放到server块,或者location块中。

核心配置

Nginx
# 在conf配置文件中直接配置,或者在conf.d中配置, 使用include引入

# 默认off,是否开启gzip
gzip on;

# 压缩的文件类型,其中 text/html 被系统强制启用
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

其他配置

配置作用
gzip_static on;如果存在预先压缩好的静态文件(gz结尾),则直接返回预先压缩过的版本
gzip_proxied any;对于后端服务器的响应结果是否开启压缩
gzip_vary on;当 gzip 压缩被激活时,Nginx 将添加一个 Vary: Accept-Encoding HTTP 头到响应中,告诉客户端(例如浏览器)它应该根据 Accept-Encoding 请求头来缓存不同的变体(未压缩和压缩的版本)。
gzip_comp_level 6;gzip 压缩比,压缩级别是 1-9,级别越高压缩率越大,压缩时间越长,建议 4-6;
gzip_buffers 16 8k;设置处理压缩请求的缓冲区数量和大小,总大小为8k*16
gzip_http_version 1.1指定压缩响应所需要的最低HTTP请求版本
gzip_min_length 1k;文件大于多少时开启压缩,默认是0(head中的Content-Length指定),但是过小的文件压缩可能会导致文件变大

负载均衡

  • 轮询:默认方式,每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务挂了,能自动剔除;
  • weight:权重分配,指定轮询几率,权重越高,在被访问的概率越大,用于后端服务器性能不均的情况;
  • ip_hash:每个请求按访问 IP 的 hash 结果分配,这样每个访客固定访问一个后端服务器,可以解决动态网页 session 共享问题。
  • least_conn:最少连接数
  • least_time:最短响应时间
  • random:随机
nginx
http {
  upstream myserver {
    # 指定负载均衡方式
  	# ip_hash; 
    # hash $request_uri;
    # least_conn;   
        
        
   # 指定负载均衡的服务器
   # 30s内检查心跳发送两次包,未回复就代表该机器宕机,请求分发权重比为1:2(weight默认为 1)
   server 192.168.0.000:8080 weight=100 max_fails=2 fail_timeout=30s; 
   server 192.168.0.000:8090 weight=200 max_fails=2 fail_timeout=30s;
  }
 
  server {
    location / {
    	proxy_pass http://myserver;
      proxy_connect_timeout 10;
    }
  }
}

动静分离

  1. 纯粹把静态文件独立成单独的域名,放在独立的服务器上(目前主流推崇的方案)。
  2. 动态跟静态文件混合在一起发布, 通过 Nginx 配置来分开。(前后端不分离,可以将resources/static目录下的文件拷贝到Nginx进行部署)
nginx
server {  
        listen       8080;        
        server_name  localhost;

        location / {
            root   html; # Nginx默认值
            index  index.html index.htm;
        	# 配置缓存过期时间
       		expires  3600000
        }
        
        # 静态化配置,所有静态请求都转发给 nginx 处理,存放目录为 my-project
    	# ~代表匹配时区分大小写
		# .*代表任意字符都可以出现零次或多次,即资源名不限制
		# \.代表匹配后缀分隔符.
		(html|...|css)代表匹配括号里所有静态资源类型
        location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|js|css)$ {
            root /usr/local/var/www/my-project; # 静态请求所代理到的根目录
        }
        
        # 动态请求匹配到path为'node'的就转发到8002端口处理
        location /node/ {  
            proxy_pass http://localhost:8002; # 充当服务代理
        }
}

HTTPS加密传输

如果是云服务器,将证书拷贝到目录下即可

shell
# 配置https签名证书
# 1、创建https证书存放目录:
cd /usr/local/nginx/conf/
mkdir ssl
# 2、创建私钥
openssl genrsa -des3 -out https.key 1024
# 3、创建签名请求证书:
openssl req -new -key https.key -out https.csr
# 4、在加载SSL支持的Nginx并使用上述私钥时除去必须的口令:
cp https.key https.key.org
openssl rsa -in https.key.org -out https.key
# 5、最后标记证书使用上述私钥和CSR和有效期:
openssl x509 -req -days 365 -in https.csr -signkey https.key -out https.crt
nginx
server {
  listen 443 ssl;   # SSL 访问端口号为 443
  server_name https://www.xxx.com;         # 填写绑定证书的域名
  # 打开SSL加密传输
  ssl on; 
    
  # RSA证书
  ssl_certificate     /usr/local/nginx/conf/ssl/https.crt; 
  # RSA密钥
  ssl_certificate_key  /usr/local/nginx/conf/ssl/https.key; 
  # 停止通信时,加密会话的有效期,在该时间段内不需要重新交换密钥
  ssl_session_timeout 5m;
  # TLS握手时,服务器采用的密码套件
  ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
  # 服务器支持的TLS版本
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  # 开启由服务器决定采用的密码套件
  ssl_prefer_server_ciphers on;
  
  keepalive_timeout    75s;
  keepalive_requests   100;
        
  location / {
    root         /usr/share/nginx/html;
    index        index.html index.htm;
  }
}


# ---------HTTP请求转HTTPS-------------
server {
    # 监听HTTP默认的80端口
    listen 80;
    # 如果80端口出现访问该域名的请求
    server_name www.xxx.com;
    # 将请求改写为HTTPS(这里写你配置了HTTPS的域名)
    rewrite ^(.*)$ https://www.xxx.com;
}

文件下载服务器

nginx
server {
    listen 8004;
    server_name localhost;
    
    # 正常显示中文,windows服务器下中文目录无法下钻,目前无解
    charset gbk,utf-8;

    # 打开autoindex功能,以/结尾的请求
    autoindex on;
    
    # 显示文件的大小,
    # on:以字节显示
    # off:人性化显示,文件过大会显示为mb或gb
    autoindex_exact_size off;
    
    # 以哪种格式返回:html | xml | json | jsonp
    # 默认值:autoindex_format html
    autoindex_format html;
    
    # 显示时间格式
    # on: 12-Jul-2019 10:11(当前时区)
    # off: 12-Jul-2019 02:11(0时区,GMT)
    autoindex_localtime on;

    location / {
        root /data/files/;
        # 如果a.html文件存在,则会返回a.html内容,否则才会返回目录内容
        index a.html;
    } 
}

限流

nginx

http {
    include       mime.types;
    default_type  application/json;
    
    # limit_conn_zone key zone=name:size,限制每个客户端的最大并发连接数
    # key:用于定义客户端的唯一标识来限速,如remote_addr
    # name:任意名称
    # size:共享内存大小空间,m为单位
    # binary_remote_addr 使用4个字节空间,高效;remote_addr 使用7-15个字节空间
    limit_conn_zone $binary_remote_addr zone=limit_addr:10m;
    
    # limit_req_zone key zone=name:size rate=rate;限制了每个客户端的请求速率
    # 上下文:http
    # rate:表示允许相同标识的客户端的访问频次,12r/m的,每分钟只能发送12个请求(也可以使用s)
    limit_req_zone  $binary_remote_addr zone=limit_req:15m rate=12r/m;

    server {
        listen       80;
        server_name  localhost;

        location / {
           root   html;
           index  index.html index.htm;
            
            # 触发限速后,返回状态码,默认503
            # 上下文:http, server, location
            limit_conn_status 503;
            
            # 当触发限速后,错误日志出记录一条日志, 这里用于定义日志等级
            # info|notice|warn|error
            # 上下文:http, server, location
            # 默认值:error
            limit_conn_log_level warn;
            
            # limit_conn zone number;
            # zone:用limit_conn_zone中定义的zone名称
            # number:以zone为标识的客户端被允许的同时最大连接数
            limit_conn limit_addr 2;
            
            # 定义响应数据的传输速度,bytes/s
            # 本指令属于ngx_http_core_module,不属于ngx_http_limit_conn_module
            limit_rate 50;

            # limit_req_status code(http的状态码) 
            # 默认值:503
            # 上下文:http, server, location
            limit_req_status 504;
            
            # 触发限速后,日志记录的等级 
            # info|notice|warn|error
            # 默认值:error
            # 上下文:http, server, location
            limit_req_log_level notice;
            
            # limit_req zone=name [burst=number] [nodelay | delay=number];
            # burst:桶大小,设置一个大小为x的缓冲区,当有大量请求(爆发)过来时,超过了访问频次限制的请求可以先放到这个缓冲区内等待,但是这个等待区里的位置只有5个,超过的请求会直接报503的错误然后返回。
            # nodelay:如果设置,会在瞬时提供处理(burst + rate)个请求的能力,请求超过(burst + rate)的时候就会直接返回503,永远不存在请求需要等待的情况。
            # 上下文:http, server, location
            # limit_req zone=limit_req burst=7 nodelay;
            limit_req zone=limit_req;
        }
    }
}

黑白名单

可以直接在nginx.conf配置文件中配置,但建议使用include导入,服务器检测到爬虫IP后,再发送请求将其追加到到include指定的文件中

Nginx
# --------黑名单:BlocksIP.conf---------
deny 192.177.12.222; # 屏蔽192.177.12.222访问
deny 127.0.0.0/8; # 屏蔽127.0.0.1到127.255.255.254网段中的所有IP访问

# --------白名单:WhiteIP.conf---------
allow 192.177.12.222; # 允许192.177.12.222访问
allow 127.45.0.0/16; # 允许127.45.0.1到127.45.255.254网段中的所有IP访问
deny all; # 除开上述IP外,其他IP全部禁止访问


http{
    # 整站屏蔽/开放就在http中导入
    include /soft/nginx/IP/BlocksIP.conf; 
    
 	server{
        # 如果只需要一个域名下屏蔽/开放就在sever中导入
    	location xxx {
        	# 如果只需要针对于某一系列接口屏蔽/开放IP,那么就在location中导入。
            include /soft/nginx/IP/blockip.conf; 
   		 }
 	}
}

防盗链

通过判断Referer(浏览器添加,描述了当前请求发出地,无法解决爬虫伪造referers信息的这种方式抓取数据)有关,如果不是本站的资源引用请求则不允许访问。也可以通过第三方依赖ngx_http_accesskey_module实现

valid_referers字段值:

  • none:表示接受没有Referer字段的HTTP请求访问。
  • blocked:表示允许http://https//以外的请求访问。
  • server_names:资源的白名单,这里可以指定允许访问的域名。
  • string:可自定义字符串,支配通配符、正则表达式写法。
nginx
# 在动静分离的location中开启防盗链机制
location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css){
    # 最后面的值在上线前可配置为允许的域名地址
    valid_referers blocked 192.168.12.129;
    if ($invalid_referer) {
        # 可以配置成返回一张禁止盗取的图片
        # rewrite   ^/ http://xx.xx.com/NO.jpg;
        # 也可直接返回403
        return   403;
    }
    
    root   /soft/nginx/static_resources;
    expires 7d;
}

nginx缓冲区

访问请求流程:客户端→ Nginx→ 服务端。在这个流程中,维护两个连接:“客户端→Nginx”和“Nginx→服务端”,为避免这两个链接速度不一致,Nginx 引入了缓冲区机制

  • 客户端到nginx速度快,nginx到服务器速度慢,使用缓冲区,积累到一定量,再传输到客户端,减少Tcp请求。

  • 客户端到nginx速度慢,nginx到服务器速度快,使用缓冲区,服务器返回内容放到缓冲区后,nginx到服务器的连接就能断开了,客户端从缓冲区拉取即可。

配置作用
proxy_buffering是否启用缓冲机制,默认为on打开状态。
client_body_buffer_size设置缓冲客户端请求数据的内存大小。
proxy_buffers为每个请求/连接设置缓冲区的数量和大小,默认4 4k/8k。
proxy_buffer_size设置用于存储响应头的缓冲区大小。
proxy_busy_buffers_size在后端数据没有完全接收完成时,Nginx可以将busy状态的缓冲返回给客户端,该参数用来设置busy状态的buffer具体有多大,默认为proxy_buffer_size*2。
proxy_temp_path path当内存缓冲区存满时,可以将数据临时存放到磁盘,path是存放的目录。
proxy_temp_file_write_size设置每次写数据到临时文件的大小限制。
proxy_max_temp_file_size设置临时的缓冲目录中允许存储的最大容量。
proxy_connect_timeout设置与后端服务器建立连接时的超时时间。
proxy_read_timeout设置从后端服务器读取响应数据的超时时间。
proxy_send_timeout设置向后端服务器传输请求数据的超时时间。
nginx
http{
    proxy_connect_timeout 10;
    proxy_read_timeout 120;
    proxy_send_timeout 10;
    proxy_buffering on;
    client_body_buffer_size 512k;
    proxy_buffers 4 64k;
    proxy_buffer_size 16k;
    proxy_busy_buffers_size 128k;
    proxy_temp_file_write_size 128k;
    proxy_temp_path /soft/nginx/temp_buffer;
}

nginx缓存

  • 减少了再次向后端或文件服务器请求资源的带宽消耗。
  • 缩短了响应时间,提升了加载速度,打开页面的速度更快。

proxy_cache_path:代理缓存的路径。

  • proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time] [max_size=size] [manager_files=number] [manager_sleep=time] [manager_threshold=time] [loader_files=number] [loader_sleep=time] [loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time];
    • path:缓存的路径地址。
    • levels:缓存存储的层次结构,最多允许三层目录。
    • use_temp_path:是否使用临时目录。
    • keys_zone:指定一个共享内存空间来存储热点Key(1M可存储8000Key)。
    • inactive:设置缓存多长时间未被访问后删除(默认是十分钟)。
    • max_size:允许缓存的最大存储空间,超出后会基于LRU算法移除缓存,Nginx会创建一个Cache manager的进程移除数据,也可以通过purge方式。
    • manager_filesmanager进程每次移除缓存文件数量的上限。
    • manager_sleepmanager进程每次移除缓存文件的时间上限。
    • manager_thresholdmanager进程每次移除缓存后的间隔时间。
    • loader_files:重启Nginx载入缓存时,每次加载的个数,默认100
    • loader_sleep:每次载入时,允许的最大时间上限,默认200ms
    • loader_threshold:一次载入后,停顿的时间间隔,默认50ms
    • purger:是否开启purge方式移除数据。
    • purger_files:每次移除缓存文件时的数量。
    • purger_sleep:每次移除时,允许消耗的最大时间。
    • purger_threshold:每次移除完成后,停顿的间隔时间。

proxy_cache:开启或关闭代理缓存,开启时需要指定一个共享内存区域。

  • proxy_cache zone | off:zone为内存区域的名称,即上面中keys_zone设置的名称。

proxy_cache_key:定义如何生成缓存的键。

  • proxy_cache_key string:string为生成Key的规则,如$scheme$proxy_host$request_uri

proxy_cache_valid:缓存生效的状态码与过期时间。

  • proxy_cache_valid [code ...] time:code为状态码,time为有效时间,可以根据状态码设置不同的缓存时间。

proxy_cache_min_uses:设置资源被请求多少次后被缓存。

  • proxy_cache_min_uses number:number为次数,默认为1

proxy_cache_use_stale:当后端出现异常时,是否允许Nginx返回缓存作为响应。

  • proxy_cache_use_stale error:error为错误类型,可配置timeout|invalid_header|updating|http_500...

proxy_cache_lock:对于相同的请求,是否开启锁机制,只允许一个请求发往后端。

  • 语法:proxy_cache_lock on | off;

proxy_cache_lock_timeout:配置锁超时机制,超出规定时间后会释放请求。

  • proxy_cache_lock_timeout time;

proxy_cache_methods:设置对于那些HTTP方法开启缓存。

  • proxy_cache_methods method:method为请求方法类型,如GET、HEAD`等。

proxy_no_cache:定义不存储缓存的条件,符合时不会保存。

  • proxy_no_cache string...:string为条件,例如$cookie_nocache $arg_nocache $arg_comment;

proxy_cache_bypass:定义不读取缓存的条件,符合时不会从缓存中读取。

  • proxy_cache_bypass string...:和上面proxy_no_cache的配置方法类似。

add_header:往响应头中添加字段信息。

  • add_header fieldName fieldValue;

$upstream_cache_status:记录了缓存是否命中的信息,存在多种情况(nginx的内置变量):

  • MISS:请求未命中缓存。
  • HIT:请求命中缓存。
  • EXPIRED:请求命中缓存但缓存已过期。
  • STALE:请求命中了陈旧缓存。
  • REVALIDDATEDNginx验证陈旧缓存依然有效。
  • UPDATING:命中的缓存内容陈旧,但正在更新缓存。
  • BYPASS:响应结果是从原始服务器获取的。
nginx
http{
    # 设置缓存的目录,并且内存中缓存区名为hot_cache,大小为128m,
    # 三天未被访问过的缓存自动清楚,磁盘中缓存的最大容量为2GB。
    proxy_cache_path /soft/nginx/cache levels=1:2 keys_zone=hot_cache:128m inactive=3d max_size=2g;
    
    server{
        location / {
            # 使用名为nginx_cache的缓存空间
            proxy_cache hot_cache;
            # 对于200、206、304、301、302状态码的数据缓存1天
            proxy_cache_valid 200 206 304 301 302 1d;
            # 对于其他状态的数据缓存30分钟
            proxy_cache_valid any 30m;
            # 定义生成缓存键的规则(请求的url+参数作为key)
            proxy_cache_key $host$uri$is_args$args;
            # 资源至少被重复访问三次后再加入缓存
            proxy_cache_min_uses 3;
            # 出现重复请求时,只让一个去后端读数据,其他的从缓存中读取
            proxy_cache_lock on;
            # 上面的锁超时时间为3s,超过3s未获取数据,其他请求直接去后端
            proxy_cache_lock_timeout 3s;
            # 对于请求参数或cookie中声明了不缓存的数据,不再加入缓存
            proxy_no_cache $cookie_nocache $arg_nocache $arg_comment;
            # 在响应头中添加一个缓存是否命中的状态(便于调试)
            add_header Cache-status $upstream_cache_status;
        }
    }
}

nginx大文件上传

Nginx中也可以作为文件服务器使用,但需要使用第三方模块nginx-upload-module,如果项目中文件上传的作用处不多,那么建议可以通过Nginx搭建。但如若文件上传/下载较为频繁,那么还是建议额外搭建文件服务器。

配置项释义
client_max_body_size设置请求体允许的最大体积
client_header_timeout等待客户端发送一个请求头的超时时间
client_body_timeout设置读取请求体的超时时间
proxy_read_timeout设置请求被后端服务器读取时,Nginx等待的最长时间
proxy_send_timeout设置后端向Nginx返回响应时的超时时间

Nginx优化配置

打开长连接配置

Nginx作为代理服务时,负责分发客户端的请求,建议开启HTTP长连接,用户减少握手的次数,降低服务器损耗

nginx
upstream xxx {
    # 长连接数
    keepalive 32;
    # 每个长连接提供的最大请求数
    keepalived_requests 100;
    # 每个长连接没有新的请求时,保持的最长时间
    keepalive_timeout 60s;
}

开启零拷贝技术

  • 传统方式:硬件-->内核-->用户空间-->程序空间-->程序内核空间-->网络套接字
  • 零拷贝方式:硬件-->内核-->程序内核空间-->网络套接字
nginx
sendfile on; # 开启零拷贝机制

开启无延迟或多包共发机制

  • tcp_nodelay

    TCP/IP协议在网络数据传输过程中,会等待一段时间,将后面的几个数据包一起组合成一个数据报文发送。需要实时性,则手动开启tcp_nodelay配置,让每个数据包都会立即发送出去。但这样会产生大量的TCP报文头,增加很大的网络开销。

  • tcp_nopush

    内核会尽量把小数据包拼接成一个大的数据包(一个MTU)再发送出去。当然若一定时间后(一般为200ms),内核仍然没有积累到一个MTU的量时,也必须发送现有的数据。

nginx
# 以下两个参数配置是互斥的

# 无延迟配置,`tcp_nodelay`一般要建立在开启了长连接模式的情况下使用。
tcp_nodelay on;

# 多包共发机制,`tcp_nopush`参数是必须要开启`sendfile`参数才可使用的。
tcp_nopush on;

调整Worker工作进程

根据机器的CPU核数开启对应数量的工作进程(工作进程的数量最高开到8个,8个之后就不会有再大的性能提升。)

shell
# 自动根据CPU核心数调整Worker进程数量
worker_processes auto;

同时也可以稍微调整一下每个工作进程能够打开的文件句柄数:

shell
# 每个Worker能打开的文件描述符,最少调整至1W以上,负荷较高建议2-3W
worker_rlimit_nofile 20000;

开启CPU亲和机制

因为进程/线程数往往都会远超出系统CPU的核心数,因为操作系统执行的原理本质上是采用时间片切换机制。

而CPU亲和机制则是指将每个Nginx的工作进程,绑定在固定的CPU核心上,从而减小CPU切换带来的时间开销和资源损耗。

nginx
worker_cpu_affinity auto;

开启epoll模型及调整并发连接数

shell
events {
    # 使用epoll网络模型
    use epoll;
    # 调整每个Worker能够处理的连接数上限
    worker_connections  10240;
}

Nginx高可用

1、下载Keepalived for Linux,解压至主从机合适位置后编译(以2.2.8为例)

shell
# 解压
cd /opt/
tar -zxvf keepalived-2.2.8.tar.gz

# 编译
cd ./keepalived-2.2.8/
# prefix:keepalived安装的位置,sysconf:keepalived核心配置文件所在位置(固定)
# 如果执行报错this build will not support IPVS with IPv6. Please install libnl/libnl-3 dev libraries to support IPv6 with IPVS,通过yum -y install libnl libnl-devel解决
./configure --prefix=/opt/keepalived-2.2.8 --sysconf=/etc

make && make install

2、编写脚本

shell
# 在某个位置下创建sh文件
cd /opt/nginx-1.26.2/
vim   nginx_restart.sh


# 添加配置文件内容
#!/bin/sh
# 通过ps指令查询后台的nginx进程数,并将其保存在变量nginx_number中
nginx_number=`ps -C nginx --no-header | wc -l`
# 判断后台是否还有Nginx进程在运行
if [ $nginx_number -eq 0 ];then
    # 如果后台查询不到`Nginx`进程存在,则执行重启指令
    /usr/local/nginx/sbin/nginx -c  /usr/local/nginx/conf/nginx.conf
    # 重启后等待1s后,再次查询后台进程数
    sleep 1
    # 如果重启后依旧无法查询到nginx进程
    if [ `ps -C nginx --no-header | wc -l` -eq 0 ];then
        # 将keepalived主机下线,将虚拟IP漂移给从机,从机上线接管Nginx服务
        systemctl stop keepalived.service
    fi
fi

# 在vim时执行
:set fileformat=unix # 在vi命令里面执行,修改编码格式
:set ff # 查看修改后的编码格式


# 赋予执行权限
chmod +x  ./nginx_restart.sh

3、编辑Keepalived配置文件

主机配置文件

shell
global_defs {
    # 自带的邮件提醒服务,建议用独立的监控或第三方SMTP,也可选择配置邮件发送。
    notification_email {
        root@localhost
    }
    notification_email_from root@localhost
    smtp_server localhost
    smtp_connect_timeout 30
    # 高可用集群主机身份标识(集群中主机身份标识名称不能重复,建议配置成本机IP)
	router_id 192.168.6.100 
}

# 定时运行的脚本文件配置,下方track_script指定的名字:nginx_restart
vrrp_script nginx_restart {
    # 之前编写的nginx重启脚本的所在位置
	script "/opt/nginx-1.26.2/nginx_restart.sh" 
    # 每间隔3秒执行一次
	interval 3
    # 如果脚本中的条件成立,重启一次则权重-20
	weight -20
}

# 定义虚拟路由,VI_1为虚拟路由的标示符(可自定义名称)
vrrp_instance VI_1 {
    # 当前节点的身份标识:用来决定主从(MASTER为主机,BACKUP为从机)
	state MASTER
    # 绑定虚拟IP的网络接口,根据自己的机器的网卡配置
	interface ens33 
    # 虚拟路由的ID号,主从两个节点设置必须一样
	virtual_router_id 121
    # 填写本机IP
	mcast_src_ip 192.168.6.100
    # 节点权重优先级,主节点要比从节点优先级高
	priority 100
    # 优先级高的设置nopreempt,解决异常恢复后再次抢占造成的脑裂问题
	nopreempt
    # 组播信息发送间隔,两个节点设置必须一样,默认1s(类似于心跳检测)
	advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    # 将track_script块加入instance配置块
    track_script 
    {
        # 执行Nginx监控的脚本
		nginx_restart
    }

    virtual_ipaddress {
        # 虚拟IP(VIP),也可扩展,可配置多个。
		192.168.6.200
    }
}

从机配置文件

shell
global_defs {
    # 自带的邮件提醒服务,建议用独立的监控或第三方SMTP,也可选择配置邮件发送。
    notification_email {
        root@localhost
    }
    notification_email_from root@localhost
    smtp_server localhost
    smtp_connect_timeout 30
    # 高可用集群主机身份标识(集群中主机身份标识名称不能重复,建议配置成本机IP)
	router_id 192.168.6.110 
}

# 定时运行的脚本文件配置
vrrp_script nginx_restart {
    # 之前编写的nginx重启脚本的所在位置
	script "/opt/nginx-1.26.2/nginx_restart.sh" 
    # 每间隔3秒执行一次
	interval 3
    # 如果脚本中的条件成立,重启一次则权重-20
	weight -20
}

# 定义虚拟路由,VI_1为虚拟路由的标示符(可自定义名称)
vrrp_instance VI_1 {
    # 当前节点的身份标识:用来决定主从(MASTER为主机,BACKUP为从机)
	state BACKUP
    # 绑定虚拟IP的网络接口,根据自己的机器的网卡配置
	interface ens33 
    # 虚拟路由的ID号,主从两个节点设置必须一样
	virtual_router_id 121
    # 填写本机IP
	mcast_src_ip 192.168.6.110
    # 节点权重优先级,主节点要比从节点优先级高
	priority 90
    # 优先级高的设置nopreempt,解决异常恢复后再次抢占造成的脑裂问题
	nopreempt
    # 组播信息发送间隔,两个节点设置必须一样,默认1s(类似于心跳检测)
	advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    # 将track_script块加入instance配置块
    track_script
    {
        # 执行Nginx监控的脚本
		nginx_restart.sh
    }

    virtual_ipaddress {
        # 虚拟IP(VIP),也可扩展,可配置多个。
		192.168.6.200
    }
}

4、启动nginx,配置keepalived启动方式

shell
# 启动nginx
/usr/local/nginx/sbin/nginx

# 启动keepalived,配置后台启动等
chkconfig keepalived on
systemctl daemon-reload
systemctl enable keepalived.service
systemctl start keepalived.service

# 不需要自启动等,直接启动也行
cd /opt/keepalived-2.2.8/sbin/
./keepalived

# 其他命令:
systemctl disable keepalived.service # 禁止开机自动启动
systemctl restart keepalived.service # 重启keepalived(修改完后需要重启)
systemctl stop keepalived.service # 停止keepalived
tail -22f /var/log/messages | grep Keepalived # 查看keepalived运行时日志

5、启动

执行ip addr查看,会发现挂载了一个

6、配置结果:

关闭主机nginx后,模拟了Nginx宕机情况,等待一定时间,nginx将会被keepalived重启

关闭主机keepalived,模拟了机器断电、硬件损坏等情况,等待一定时间后,访问将会转移至从机