跳转至

nginx#

安装Nginx#

docker安装#

docker run -d --restart=always \
--net host \
--name nginx \
-v ./nginx.conf:/etc/nginx/nginx.conf \
-v ./log:/var/log/nginx \ # log
-v ./cert:/etc/nginx/cert \ # SSL证书文件, 没有可以去掉
-v ./html:/usr/share/nginx/html \
nginx:1.24.0

​ net=host是因为懒得配端口了, 这样好一些

​ shell启动不够优雅, 建议使用docker compose

version: '3.8'
services:
  nginx:
    image: nginx:1.24.0
    container_name: nginx
    restart: always
    network_mode: host
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./logs:/var/log/nginx:rw
      - ./cert:/etc/nginx/cert:ro
      - ./html:/usr/share/nginx/html:ro # 一些html或者error.json

​ 注意:

  1. network_mode是linux专用, docker desktop没用
  2. host网络模式不是最佳实践, 如果有确定的后端编排还是一起编排比较合适

apt下载安装启动(不建议)#

为了不找不自在, 还是用docker部署吧!

​ 不建议使用apt安装, 因为会缺少很多模块, 而且版本较老

sudo apt install nginx
service nginx start # 启动nginx

​ 然后打开80端口查看情况, 如果出现nginx主页说明成功

从源码编译安装并配置SSL模块#

参考: https://developer.aliyun.com/article/766958

​ 先安装好nginx

  1. 去官网下载源码: https://nginx.org/en/download.html

建议下载Stable version

  1. 解压安装包
tar -zxvf <包的名字>
  1. 安装SSL模块

到nginx目录下, 输入

./configure --prefix=/etc/nginx --with-http_ssl_module

/ect/nginx是你的nginx安装位置, 也可以是/usr/local/nginx

如果用apt安装的话, 为/etc/nginx

如果出现 the HTTP rewrite module requires the PCRE library, 则安装:

apt-get install libpcre3 libpcre3-dev

​ 上面的命令是配置ssl模块

  1. 用make命令编译, 注意不要使用make install, 会重新安装nginx, 当然, 想重新安装也可以输入
make

这里面可能会出现errors, 不用管

如果出现了缺少包依赖的错误, 直接安装即可, 这里提供一些可能出现的:

sudo apt-get install libpcre3 libpcre3-dev # 缺少pcre
sudo apt-get install openssl libssl-dev # 缺少openssl
sudo apt-get install zlib1g-dev # 缺少zlib
  1. 将obj的文件复制到nginx上覆盖原来的文件

  2. 查看是否安装成功

nginx -V

如果出现**--with-http_ssl_module**则成功

nginx文件树#

nginx配置文件在/etc/nginx中

nginx启动时加载nginx.conf

其中有两行:

include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;

意思是引用了这两个目录下的所有文件

其中, sites-enabled 是 sites-available的链接, 把想启动的配置放在这里即可, 同理当想临时关闭某个站点时, 把sites-enabled对应的链接删去即可

当然,也可以在conf.d中放配置文件, 不过**不建议**

注意: 由于 sites-enabled 有默认的nginx界面,所有访问均会导向默认界面 所以要使我们的配置生效, 需要把sites-enabled的链接删去

nginx架构#

nginx 一把梭!(超详细讲解+实操)

配置模板开箱即用#

​ 注意, 需要使用上面的docker-compose.yaml启动, 目录下放这个配置文件(nginx.conf)

user nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice; # notice级别
pid        /var/run/nginx.pid; # nginx进程id


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    # --------------------日志 配置---------------------
    # 格式: 
    # remote_addr - remote_user [time_local] "request" status body_bytes_sent "http_referer" "http_user_agent" "http_x_forwarded_for"
    # 远程地址       用户名      时间            请求     状态   响应大小         来源网址         用户UA          代理地址

    # log_format  debug  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';
    log_format  debug  ' $remote_user [$time_local]  $http_x_Forwarded_for $remote_addr  $request '  
                      '$http_x_forwarded_for '  
                      '$upstream_addr '  
                      'ups_resp_time: $upstream_response_time '  
                      'request_time: $request_time'; 
    access_log  /var/log/nginx/access.log  debug; # debug级别

    # --------------------网络 配置---------------------
    sendfile        on; # 零拷贝传输(内核和用户)
    #tcp_nopush     on; # 优化网络传输,减少网络报文, 把多个小包合并成一个大包发送
    keepalive_timeout  65; # 保持长连接的时间, 如果有客户端在65s内没有任何请求, 则关闭连接

    # --------------------压缩 配置---------------------
    # 开启/关闭 压缩机制
    gzip on;
    # 根据文件类型选择 是否开启压缩机制
    gzip_types text/plain application/javascript text/css application/xml text/javascript image/jpeg image/jpg image/gif image/png  application/json;
    # 设置压缩级别,越高资源消耗越大越耗时,但压缩效果越好
    gzip_comp_level 5;
    # 设置是否携带Vary:Accept-Encoding 的响应头
    gzip_vary on;
    # 处理压缩请求的 缓冲区数量和大小
    gzip_buffers 32 64k;
    # 对于不支持压缩功能的客户端请求 不开启压缩机制
    gzip_disable "MSIE [1-6]\."; # 比如低版本的IE浏览器不支持压缩
    # 设置压缩功能所支持的HTTP最低版本
    gzip_http_version 1.1;
    # 设置触发压缩的最小阈值
    gzip_min_length 2k;
    # off/any/expired/no-cache/no-store/private/no_last_modified/no_etag/auth 根据不同配置对后端服务器的响应结果进行压缩
    gzip_proxied any;

    # --------------------缓存 配置---------------------
    # 指定缓存存放目录为/usr/local/nginx/test/nginx_cache_storage,并设置缓存名称为mycache,大小为64m, 1天未被访问过的缓存将自动清除,磁盘中缓存的最大容量为1gb
    proxy_cache_path /usr/local/nginx/test/nginx_cache_storage levels=1:2 keys_zone=mycache:64m inactive=1d max_size=1g;

    # --------------------限流 配置---------------------
    # 对请求速率限流
    #limit_req_zone $binary_remote_addr zone=myRateLimit:10m rate=5r/s;
    # 对请求连接数限流
    limit_conn_zone $binary_remote_addr zone=myConnLimit:10m; 

    # --------------------重定向 配置---------------------
    server {
      listen 80;
      charset utf-8;
      server_name www.example.com example.com;
      return 301 https://$server_name$request_uri; # 301永久重定向到https
    }

    # --------------------负载均衡 配置---------------------
    # upstream backendserver {
    #     server 172.30.128.64:8081 fail_timeout=60s max_fails=3; # 60秒内 如果请求某一个应用失败3次,则认为该应用宕机 时间到后再有请求进来继续尝试连接宕机应用且仅尝试 1 次,如果还是失败,则继续等待 60 秒...以此循环,直到恢复
    #     server 172.30.128.64:8082;
    #     server 172.30.128.64:8083 backup; # 设置8083位备机
    # }
    upstream backendserver {
        server 127.0.0.1:9000;
    }

    # --------------------HTTPS 配置---------------------
    server {
        #SSL 默认访问端口号为 443
        listen 443 ssl; 
        #填写绑定证书的域名 
        server_name www.example.com example.com;
        #请填写证书文件的相对路径或绝对路径
        ssl_certificate /etc/nginx/cert/xxx.pem; 
        #请填写私钥文件的相对路径或绝对路径
        ssl_certificate_key /etc/nginx/cert/xxx.key;
        #停止通信时,加密会话的有效期,在该时间段内不需要重新交换密钥
        ssl_session_timeout 5m;
        #服务器支持的TLS版本
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; 
        #请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; 
        #开启由服务器决定采用的密码套件
        ssl_prefer_server_ciphers on;

        # # 指定 username 参数中只要有字母 就不走nginx缓存  
        # if ($arg_username ~ [a-z]) {
        #     set $cache_name "no cache";
        # }
        # # 前端页面资源
        # location  /page {
        #   alias  '/usr/local/nginx/test/static/';
        #   index index_page.html; 

        #   allow all;
        # }
        # # 后端服务
        # location  /interface {
        #   proxy_pass http://backendserver/;

        #   # 指定哪些错误状态才执行 重试
        #   proxy_next_upstream error timeout http_500 http_502 http_503 http_504 http_404;


        #   # 使用名为 mycache 的缓存空间
        #   proxy_cache mycache;
        #   # 对于200 206 状态码的数据缓存2分钟
        #   proxy_cache_valid 200 206 1m;
        #   # 定义生成缓存键的规则(请求的url+参数作为缓存key)
        #   proxy_cache_key $host$uri$is_args$args;
        #   # 资源至少被重复访问2次后再加入缓存
        #   proxy_cache_min_uses 3;
        #   # 出现重复请求时,只让其中一个去后端读数据,其他的从缓存中读取
        #   proxy_cache_lock on;
        #   # 上面的锁 超时时间为4s,超过4s未获取数据,其他请求直接去后端
        #   proxy_cache_lock_timeout 4s;
        #   # 对于请求参数中有字母的 不走nginx缓存
        #   proxy_no_cache $cache_name; # 判断该变量是否有值,如果有值则不进行缓存,没有值则进行缓存
        #   # 在响应头中添加一个缓存是否命中的状态(便于调试)
        #   add_header Cache-status $upstream_cache_status;

        #   limit_conn myConnLimit 12;

        # # limit_req zone=myRateLimit burst=5  nodelay;
        # # limit_req_status 520;
        # # limit_req_log_level info;
        # } 

        # # 后端服务
        # location  /interface2 {
        #   proxy_pass http://backendserver;
        #   # 使用名为 mycache 的缓存空间
        #   proxy_cache mycache;
        #   # 对于200 206 状态码的数据缓存2分钟
        #   proxy_cache_valid 200 206 1m;
        #   # 定义生成缓存键的规则(请求的url+参数作为缓存key)
        #   proxy_cache_key $host$uri$is_args$args;
        #   # 资源至少被重复访问2次后再加入缓存
        #   proxy_cache_min_uses 3;
        #   # 出现重复请求时,只让其中一个去后端读数据,其他的从缓存中读取
        #   proxy_cache_lock on;
        #   # 上面的锁 超时时间为4s,超过4s未获取数据,其他请求直接去后端
        #   proxy_cache_lock_timeout 4s;
        #   # 对于请求参数中有字母的 不走nginx缓存
        #   proxy_no_cache $cache_name; # 判断该变量是否有值,如果有值则不进行缓存,没有值则进行缓存
        #   # 在响应头中添加一个缓存是否命中的状态(便于调试)
        #   add_header Cache-status $upstream_cache_status;

        #   limit_conn myConnLimit 12;

        # # limit_req zone=myRateLimit burst=5  nodelay;
        # # limit_req_status 520;
        # # limit_req_log_level info;
        # } 

    }

    # include /etc/nginx/conf.d/*.conf;
}

配置示例#

修改错误返回值#

​ 有些时候希望返回的不是service unavailable, 希望返回某段json, 可以这样设置

​ /50x.json是返回的json内容, 也可以返回其他网页

server {
    ...
    error_page 5xx /5xx.json;
    location = /5xx.json {
        root /usr/share/nginx/html;
        internal; # 保证这个路径只能内部请求
    }
    ...
}

websocket配置#

​ websocket比较特殊, 需要加入upgrade和connection

location /api/ws/ {
    proxy_redirect off;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_pass       http://127.0.0.1:9000/api/ws/;
}

SSE配置#

​ SSE配置需要去掉缓存, 不然SSE失效

location /api/sse {
    proxy_redirect off;
    proxy_pass         http://127.0.0.1:9000/api/sse;
    proxy_buffering off; # 去掉缓存
}

请求速率限流#

http{
    ...
    # 对请求速率限流
    limit_req_zone $binary_remote_addr zone=myRateLimit:10m rate=5r/s;

    server{
        location /api {
            ...
            limit_req zone=myRateLimit burst=5 nodelay;
            limit_req_status 520; # 返回码
            limit_req_log_level info;
        }
    }
}
  • $binary_remote_addr: 基于客户端IP做限流

zone=myRateLimit:10m 指myRateLimit作为内存区域, 大小10M(16万)IP地址

rate=5r/s 指相同IP每秒最多请求5次(200ms一个请求)

  • burst=5: 削峰, 如果峰值超过rate(比如说200ms来了两个), 则会用一个大小为burst的队列削峰, 然后慢慢根据rate速率处理, 多余的直接503

  • nodelay: 如果是nodelay, 则burst削峰会立即处理, 而不是每200ms取一个

nodelay立即处理, 那么nginx怎么控制并发? 是通过处理但不释放的方式控制. 后面的请求会阻塞

一般建议burst和nodelay一起用, 可以处理突发流量

请求连接数限流#

http{
    # 针对ip  对请求连接数限流
    ...
    limit_conn_zone $binary_remote_addr zone=myConnLimit:10m; 
    ...

    server{
       ...
       limit_conn myConnLimit 12;
    }
}

https/SSL#

​ 注意需要http_ssl_module

server {
    #SSL 默认访问端口号为 443
    listen 443 ssl; 
    #填写绑定证书的域名 
    server_name www.hzznb-xzll.xyz hzznb-xzll.xyz; 
    #请填写证书文件的相对路径或绝对路径
    ssl_certificate 证书路径;
    #请填写私钥文件的相对路径或绝对路径
    ssl_certificate_key 私钥路径;
    #停止通信时,加密会话的有效期,在该时间段内不需要重新交换密钥
    ssl_session_timeout 5m;
    #服务器支持的TLS版本
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; 
    #请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; 
    #开启由服务器决定采用的密码套件
    ssl_prefer_server_ciphers on;
}

ssl_certificate: .pem或者/csr文件

ssl_certificate_key: 一般是.key文件

80重定向到443#

server_name www.hzznb-xzll.xyz hzznb-xzll.xyz;
# 重定向到目标地址
return 301 https://$server_name$request_uri;

压缩#

http {
    # 开启/关闭 压缩机制
    gzip on;
    # 根据文件类型选择 是否开启压缩机制
    gzip_types text/plain application/javascript text/css application/xml text/javascript image/jpeg image/jpg image/gif image/png  application/json;
    # 设置压缩级别,一共9个级别  1-9   ,越高资源消耗越大 越耗时,但压缩效果越好,
    gzip_comp_level 5;
    # 设置是否携带Vary:Accept-Encoding 的响应头
    gzip_vary on;
    # 处理压缩请求的 缓冲区数量和大小
    gzip_buffers 32 64k;
    # 对于不支持压缩功能的客户端请求 不开启压缩机制
    gzip_disable "MSIE [1-6]\."; # 比如低版本的IE浏览器不支持压缩
    # 设置压缩功能所支持的HTTP最低版本
    gzip_http_version 1.1;
    # 设置触发压缩的最小阈值
    gzip_min_length 2k;
    # off/any/expired/no-cache/no-store/private/no_last_modified/no_etag/auth 根据不同配置对后端服务器的响应结果进行压缩
    gzip_proxied any;
} 

负载均衡#

配置热备#

upstream mysvr { 
    server 192.168.10.121:3333 max_fails=2 fail_timeout=2;
    server 192.168.10.122:3333 backup;
}
  • max_fails: 允许请求失败的最大次数, 超过时返回proxy_next_upstream模块定义的错误
  • fail_timeout: 经历了max_fails失败后暂停服务的时间

轮询(round-robin)#

upstream mysvr { 
    server 127.0.0.1:7878;
    server 192.168.10.121:3333;       
}
  • 请求会分别发送到两个服务器, A-B-A-B......
upstream mysvr { 
    server 127.0.0.1:7878 weight=1;
    server 192.168.10.121:3333 weight=2;
}
  • 给不同服务器设置权重, 上面会变成A-B-B-A-B-B......

ip_hash#

upstream mysvr { 
    server 127.0.0.1:7878; 
    server 192.168.10.121:3333;
    ip_hash;
}
  • 会让相同客户端请求相同的服务器, 实现session等的共享