跳转至

Nginx

Nginx 的配置文件

nginx 配置文件为 nginx.conf,可以使用 nginx -t 检查文件位置

配置文件结构

# 全局块
worker_processes 1;

events {
    # events块
}
http {
    # http块
    server {
        # server块
        location / {
            # location块
        }
    }
}

全局块

包含 nginx 服务其的整体配置

# 指定运⾏Nginx服务器的⽤户,只能在全局块配置
# 将user指令注释掉,或者配置成nobody的话所有⽤户都可以运⾏
# user [user] [group]
# user nobody nobody;
user nginx;

# 指定⽣成的worker进程的数量,也可使⽤⾃动模式,只能在全局块配置
worker_processes 1;

# 错误⽇志存放路径和类型
error_log /var/log/nginx/error.log warn;

# 进程PID存放路径
pid /var/run/nginx.pid;

events 块

events {
    # 指定使⽤哪种⽹络IO模型,只能在events块中进⾏配置
    use epoll

    # 每个worker process允许的最⼤连接数
    worker_connections 1024;
}

http 块

http {
    # nginx 可以使⽤include指令引⼊其他配置⽂件
    include /etc/nginx/mime.types;

    # 默认类型,如果请求的URL没有包含⽂件类型,会使⽤默认类型
    default_type application/octet-stream; # 默认类型

    # 开启⾼效⽂件传输模式
    sendfile on;

    # 连接超时时间
    keepalive_timeout 65;

    # access_log ⽇志存放路径和类型
    # 格式为:access_log <path> [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
    access_log /var/log/nginx/access.log;

    # upstream 指令⽤于定义⼀组服务器,⼀般⽤来配置反向代理和负载均衡
    upstream www.example.com {
        # ip_hash指令⽤于设置负载均衡的⽅式,ip_hash表示使⽤客户端的IP进⾏hash,
        # (这样可以保证同⼀个客户端的请求每次都会分配到同⼀个服务器,解决了session共享的问题)
        ip_hash;
        # weight ⽤于设置权重,权重越⾼被分配到的⼏率越⼤
        server 192.168.50.11:80 weight=3;
        server 192.168.50.12:80;
        server 192.168.50.13:80;
    }

    upstream backend {
        server 127.0.0.1:8000;
        server 127.0.0.1:8001;
        server 127.0.0.1:8002;
    }

    server {
        listen 80;
        server_name localhost;

        location /app {
            proxy_pass http://backend; # 和 upstream 中的命名相同
        }
    }
}

server 块

作为 http 块的子块,用于配置虚拟主机。一个 http 块可以包含多个 server 块,每个 server 块即一个虚拟主机

server {
    # 监听配置
    listen 80;  # 监听所有IP的80端口请求

    # 服务器名称
    server_name *.example.com; # 可以匹配(处理)多个域名,这里使用通配符匹配

    # 路由配置
    location / {
        root /usr/share/nginx/html;  # 设置根目录
        index index.html index.htm;   # 设置默认文件
    }

    location = / {  # 精确匹配请求
        root /usr/share/nginx/html;
        index index.html index.htm;
    }

    location ^~ /images/ {  # 前缀匹配
        root /usr/share/nginx/html;
    }

    location ~ \.(gif|jpg|jpeg)$ {  # 正则匹配(区分大小写)
        root /usr/share/nginx/html;
    }

    location ~* \.(gif|jpg|jpeg)$ {  # 正则匹配(不区分大小写)
        root /usr/share/nginx/html;
    }

    location !~ \.(gif|jpg|jpeg)$ {  # 反向匹配(区分大小写)
        root /usr/share/nginx/html;
    }

    location !~* \.(gif|jpg|jpeg)$ {  # 反向匹配(不区分大小写)
        root /usr/share/nginx/html;
    }

    # 错误页面配置
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
        root /usr/share/nginx/html;
    }
}

https 配置

https 配置需要使用到 ssl 证书,在腾讯云/阿里云等上可以申请到 ssl 证书,证书申请完成后,会得到密钥文件和证书文件。

也可以通过 openssl 生成一个自签名的证书,可以得到两个文件:

这里生成的证书是没有经过 ca 机构验证的,浏览器可能提示不安全

  • private.key
  • cacert.pem
# http 请求自动转换,永久重定向
server {
    listen 80;
    server_name localhost;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl;
    server_name localhost;

    # 证书文件名称
    ssl_certificate /opt/homebrew/etc/nginx/cacert.pem;

    # 证书私钥文件名称
    ssl_certificate_key /opt/homebrew/etc/nginx/private.key;

    # ssl验证配置
    ssl_session_timeout 5m;  # 缓存有效期

    # 安全链接可选的加密协议
    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;

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

Nginx 架构

nginx master 进程通过 IO 多路复用(在 events 块中可以配置,如 use epoll),监控来自客户端的连接,并将对应连接的 fd 分配给空闲的 worker(基于操作系统的调度算法),最终由 worker 来处理转发 http 请求

image-20250823204914231

nginx 进程间的通信方式:

  1. 共享内存:worker 之间可以通过 shared_dict 共享内存块进行通信,即多个 worker 对同一个内存块进行读写操作

    openresty 提供了ngx.shared.DICT 的 get() 和 set() 两种原子操作 api,其底层实现属于 ngx_http_lua_module

  2. 信号量:master 与 worker 间最常见通信方式是通过 Unix 信号。例如:

    • 主进程向工作进程发送信号:
      • SIGTERM:用于终止 worker 进程。
      • SIGUSR1:主进程通过发送 SIGUSR1 信号来平滑地重载配置文件。
      • SIGUSR2:启用新的配置文件,常用于升级或滚动重启操作。主进程会向现有工作进程发送该信号,平滑地替换工作进程。
    • 工作进程向主进程发送信号:
      • 工作进程在处理请求时,如果出现异常或者需要退出,它会通过发送 SIGTERM 信号来通知主进程。

OpenResty 中的 Lua 协程

OpenResty 是 "enhanced nginx",在 nginx 的基础上提供了 LuaJit 即时编译,同时提供了一系列的 AOP 功能:

image-20250823210601140

在 Nginx 中:

  1. 每个请求是一个协程:Nginx 为每个请求创建一个独立的 Lua 协程
  2. 定时器回调也是协程:当定时器触发时,Nginx 会为回调函数创建一个新的协程来执行它
  3. 协程隔离:这个协程独立于任何请求协程,有自己的执行上下文
  • 所有协程都运行在同一个线程
  • 一个 worker 进程通常绑定到一个 CPU 核心
  • 协程之间是协作式调度,不是抢占式

ngx.worker.id() 为 0 的是第一个 worker 进程。Master 进程根本不参与请求处理,也不会执行 Lua 代码。

consul-template 上游服务模板配置

upstream store {
    {{range service "store"}}server {{.Address}}:{{.Port}} max_fails=2 fail_timeout=2s;
    {{else}}server 127.0.0.1:65535 down; # force a 502{{end}}
    keepalive 200;
}
  • {{range service "store"}} 为 Consul 模板语法,动态遍历名为 store 的服务在 Consul 服务注册表中的所有实例。每个实例会生成一行 server 配置

    • server {{.Address}}:{{.Port}} 将服务的 ip 地址和端口填充到 Nginx 配置中,
    • max_fails=2 fail_timeout=2 表示 2 秒内若请求失败 2 次,标记该服务器为暂不可用;被标记为不可用后,两秒内不再分配请求给他,之后重新尝试
  • {{else}} 表示如果 consul 中没有发现任何 store 服务实例,则生成一个 强制返回 502 错误的备用配置

    • server 127.0.0.1:65535 down 表示指向本地无效端口,并标记为 down,确保 Nginx 直接返回 502 错误
  • keepalive 200

    启用与后端服务的长连接。200 表示每个 Nginx worker 最多保持 200 个空闲长连接

location /title/ {  # For HTTP API
    lua_code_cache on;
    access_by_lua_file /usr/local/openresty/lua/check.lua;
    log_by_lua_file /usr/local/openresty/lua/counter.lua;
    proxy_next_upstream off;
    proxy_pass http://title/title_svr/;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $http_x_forwarded_for;
    proxy_set_header X-Real-IP $http_x_real_ip;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
}