# 通信协议
# 关于 TCP
# keepalive
:用于控制 Nginx 到 upstream 的 TCP 长连接。
可用范围:upstream
例:
keepalive 8; # 启用长连接,并限制每个 worker 保持的空闲连接数,但并不限制长连接总数 # keepalive_requests 1000; # 限制每个长连接可以发送的请求数。如果超过,则关闭 TCP 连接 # keepalive_time 1h; # 限制每个长连接的存在时间。如果超过,则在当前 HTTP 请求结束后关闭 TCP 连接 # keepalive_timeout 60s; # 限制每个长连接的空闲时间。如果超过,则关闭 TCP 连接
Nginx 关于 TCP 长连接的配置:
- 被 HTTP 客户端访问时,Nginx 作为服务器默认启用 keepalive 。因此会保留 TCP 长连接,直到客户端主动关闭连接,或者达到 keepalive_timeout 等限制。
- 直接用 proxy_pass 反向代理时,Nginx 作为客户端默认禁用 keepalive 。建议先定义 upstream ,再用 proxy_pass 反向代理,从而启用 keepalive ,提高效率。
例:启用 Nginx 到 upstream 的长连接
upstream backend { server 127.0.0.1:80; keepalive 8; } server { listen 80; location / { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Connection ''; } }
# send_timeout
:限制发送响应报文时,写操作中断的超时时间。
- 可用范围:http、server、location
- 默认值:
send_timeout 60s;
- 如果超过该值,关闭 TCP 连接。
- timeout 之类的参数取值过大时容易遭受 DDOS 攻击,取值过小时对网速较慢的客户端不友好。
# sendfile
:通过 Linux sendfile() 零拷贝技术,提高发送本机文件的速度。
- 可用范围:http、server、location
- 默认值:
sendfile off;
# tcp_nodelay
:TCP 发送缓冲区中一旦有数据,就立即发出 TCP 包。
- 可用范围:http、server、location
- 默认值:
tcp_nodelay on;
- 仅在 TCP 长连接中有效。这样会增加网络 I/O 量,但是能减少通信延迟。
# tcp_nopush
:TCP 发送缓冲区中有数据时先不发送,而是等满足 TCP 包最大段大小(Maximum Segment Size ,MSS)时才发送。
- 可用范围:http、server、location
- 默认值:
tcp_nopush off;
- 仅在 sendfile 模式中有效。这样能降低网络 I/O 量,不容易阻塞网络。
- 如果同时启用 tcp_nodelay ,tcp_nopush ,则最后一个 TCP 包采用 tcp_nodelay ,其它 TCP 包采用 tcp_nopush 。
# 关于 HTTP
# gzip
:以 gzip 格式压缩响应报文 body 。
- 可用范围:http、server、location
- 例:
gzip on; # 是否启用 gzip ,默认为 off # gzip_buffers 16 8k; # 设置 gzip 缓冲区的数量、大小。默认大小等于一个内存页 gzip_comp_level 1; # 压缩率,取值为 1~9 。默认为 1 ,压缩率最低,CPU 负载也最小 gzip_http_version 1.1; # 只压缩指定协议以上的响应报文,避免客户端版本过老二不能解析 gzip 报文。默认为 HTTP/1.1 gzip_min_length 1k; # 限制只压缩指定大小以上的响应报文,默认为 20 gzip_proxied any; # 压缩 proxy_pass 哪些类型的响应报文。默认为 off gzip_types text/plain text/javascript text/css text/xml application/json application/javascript; # 默认只压缩 text/html 类型的响应报文,这里增加其它类型 gzip_vary on; # 是否在响应头中加入 Vary: Accept-Encoding ,告诉客户端这是 gzip 报文。默认为 off
- 开启 gzip 压缩能大幅减小响应体积,提高网页加载速度,但是会增加 Nginx 的 CPU 负载。
- 文本类型的响应容易压缩,而图片、视频不容易压缩,因为本身已经被压缩了。
# add_header
:用于添加响应报文的 header 。
- 可用范围:http、server、location
- 语法:
add_header name value [always];
- 该指令可以多次使用。
- 默认当响应报文的状态码属于
200, 201, 204, 206, 301, 302, 303, 304, 307, 308
时,才添加 header 。- 如果声明了 always ,则无论状态码是什么,都会添加 header 。
- 默认如果当前级别没有定义任何 add_header 指令,则继承上一级别的 add_header 指令。
- 例:
location /api { add_header Content-Type 'application/json; charset=utf-8'; return 200 '{"code": 200, "msg": "请求成功"}'; }
# charset
:用于在响应报文的 Content-Type 中加入 charset 。
- 可用范围:http、server、location
- 默认值:
charset off;
- 例:
charset utf-8;
# types
:用于定义 MIME 类型与文件扩展名(不区分大小写)的映射关系。
- 可用范围:http、server、location
- 默认值:
types { text/html html; image/gif gif; image/jpeg jpg; }
- Nginx 会根据该映射关系设置响应报文头部中 Content-Type 的值。比如发送一个扩展名为 html 的文件时,就设置
Content-Type: text/html
。 - /etc/nginx/mime.types 文件中通过 types 指令记录了很多 MIME 类型与文件扩展名的映射关系。
# default_type
:设置响应报文头部中 Content-Type 的默认值。
- 可用范围:http、server、location
- 默认值:
default_type text/plain;
# client_*
:关于接收 HTTP 请求报文的配置参数。
- 可用范围:http、server
- 默认值:
client_header_buffer_size 1k; # 接收每个请求报文 headers 时,分配的一个内存缓冲区的大小。如果超出容量限制,则采用 large_client_header_buffers 缓冲区 large_client_header_buffers 4 8k; # 用于接收大型请求报文 headers 的一组内存缓冲区,最大数量为 4 ,每个体积为 8k 。如果超出容量限制,则拒绝接收,返回响应报文 414 或 400 client_header_timeout 60s; # 接收请求报文 headers 的超时时间。如果超时,则返回响应报文:408 Request Time-out client_body_buffer_size 16k; # 接收每个请求报文 body 时,分配的一个内存缓冲区的大小。如果超出容量限制,则写入 client_body_temp_path 目录下的临时文件,并记录 warn 日志: a client request body is buffered to a temporary file client_body_temp_path /tmp/nginx/client_temp 1 2; client_body_timeout 60s; # 接收请求报文 body 时,读操作中断的超时时间。如果超时,则返回响应报文:408 Request Time-out client_max_body_size 1m; # 限制请求报文 body 的最大体积。如果超出限制,则拒绝接收,返回响应报文:413 Request Entity Too Large 。设置成 0 则无限制
- Nginx 接收每个请求报文时,会为 headers、body 分别分配一个内存缓冲区。
- 如果接收的数据超出了内存缓冲区的容量限制,则拒绝接收,或者暂存到临时文件。
- 处理完请求之后,会立即释放内存缓冲区。
- 例:
client_body_buffer_size 1m; # 当请求报文的 body 较大时,可选调大该参数,避免写入临时文件而拖慢速度 client_max_body_size 1g; # 当请求报文的 body 较大时,必须调大该参数,否则会拒绝请求。比如客户端需要通过 POST 请求上传一个大型文件
- Nginx 接收每个请求报文时,会为 headers、body 分别分配一个内存缓冲区。
# 关于缓存
# expires
:设置响应报文的缓存过期时间。
- 可用范围:http、server、location
- 启用 expires 指令时,如果响应报文的状态码属于 200, 201, 204, 206, 301, 302, 303, 304, 307, 308 ,则会添加响应头 Expires、Cache-Control 。
- 例:
expires off; # 默认值,禁用 expires 指令 expires epoch; # 不使用缓存。这会设置 Expires: "Thu, 01 Jan 1970 00:00:01 GMT"; Cache-Control: "no-cache" expires max; # 最长缓存。这会设置 Expires: "Thu, 31 Dec 2037 23:55:55 GMT"; Cache-Control: "max-age=315360000" expires 10m; # 过期时间为 10m 之后 expires modified 10m; # 过期时间为文件的最后修改时间 + 10m
location / { root /www/; # HTML 文件通常会变化,因此不使用缓存 if ( $uri ~* \.html$ ){ expires epoch; } # 设置静态文件的缓存 if ( $uri ~* \.(js|css|jpe?g|png|gif|ico|svg)$ ){ expires 7d; } }
# etag
:是否添加响应头 etag 。
- 可用范围:http、server、location
- 例:
etag on; # 默认值 etag off;
- 因为计算文件哈希值的开销较高,Nginx 是根据文件的 last_modified 时间和 content_length 长度生成 etag 。
# if_modified_since
:设置处理请求头 If-Modified-Since 的方式。
- 可用范围:http、server、location
- 例:
if_modified_since exact; # 默认值,要求文件的 last_modified 时间等于 If-Modified-Since ,才命中缓存,返回 304 报文 if_modified_since before; # 只要文件的 last_modified 时间小于等于 If-Modified-Since ,就返回 304 报文 if_modified_since off; # 忽略请求头 If-Modified-Since
# 关于 SSL
# ssl_*
:关于 HTTPS 协议的配置参数。
- 可用范围:http、server
- 例:
server { listen 443 ssl; # 监听时采用 ssl 协议 server_name localhost; ssl_certificate /ssl/cert.crt; # SSL 证书 ssl_certificate_key /ssl/cert.key; # SSL 私钥 ssl_protocols TLSv1.2 TLSv1.3; # 设置可用的 SSL 协议版本,默认为 TLSv1 TLSv1.1 TLSv1.2 ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256'; # 设置 SSL 加密算法 ssl_prefer_server_ciphers on; # 在 SSL 握手时优先采用服务器的加密算法 # 在一段时间内复用一个 SSL 会话,以节省 SSL 握手的时间 ssl_session_cache shared:SSL:10m; # 设置 SSL 缓存的大小,10M 大概可以存储 40000 个 SSL 会话 ssl_session_timeout 10m; # 设置缓存的失效时间 }
- HTTP、HTTPS 协议分别默认采用 TCP 80、443 端口,互不兼容。
[root@CentOS ~]# curl https://127.0.0.1:80/ # 不支持向 HTTP 端口发送 HTTPS 请求 curl: (35) SSL received a record that exceeded the maximum permissible length. [root@CentOS ~]# http://127.0.0.1:443/ # 不支持向 HTTPS 端口发送 HTTP 请求 <html> <head><title>400 The plain HTTP request was sent to HTTPS port</title></head> <body bgcolor="white"> <center><h1>400 Bad Request</h1></center>
- 当用户访问 HTTPS 网站时,浏览器通常会禁止发出 HTTP 请求,比如 chrome 浏览器会报错:
blocked:mixed-content
- 当用户访问 HTTPS 网站时,浏览器通常会禁止发出 HTTP 请求,比如 chrome 浏览器会报错:
# http2
例:
server { listen 443 ssl http2; # 监听时采用 ssl 和 http2 协议 }
- 一般的浏览器只支持在 HTTPS 端口启用 HTTP/2 协议,因此需要 Nginx 在监听时同时采用 ssl 和 http2 。
Nginx 端口启用了 HTTP/2 协议时,依然允许接收 HTTP/1 请求。可加入以下配置,拒绝 HTTP/1 请求:
if ($server_protocol ~* "HTTP/1*") { return 444; }