尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

04-Nginx核心配置文件详解:全局块、http块、server块、location匹配规则

04-Nginx核心配置文件详解:全局块、http块、server块、location匹配规则 04-Nginx核心配置文件详解全局块、http块、server块、location匹配规则作者黒漂技术佬系列专栏Nginx高可用部署与三端项目实战一、nginx.conf 整体结构鸟瞰前面几篇铺垫了架构和部署这一篇啃硬骨头——配置文件。Nginx 的配置看起来像一堆花括号嵌套新手一上来就懵。其实你把它想成一棵树结构清晰得很nginx.conf │ ├── 全局块events 之前 # 进程级配置影响整个 Nginx │ ├── events 块 # 影响 Worker 进程的连接行为 │ └── http 块 # HTTP 协议相关所有 web 业务都在这里 │ ├── http 全局配置 # mime/日志/gzip/sendfile 等 │ ├── upstream 块 # 后端服务集群定义负载均衡 │ └── server 块 # 一个虚拟主机对应一个域名/端口 │ ├── server 全局配置 # listen / server_name │ └── location 块 # URL 路由匹配规则记忆口诀全局管进程events 管连接http 管协议server 管主机location 管 URL。从外到内层层收敛越往里越具体。二、全局块main blockevents之前的部分就是全局块影响整个 Nginx 进程的行为# ---- 全局块 ---- user nginx; # worker 进程运行用户 worker_processes auto; # worker 进程数auto 自动匹配 CPU 核数 worker_rlimit_nofile 65535; # worker 能打开的最大文件描述符数 error_log /var/log/nginx/error.log warn; # 错误日志路径和级别 pid /var/run/nginx.pid; # pid 文件路径逐个说明1. userWorker 进程以哪个用户身份运行。前面编译安装时我们建了个nginx无登录权限账户这里就指定用它。为什么不直接用 root——root 跑 Worker 风险太大万一 Nginx 被攻破比如老版本解析漏洞攻击者直接拿到 root 权限整个服务器沦陷。最小权限原则是 Linux 运维的底线。2. worker_processesWorker 进程数。三种写法固定数字worker_processes 4;4 核机器就写 4auto自动等于 CPU 核数推荐错误示范写大于 CPU 核数的值——多出来的 Worker 抢不到 CPU反而增加上下文切换开销为什么核数就是最优因为 Nginx 是事件驱动模型CPU 跑满时一个核一个 Worker 已经能榨干性能多开 Worker 互相抢核反而慢。3. worker_rlimit_nofileWorker 能打开的文件描述符上限。每个连接占用一个 fd设备长连接场景一台机器几万连接很常见这个值要够大65535 是底线生产常调到 100000。注意这个值不能超过操作系统ulimit -n的限制得在 systemd 服务文件里配LimitNOFILE或在/etc/security/limits.conf里调系统限制否则 Nginx 启动会报too many open files。4. error_log错误日志路径和级别。可选级别从详细到精简debug info notice warn error crit alert emerg。生产上用warn或error别用 debug——debug 日志量大到能撑爆磁盘排查问题时才临时开。三、events 块events { worker_connections 10240; # 每个 worker 最大连接数 use epoll; # 事件驱动模型Linux 用 epoll multi_accept on; # 一次 accept 多个连接 }1. worker_connections每个 Worker 能同时持有的连接数。理论最大并发 worker_processes × worker_connections。4 核机器配 10240理论并发 40960。2. use epoll事件驱动模型选择。Linux 下默认就是 epoll可以不显式写写上更明确。其他平台BSD/macOS 用 kqueue老 Linux 用 select/poll。3. multi_accept on一次accept调用尽量多接连接而不是一次一个。高并发场景开它能减少系统调用次数性能有小幅提升。四、http 块核心中的核心http 块管所有 HTTP 协议的事是配置最密集的区域。http { # ---- 1. mime 类型映射 ---- include /etc/nginx/mime.types; # 文件扩展名到 MIME 类型的映射表 default_type application/octet-stream;# 默认 MIME 类型未知扩展名 # ---- 2. 日志格式 ---- log_format main $remote_addr - $remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for; access_log /var/log/nginx/access.log main; # ---- 3. 性能优化 ---- sendfile on; # 零拷贝发送静态文件 tcp_nopush on; # 数据包攒大了再发配合 sendfile tcp_nodelay on; # 禁用 Nagle小包立即发长连接场景 keepalive_timeout 65; # 客户端长连接超时秒 keepalive_requests 1000; # 一条长连接最多复用多少次请求 # ---- 4. gzip 压缩 ---- gzip on; gzip_min_length 1k; # 小于1k不压压完反而更大 gzip_comp_level 6; # 压缩级别1-96是性价比之选 gzip_types text/plain application/json application/javascript text/css; gzip_vary on; # 加 Vary: Accept-Encoding 头支持 CDN 缓存 # ---- 5. 后端长连接 ---- proxy_http_version 1.1; proxy_set_header Connection ; # ---- 6. upstream 集群 ---- upstream order_cluster { # 负载均衡策略 least_conn; # 最少连接数优先 server 192.168.1.11:8080 weight5; # 权重5 server 192.168.1.12:8080 weight3; # 权重3 server 192.168.1.13:8080 max_fails3 fail_timeout30s; # 异常自动剔除 keepalive 32; # 到后端保持32条复用长连接 } # ---- 7. server 块虚拟主机---- server { listen 80; server_name api.cabinet.example.com; # ... location 块在下面单独讲 } }逐个把关键配置讲透sendfile零拷贝发静态文件传统发送静态文件流程磁盘→内核缓冲→用户空间read→内核缓冲write→网卡。4 次拷贝 2 次系统调用。sendfile on启用后磁盘→内核缓冲→网卡直接内核态转发。省掉用户空间来回拷贝发大文件性能提升巨大。管理后台静态资源场景必开。tcp_nopush vs tcp_nodelay这俩看起来矛盾实际配合用tcp_nopush on把响应头和响应体攒一起发减少小包数量适合 sendfile 大文件场景tcp_nodelay on禁用 Nagle 算法小包立即发适合 WebSocket/交互式长连接两个都开是常见做法静态资源走 nopush 优化长连接走 nodelay 优化。keepalive_timeout客户端到 Nginx 的 HTTP 长连接保持多久。设 65 秒意思是用户访问完一个页面后连接保留 65 秒期间再发请求不用重新握手。对移动端小程序、设备这种频繁请求场景能省掉大量 TCP 握手开销响应时间能降 30% 以上。gzip 压缩后端返回的 JSON、JS、CSS 这些文本资源压缩后能小 60-80%省带宽省加载时间。但要注意gzip_min_length 1k小于 1k 的内容压完可能更大多了 gzip 头不压gzip_comp_level 61 最快压缩比低9 最慢压缩比高6 是性价比最优gzip_types默认只压 text/html要显式加 json/js/css 等 MIME 类型图片不要压jpg/png 已经是压缩格式再 gzip 纯浪费 CPUupstream后端服务集群这是 Nginx 做负载均衡的核心。几种策略轮询默认请求按顺序轮流分给后端weightN权重轮询性能强的后端权重大least_conn最少连接数优先长连接场景更合理ip_hash同一客户端 IP 固定打到同一后端会话保持场景用但破坏负载均衡售货柜项目设备长连接场景用least_conn最合适——长连接占着连接不放按连接数分配更均衡。max_fails和fail_timeout是健康检查某后端 30 秒内失败 3 次自动剔除30 秒后再试。五、server 块一个虚拟主机server { listen 443 ssl http2; # 监听端口 协议 server_name api.cabinet.example.com; # 域名 ssl_certificate /etc/nginx/ssl/cabinet.pem; ssl_certificate_key /etc/nginx/ssl/cabinet.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; # 精确匹配根路径健康检查 location /health { return 200 ok; add_header Content-Type text/plain; } # 小程序订单 API location /mini/order/ { proxy_pass http://order_cluster/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } # 设备 WebSocket location /device/ws/ { proxy_pass http://device_ws_cluster/; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; proxy_read_timeout 3600s; } }listen监听端口。443 ssl http2表示监听 443、启用 SSL、启用 HTTP/2。HTTP/2 多路复用能让浏览器一个连接并发多个请求对小程序加载一堆小接口提升明显。server_name虚拟主机域名。Nginx 收到请求后按 Host 头匹配 server_name决定走哪个 server 块。多个 server 共用 80 端口时靠 server_name 区分这是 Nginx 一台机器托管多个站点的基础。六、location 匹配规则最容易踩坑的部分这是新手最迷糊的地方。同一个 server 里多个 location请求到底走哪个规则要背熟。1. 四种匹配修饰符location /health { ... } # 精确匹配 location /api/order/ { ... } # 前缀匹配 location ~ \.php$ { ... } # 正则匹配区分大小写 location ~* \.(jpg|png|gif)$ { .. } # 正则匹配不区分大小写 location ^~ /static/ { ... } # 优先前缀匹配匹配后不再查正则2. 匹配优先级从高到低这是命门规则记错就路由乱套1. 精确匹配 命中即停最高优先级 2. ^~ 前缀匹配 命中即停不再查正则 3. ~ / ~* 正则匹配 按配置文件中出现顺序先到先得 4. 普通前缀匹配 最长前缀胜出最低优先级举例说明匹配过程请求/static/logo.png配置里有location /static/ { ... } # A 普通前缀 location ~* \.png$ { ... } # B 正则 location ^~ /static/ { ... } # C 优先前缀匹配流程先查精确没有命中查前缀匹配含^~和普通前缀A 和 C 都匹配C 用了^~命中后直接用 C不再查正则如果 C 不存在A 命中最长前缀但因为 A 不是^~会继续查正则B 也匹配正则优先级高于普通前缀最终走 B这个流程记不住很正常记住一句口诀“先精确再优先前缀再正则最后普通前缀”。3. 精确匹配的经典用法location /health { access_log off; return 200 ok\n; }健康检查接口单独精确匹配关掉访问日志——不然每秒几次健康检查会刷爆 access.log这是生产上的常见优化。4. proxy_pass 的斜杠陷阱# 写法1带斜杠 location /mini/order/ { proxy_pass http://order_cluster/; # 请求 /mini/order/list → 后端收到 /list } # 写法2不带斜杠 location /mini/order/ { proxy_pass http://order_cluster; # 请求 /mini/order/list → 后端收到 /mini/order/list }带不带尾斜杠决定路径是否被截断。带斜杠是代理路径改写不带斜杠是纯转发保留原路径。生产上线前必须验证这一条路径错一截后端直接 404而且是那种本地能跑线上报错的诡异 bug。七、一份可作模板的生产配置示例把前面的零散拼起来下面这份可以直接当模板用user nginx; worker_processes auto; worker_rlimit_nofile 65535; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 10240; use epoll; multi_accept on; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main $remote_addr - [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent rt$request_time; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; keepalive_requests 1000; gzip on; gzip_min_length 1k; gzip_comp_level 6; gzip_types text/plain application/json application/javascript text/css; upstream order_cluster { least_conn; server 192.168.1.11:8080 weight5 max_fails3 fail_timeout30s; server 192.168.1.12:8080 weight3 max_fails3 fail_timeout30s; keepalive 32; } server { listen 443 ssl http2; server_name api.cabinet.example.com; ssl_certificate /etc/nginx/ssl/cabinet.pem; ssl_certificate_key /etc/nginx/ssl/cabinet.key; ssl_protocols TLSv1.2 TLSv1.3; location /health { access_log off; return 200 ok\n; } location /mini/order/ { proxy_pass http://order_cluster/; 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; } } }八、小结这一篇把 nginx.conf 从外到内拆了个底朝天全局块管进程user/worker_processes/error_logevents 块管连接worker_connections/epollhttp 块管协议sendfile/gzip/keepalive/upstreamserver 块管虚拟主机listen/server_namelocation 块管 URL 路由。重点讲了 location 的四种匹配修饰符和优先级口诀以及proxy_pass斜杠截断的陷阱。最后给了一份可直接套用的生产模板。后面会进入更深入的实战讲 Nginx 在三端项目里的具体落地配置和性能调优。
返回列表