nginx 到上游的连接复用率由什么决定?keepalive 池应该开多大?后端先关闭空闲连接会不会导致错误?这篇用一个能数连接的后端和 nginx 1.31.6 量出来,也诚实记下了没有复现的现象。
配置 | 状态码 | 后端 accept 的连接数 | 复用率 | nginx 发给后端的请求行与 Connection 头
--------------------------------------------+-------------+----------------+-------+-----------------------------------
(a) 只有 proxy_pass | {200: 1000} | 1 | 99.9% | GET / HTTP/1.1 (没有 Connection 头)
(b) proxy_http_version 1.0 | {200: 1000} | 1000 | 0.0% | GET / HTTP/1.0 (没有 Connection 头)
(c) proxy_set_header Connection close | {200: 1000} | 1000 | 0.0% | GET / HTTP/1.1 + Connection: close
(d) keepalive 16 + HTTP/1.1 + Connection "" | {200: 1000} | 1 | 99.9% | GET / HTTP/1.1 (没有 Connection 头)
nginx 1.31.6 里,什么都不配时就已经是 HTTP/1.1 且复用到上游的连接(教科书里“必须同时配 HTTP/1.1、Connection 空串和 keepalive”是旧版本的默认值,我没有测旧版本);只有显式退回 HTTP/1.0 或发 Connection: close 才会每个请求新建连接nginx 1.31.6 默认 HTTP/1.1 并复用上游连接;只有显式退回 1.0 或 Connection: close 才每个请求新建。
配置 | 并发 1 | 并发 8 | 并发 32 --------------------------------------+-------------+--------------+------------- keepalive 2 | 3 条(99.9%) | 834 条(72.2%) | 853 条(71.6%) keepalive 8 | 3 条(99.9%) | 8 条(99.7%) | 171 条(94.3%) keepalive 32 | 3 条(99.9%) | 8 条(99.7%) | 28 条(99.1%) keepalive 32 + keepalive_requests 100 | 30 条(99.0%) | - | - keepalive N 只缓存“空闲”连接:并发比 N 大时,多出来的请求处理完之后连接放不进池子(池子满了)就会被关掉,下一个请求又得新建;并发不超过 N 时,连接几乎全部复用
keepalive N 缓存空闲连接,并发超过 N 时多出来的连接用完就被关;keepalive_requests 限制每条连接处理的请求数。
请求间隔 gap | client 看到的状态码(60 个) | error.log: upstream prematurely closed connection 次数 | 后端 accept 的连接数
-----------------+---------------------+------------------------------------------------------+---------------
0.1 s | {200: 60} | 0 | 1
0.6 s | {200: 60} | 0 | 60
0.27 到 0.33 s 随机 | {200: 60} | 0 | 36
三种 gap 下的 60 个请求都没有失败,包括 gap 在 0.3 s 附近的那一组(最后一列的连接数介于 1 和 60 之间,说明有的连接被复用、有的在被后端关掉之后重建了)。人们常说的“后端先关了空闲连接,nginx 还往里发请求,于是出现偶发 502”,在这个实验里没有复现;它需要请求恰好和对端的关闭同时发生,我没有去构造这个窗口,所以这里不下结论没有复现偶发 502;这种竞争需要请求与关闭同时发生。