返回归档
🎐技术分享

Nginx

文章目录

Nginx 的设计哲学是事件驱动 + 异步非阻塞 + 模块化,这让它在单机上轻松处理数十万并发连接,内存占用极低,CPU 利用率极高。

进程模型(Master + Worker + 辅助进程)

Nginx 启动后会产生以下进程:

image

  • Master 进程(1 个,通常 root 启动)
    • 读取、解析、校验 nginx.conf
    • 根据配置 fork 出 Worker 进程
    • 绑定监听端口(listen)
    • 管理 Worker:监控存活、优雅 reload、平滑升级、接收信号(HUP、TERM 等)
    • 不处理任何客户端请求,只做“管理者”角色
    • reload 时:启动新 Worker 加载新配置 + 新 Lua 代码,旧 Worker 优雅退出(继续处理已有连接)
  • Worker 进程(默认等于 CPU 核数,可手动设置 worker_processes auto;
    • 每个 Worker 是单线程的事件循环(event loop)
    • 使用操作系统最高效的 I/O 多路复用机制:
      • Linux → epoll
      • BSD/macOS → kqueue
      • Windows → IOCP
    • 所有连接(监听 socket + 已建立连接)都在同一个线程里通过事件通知异步处理
    • 一个 Worker 可以同时持有几万到几十万连接(取决于 worker_connections
  • 辅助进程(可选,由 Master 启动)
    • Cache Loader:Nginx 启动时把磁盘上的缓存元数据加载到内存(只运行一次)
    • Cache Manager:定期清理过期缓存文件、检查磁盘空间
    • (OpenResty 中还可能有 Lua JIT 相关辅助进程)

事件驱动异步非阻塞机制(核心竞争力)

  • 每个 Worker 只用一个线程,通过 epoll 等监听成千上万的文件描述符(fd)。
  • 当某个连接有事件(可读、可写、超时、关闭)时,内核通知 Worker,Worker 立刻切换处理。
  • 网络 I/O、磁盘 I/O、后端代理等全部异步:不会阻塞 Worker 线程。
  • 这就是 Nginx 能同时服务百万连接的原因——没有上下文切换开销,没有线程争抢锁。

模块化架构

Nginx 几乎所有功能都由模块实现,编译时可静态/动态加载:

  • 核心模块:events、http、stream、mail 等
  • HTTP 模块:ngx_http_core_module、ngx_http_proxy_module、ngx_http_upstream_module、ngx_http_ssl_module、ngx_http_gzip_module…
  • 第三方模块:OpenResty 的 LuaJIT、lua-resty-*、ngx_lua 等
  • Lua 代码(content_by_lua_file、access_by_lua 等)其实是运行在 ngx_lua 模块的上下文里,reload 时新 Worker 会重新加载 Lua 脚本(结合你之前问的 Lua 热更新问题)。

配置加载与零宕机 reload(与 Lua 结合)

  • Master 读取 nginx.conf → 解析所有块 → fork 新 Worker
  • 新 Worker 加载新配置 + 重新编译缓存所有 Lua 代码
  • 旧 Worker 停止接受新连接,但处理完手中所有请求后才退出 → Lua 修改后 reload 完全零宕机,正在进行的连接不会断开(除非你设置了很短的 worker_shutdown_timeout)

Nginx 配置结构与主要常用字段参数

Nginx 配置是分层块结构,从外到内层层继承(内层可覆盖外层):

main(全局)
├── events { ... }
├── http {
│   ├── upstream { ... }
│   ├── server {          ← 虚拟主机
│   │   ├── listen
│   │   ├── server_name
│   │   └── location / {  ← 匹配 URI
│   │       ├── proxy_pass
│   │       ├── proxy_set_header
│   │       └── ...
│   │   }
│   └── ...
}
└── stream { ... }   ← TCP/UDP 代理(可选)

最常用参数分类

全局 / 进程相关(main 上下文)

参数 作用 推荐生产值
worker_processes Worker 数量 auto(等于 CPU 核数)
worker_rlimit_nofile 每个 Worker 最大打开文件数 65535 或更高
worker_connections 每个 Worker 最大连接数 16384 ~ 65535
worker_shutdown_timeout 优雅退出超时(旧 Worker) 10s

events 块(事件机制)

events {
    use epoll;                    # Linux 默认最好
    worker_connections 32768;
    multi_accept on;              # 一次 accept 多个连接
}

http 块(HTTP 相关全局设置)

参数 作用 常用值
sendfile on 零拷贝发送静态文件 on
tcp_nopush on 结合 sendfile,减少小包 on
tcp_nodelay on 实时性要求高的场景 on
keepalive_timeout 客户端 keep-alive 超时 65s
client_max_body_size 最大上传大小 100m
proxy_cache_path 定义缓存目录(生产必配) /var/cache/nginx levels=1:2 keys_zone=…

server 块(虚拟主机)

参数 作用 示例
listen 监听端口 + 协议 443 ssl http2; 80;
server_name 域名匹配 example.com www.example.com;
ssl_certificate / ssl_certificate_key HTTPS 证书 /path/to/fullchain.pem;

location 块(最常用转发配置)

location /api/ {
    proxy_pass <http://backend>;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_buffering on;           # 静态接口开,SSE 关
    proxy_read_timeout 60s;
}

upstream 块(负载均衡)

upstream backend {
    least_conn;                   # 或 ip_hash, hash $arg_token consistent;
    server backend1:8080 weight=5;
    server backend2:8080 max_fails=3 fail_timeout=30s;
    keepalive 32;                 # 重要!后端连接池
}