server 与 listen

listen 的三种形式与全部参数、http2 参数的废弃、reuseport 与 backlog,以及 server 级常用指令。

作者 David更新于 第 5 篇(共 21 篇)

listen

语法:    listen address[:port] [parameters];
         listen port [parameters];
         listen unix:path [parameters];
默认:    listen *:80 | *:8000;
上下文:  server

三种形式:地址[:端口]、纯端口、UNIX 套接字。

默认值那个 *:80 | *:8000 的写法含义是:以 root 运行时默认 80,非 root 时默认 8000(绑不了特权端口)。

常见写法

listen 80;                      # 所有 IPv4 地址的 80 端口
listen *:8000;                  # 同上,显式通配
listen 127.0.0.1:8000;          # 仅本机
listen [::]:8000;               # IPv6
listen localhost:8000;
listen unix:/var/run/nginx.sock;

http2 参数已废弃

官方文档对 listen 的 http2 参数标注:

http2 — Configure port to accept HTTP/2 connections (deprecated; use http2 directive instead)

listen 443 ssl http2; 这种写法已被官方标记为废弃(1.25.1 起分离),应改成:

listen 443 ssl;
http2 on;

原因是 http2 作为 listen 参数是端口级的,而独立的 http2 指令可以写在 http/server 级,粒度更合理——同一端口上不同 server 可以有不同的 HTTP/2 开关。

旧写法目前仍能工作,但网上绝大多数教程停留在旧形式,新配置应该用新写法。

全部参数

参数含义
default_server该 address:port 的默认服务器
ssl该端口所有连接走 TLS
http2已废弃,改用 http2 指令
quic接受 QUIC 连接(1.25.0+),HTTP/3 用
proxy_protocol该端口所有连接走 PROXY 协议
backlog=numberlisten() 的 backlog。默认 BSD/macOS 为 -1,其他为 511
reuseport每个 worker 独立 socket(SO_REUSEPORT),Linux 3.9+
bind对该 address:port 单独调 bind()
ipv6only=on|offIPV6_V6ONLY,默认 on
deferred延迟 accept(Linux TCP_DEFER_ACCEPT)
fastopen=numberTCP Fast Open 队列长度
so_keepalive=...TCP keepalive,形如 30m::10
rcvbuf= / sndbuf=socket 收发缓冲
accept_filter=FreeBSD/NetBSD 的 dataready / httpready
multipathMultipath TCP,Linux 5.6+
setfib=number路由表,仅 FreeBSD

reuseport

listen 80 reuseport;

每个 worker 拿到自己的监听 socket,由内核直接把新连接分发到各 worker。

价值:彻底消除惊群与 accept 争抢,高并发短连接下能显著提升吞吐与均衡性。这也是 accept_mutex 默认关闭的底气之一。

注意:reuseport 只需在一个 server 块的 listen 上写一次,同 address:port 的其他 server 不要重复写(会报错)。

ipv6only

listen [::]:80;                # 默认 ipv6only=on,只收 IPv6
listen [::]:80 ipv6only=off;   # 同时收 IPv4(v4-mapped)

默认 on。想用一个 socket 同时服务 v4/v6 才关掉,但更常见的做法是写两条 listen:

listen 80;
listen [::]:80;

backlog

未被 accept 的连接排队长度,默认 511。突发流量下 accept 队列打满会导致连接被拒(表现为客户端连接超时)。高并发场景可调大,但同时要抬高内核的 net.core.somaxconn——两者取较小值生效。

server_name

见 nginx 如何处理请求的四级优先级。补充几个写法:

server_name example.com www.example.com;   # 多个名字
server_name *.example.com;                 # 前置通配
server_name mail.*;                        # 后置通配
server_name ~^www(?<num>\d+)\.example\.com$;  # 正则 + 命名捕获
server_name "";                            # 匹配无 Host 的请求
server_name _;                             # 「无效名」惯例,见下

server_name _; 不是什么特殊语法。 _ 只是一个不可能与任何真实 Host 匹配的普通名字(下划线不是合法域名字符)。它常与 default_server 一起用来表达「这是兜底块」,但起作用的是 default_server,不是 _。

写成 server_name __; 或 server_name ---; 效果完全一样。

正则形式的命名捕获可以直接当变量用:

server {
    server_name ~^(?<subdomain>.+)\.example\.com$;
    root /sites/$subdomain;
}

client_max_body_size

语法:    client_max_body_size size;
默认:    client_max_body_size 1m;
上下文:  http, server, location

请求体大小上限,默认仅 1 MB。超过返回 413(Content Too Large)。

设为 0 关闭检查。

「上传文件失败/413」的头号原因就是这个 1m 默认值。改的时候注意:如果后面还有一层上游(另一个 nginx、应用服务器),每一层都要改——任何一层拒绝都会失败。

keepalive_timeout

语法:    keepalive_timeout timeout [header_timeout];
默认:    keepalive_timeout 75s;
上下文:  http, server, location
  • 第一个参数:服务端保持长连接的超时。设为 0 禁用 keep-alive。
  • 第二个参数(可选):写进响应头 Keep-Alive: timeout=N 的值。

两者可以不同——常见做法是让通告值略小于实际值,给客户端留出关闭余量:

keepalive_timeout 65s 60s;

server_tokens

语法:    server_tokens on | off | build | string;
默认:    server_tokens on;
上下文:  http, server, location

控制错误页与 Server 响应头里是否带 nginx 版本号。

值效果
onServer: nginx/1.30.4
offServer: nginx(版本隐藏,但仍暴露是 nginx)
build版本 + 构建名(1.11.10+)
string自定义(商业版,1.9.13+);空串则完全去掉 Server 头

开源版做不到彻底隐藏 Server 头——off 只去掉版本号。要完全去掉需要商业版,或用第三方模块 headers-more。

生产建议至少:

server_tokens off;

理由见 HTTP 的 Server 字段:精确版本号方便攻击者匹配已知漏洞。

一个典型 server 块

server {
    listen              443 ssl reuseport;
    listen              [::]:443 ssl;
    http2               on;

    server_name         example.com www.example.com;
    root                /var/www/example;

    client_max_body_size 20m;
    keepalive_timeout    65s 60s;
    server_tokens        off;

    ssl_certificate     /etc/ssl/example.crt;
    ssl_certificate_key /etc/ssl/example.key;

    location / {
        try_files $uri $uri/ =404;
    }
}

下一篇:location 匹配规则。

本页目录