首页 运维 nginx Nginx中HTTP的keepalive怎么配置

Nginx中HTTP的keepalive怎么配置

May 12, 2023 am 11:28 AM
http nginx keepalive

http keepalive
在http早期 ,每个http请求都要求打开一个tpc socket连接,并且使用一次之后就断开这个tcp连接。使用keep-alive可以改善这种状态,即在一次tcp连接中可以持续发送多份数据而不会 断开连接。通过使用keep-alive机制,可以减少tcp连接建立次数,也意味着可以减少time_wait状态连接,以此提高性能和提高httpd 服务器的吞吐率(更少的tcp连接意味着更少的系统内核调用,socket的accept()和close()调用)。但是,keep-alive并不是 免费的午餐,长时间的tcp连接容易导致系统资源无效占用。配置不当的keep-alive,有时比重复利用连接带来的损失还更大。所以,正确地设置 keep-alive timeout时间非常重要。
keepalvie timeout
httpd守护进程,一般都提供了keep-alive timeout时间设置参数。比如nginx的keepalive_timeout,和apache的keepalivetimeout。这个 keepalive_timout时间值意味着:一个http产生的tcp连接在传送完最后一个响应后,还需要hold住 keepalive_timeout秒后,才开始关闭这个连接。当httpd守护进程发送完一个响应后,理应马上主动关闭相应的tcp连接,设置 keepalive_timeout后,httpd守护进程会想说:”再等等吧,看看浏览器还有没有请求过来”,这一等,便是 keepalive_timeout时间。如果守护进程在这个等待的时间里,一直没有收到浏览发过来http请求,则关闭这个http连接。
我写了一个脚本,方便测试

<?php
sleep(60); //为了便于分析测试,会根据测试进行调整
echo "www.jb51.net";
?>
登录后复制

1.当keepalive_timeout时间为0时,即不启用keep-alive时,一个tcp连接的生命周期

#tcpdump -n host 218.1.57.236 and port 80
登录后复制
登录后复制
20:36:50.792731 ip 218.1.57.236.43052 > 222.73.211.215.http: s 1520902589:1520902589(0) win 65535
20:36:50.792798 ip 222.73.211.215.http > 218.1.57.236.43052: s 290378256:290378256(0) ack 1520902590 win 5840
20:36:50.801629 ip 218.1.57.236.43052 > 222.73.211.215.http: . ack 1 win 3276820:36:50.801838 ip 218.1.57.236.43052 > 222.73.211.215.http: p 1:797(796) ack 1 win 32768
20:36:50.801843 ip 222.73.211.215.http > 218.1.57.236.43052: . ack 797 win 5920:37:50.803230 ip 222.73.211.215.http > 218.1.57.236.43052: p 1:287(286) ack 797 win 59
20:37:50.803289 ip 222.73.211.215.http > 218.1.57.236.43052: f 287:287(0) ack 797 win 59
20:37:50.893396 ip 218.1.57.236.43052 > 222.73.211.215.http: . ack 288 win 32625
20:37:50.894249 ip 218.1.57.236.43052 > 222.73.211.215.http: f 797:797(0) ack 288 win 32625
20:37:50.894252 ip 222.73.211.215.http > 218.1.57.236.43052: . ack 798 win 59
登录后复制

第1~3行建立tcp三次握手,建立连接。用时8898μs
第4~5行通过建立的连接发送第一个http请求,服务端确认收到请求。用时5μs
第5~6行,可以知道脚本执行用时60s1387μs,与php脚本相符。
第6、8行服务端发送http响应。发送响应用时90166μs。
第7行,表明由服务端守护进程主动关闭连接。结合第6、8行,说明http响应一旦发送完毕,服务端马上关闭这个tcp连接
第7、9、10说明tcp连接顺序关闭,用时90963μs。需要注意,这里socket资源并没有立即释放,需要等待2msl时间(60s)后才被真正释放。
由此可见,在没有设置 keepalive_timeout情况下,一个socket资源从建立到真正释放需要经过的时间是:建立tcp连接 + 传送http请求 + php脚本执行 + 传送http响应 + 关闭tcp连接 + 2msl 。(注:这里的时间只能做参考,具体的时间主要由网络带宽,和响应大小而定)
2.当keepalive_timeout时间大于0时,即启用keep-alive时,一个tcp连接的生命周期。为了便于分析,我们将keepalive_timeout设置为300s

#tcpdump -n host 218.1.57.236 and port 80
登录后复制
登录后复制
21:38:05.471129 ip 218.1.57.236.54049 > 222.73.211.215.http: s 1669618600:1669618600(0) win 65535
21:38:05.471140 ip 222.73.211.215.http > 218.1.57.236.54049: s 4166993862:4166993862(0) ack 1669618601 win 5840
21:38:05.481731 ip 218.1.57.236.54049 > 222.73.211.215.http: . ack 1 win 32768
21:38:05.481976 ip 218.1.57.236.54049 > 222.73.211.215.http: p 1:797(796) ack 1 win 32768
21:38:05.481985 ip 222.73.211.215.http > 218.1.57.236.54049: . ack 797 win 59
21:38:07.483626 ip 222.73.211.215.http > 218.1.57.236.54049: p 1:326(325) ack 797 win 59
21:38:07.747614 ip 218.1.57.236.54049 > 222.73.211.215.http: . ack 326 win 32605
21:43:07.448454 ip 222.73.211.215.http > 218.1.57.236.54049: f 326:326(0) ack 797 win 59
21:43:07.560316 ip 218.1.57.236.54049 > 222.73.211.215.http: . ack 327 win 32605
21:43:11.759102 ip 218.1.57.236.54049 > 222.73.211.215.http: f 797:797(0) ack 327 win 32605
21:43:11.759111 ip 222.73.211.215.http > 218.1.57.236.54049: . ack 798 win 59
登录后复制

我们先看一下,第6~8行,跟上次示例不一样的是,服务端httpd守护进程发完响应后,没有立即主动关闭tcp连接。
第8行,结合第6行,我们可以看到,5分钟(300s)后,服务端主动关闭这个tcp连接。这个时间,正是我们设置的keepalive_timeout的时间。
由此可见,设置了keepalive_timout时间情况下,一个socket建立到释放需要的时间是多了keepalive_timeout时间。
3.当keepalive_timeout时间大于0,并且在同一个tcp连接发送多个http响应。这里为了便于分析,我们将keepalive_timeout设置为180s
通过这个测试,我们想弄清楚,keepalive_timeout是从第一个响应结束开启计时,还是最后一个响应结束开启计时。测试结果证实是后者,这里,我们每隔120s发一次请求,通过一个tcp连接发送了3个请求。

# tcpdump -n host 218.1.57.236 and port 80
登录后复制
22:43:57.102448 ip 218.1.57.236.49955 > 222.73.211.215.http: s 4009392741:4009392741(0) win 65535
22:43:57.102527 ip 222.73.211.215.http > 218.1.57.236.49955: s 4036426778:4036426778(0) ack 4009392742 win 5840
22:43:57.111337 ip 218.1.57.236.49955 > 222.73.211.215.http: . ack 1 win 3276822:43:57.111522 ip 218.1.57.236.49955 > 222.73.211.215.http: p 1:797(796) ack 1 win 32768
22:43:57.111530 ip 222.73.211.215.http > 218.1.57.236.49955: . ack 797 win 59
22:43:59.114663 ip 222.73.211.215.http > 218.1.57.236.49955: p 1:326(325) ack 797 win 59
22:43:59.350143 ip 218.1.57.236.49955 > 222.73.211.215.http: . ack 326 win 3260522:45:59.226102 ip 218.1.57.236.49955 > 222.73.211.215.http: p 1593:2389(796) ack 650 win 32443
22:45:59.226109 ip 222.73.211.215.http > 218.1.57.236.49955: . ack 2389 win 83
22:46:01.227187 ip 222.73.211.215.http > 218.1.57.236.49955: p 650:974(324) ack 2389 win 83
22:46:01.450364 ip 218.1.57.236.49955 > 222.73.211.215.http: . ack 974 win 3228122:47:57.377707 ip 218.1.57.236.49955 > 222.73.211.215.http: p 3185:3981(796) ack 1298 win 32119
22:47:57.377714 ip 222.73.211.215.http > 218.1.57.236.49955: . ack 3981 win 108
22:47:59.379496 ip 222.73.211.215.http > 218.1.57.236.49955: p 1298:1622(324) ack 3981 win 108
22:47:59.628964 ip 218.1.57.236.49955 > 222.73.211.215.http: . ack 1622 win 3276822:50:59.358537 ip 222.73.211.215.http > 218.1.57.236.49955: f 1622:1622(0) ack 3981 win 108
22:50:59.367911 ip 218.1.57.236.49955 > 222.73.211.215.http: . ack 1623 win 32768
22:50:59.686527 ip 218.1.57.236.49955 > 222.73.211.215.http: f 3981:3981(0) ack 1623 win 32768
22:50:59.686531 ip 222.73.211.215.http > 218.1.57.236.49955: . ack 3982 win 108
登录后复制

第一组,三个ip包表示tcp三次握手建立连接,由浏览器建立。
第二组,发送第一次http请求并且得到响应,服务端守护进程输出响应之后,并没马上主动关闭tcp连接。而是启动keepalive_timout计时。
第三组,2分钟后,发送第二次http请求并且得到响应,同样服务端守护进程也没有马上主动关闭tcp连接,重新启动keepalive_timout计时。
第四组,又2分钟后,发送了第三次http请求并且得到响应。服务器守护进程依然没有主动关地闭tcp连接(距第一次http响应有4分钟了,大于keepalive_timeout值),而是重新启动了keepalive_timout计时。
第五组,跟最后一个响应keepalive_timeout(180s)内,守护进程再没有收到请求。计时结束,服务端守护进程主动关闭连接。4次挥手后,服务端进入time_wait状态。
这说明,当设定了keepalive_timeout,一个socket由建立到释放,需要时间是:tcp建立 + (最后一个响应时间 – 第一个请求时间) + tcp关闭 + 2msl。红色加粗表示每一次请求发送时间、每一次请求脚本执行时间、每一次响应发送时间,还有两两请求相隔时间。进一步测试,正在关闭或者 time_wait状态的tcp连接,不能传输http请求和响应。即,当一个连接结束keepalive_timeout计时,服务端守护进程发送第一 个fin标志ip包后,该连接不能再使用了。
http keep-alive与tcp keep-alive
http keep-alive与tcp keep-alive,不是同一回事,意图不一样。http keep-alive是为了让tcp活得更久一点,以便在同一个连接上传送多个http,提高socket的效率。而tcp keep-alive是tcp的一种检测tcp连接状况的保鲜机制。tcp keep-alive保鲜定时器,支持三个系统内核配置参数:

echo 1800 > /proc/sys/net/ipv4/tcp_keepalive_time
echo 15 > /proc/sys/net/ipv4/tcp_keepalive_intvl
echo 5 > /proc/sys/net/ipv4/tcp_keepalive_probes
登录后复制

keepalive是tcp保鲜定时器,当网络两端建立了tcp连接之后,闲置idle(双方没有任何数据流发送往来)了 tcp_keepalive_time后,服务器内核就会尝试向客户端发 送侦测包,来判断tcp连接状况(有可能客户端崩溃、强制关闭了应用、主机不可达等等)。如果没有收到对方的回答(ack包),则会在 tcp_keepalive_intvl后再次尝试发送侦测包,直到收到对对方的ack,如果一直没有收到对方的ack,一共会尝试 tcp_keepalive_probes次,每次的间隔时间在这里分别是15s, 30s, 45s, 60s, 75s。如果尝试tcp_keepalive_probes,依然没有收到对方的ack包,则会丢弃该tcp连接。tcp连接默认闲置时间是2小时,一般 设置为30分钟足够了。也就是说,仅当nginx的keepalive_timeout值设置高于tcp_keepalive_time,并且距此tcp连接传输的最后一 个http响应,经过了tcp_keepalive_time时间之后,操作系统才会发送侦测包来决定是否要丢弃这个tcp连接。一般不会出现这种情况, 除非你需要这样做。
keep-alive与time_wait
使用http keep-alvie,可以减少服务端time_wait数量(因为由服务端httpd守护进程主动关闭连接)。道理很简单,相较而言,启用keep-alive,建立的tcp连接更少了,自然要被关闭的tcp连接也相应更少了。

以上是Nginx中HTTP的keepalive怎么配置的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

怎么查看nginx是否启动 怎么查看nginx是否启动 Apr 14, 2025 pm 01:03 PM

确认 Nginx 是否启动的方法:1. 使用命令行:systemctl status nginx(Linux/Unix)、netstat -ano | findstr 80(Windows);2. 检查端口 80 是否开放;3. 查看系统日志中 Nginx 启动消息;4. 使用第三方工具,如 Nagios、Zabbix、Icinga。

nginx怎么配置云服务器域名 nginx怎么配置云服务器域名 Apr 14, 2025 pm 12:18 PM

在云服务器上配置 Nginx 域名的方法:创建 A 记录,指向云服务器的公共 IP 地址。在 Nginx 配置文件中添加虚拟主机块,指定侦听端口、域名和网站根目录。重启 Nginx 以应用更改。访问域名测试配置。其他注意事项:安装 SSL 证书启用 HTTPS、确保防火墙允许 80 端口流量、等待 DNS 解析生效。

docker容器名称怎么查 docker容器名称怎么查 Apr 15, 2025 pm 12:21 PM

可以通过以下步骤查询 Docker 容器名称:列出所有容器(docker ps)。筛选容器列表(使用 grep 命令)。获取容器名称(位于 "NAMES" 列中)。

nginx怎么查版本 nginx怎么查版本 Apr 14, 2025 am 11:57 AM

可以查询 Nginx 版本的方法有:使用 nginx -v 命令;查看 nginx.conf 文件中的 version 指令;打开 Nginx 错误页,查看页面的标题。

怎么启动nginx服务器 怎么启动nginx服务器 Apr 14, 2025 pm 12:27 PM

启动 Nginx 服务器需要按照不同操作系统采取不同的步骤:Linux/Unix 系统:安装 Nginx 软件包(例如使用 apt-get 或 yum)。使用 systemctl 启动 Nginx 服务(例如 sudo systemctl start nginx)。Windows 系统:下载并安装 Windows 二进制文件。使用 nginx.exe 可执行文件启动 Nginx(例如 nginx.exe -c conf\nginx.conf)。无论使用哪种操作系统,您都可以通过访问服务器 IP

nginx在windows中怎么配置 nginx在windows中怎么配置 Apr 14, 2025 pm 12:57 PM

如何在 Windows 中配置 Nginx?安装 Nginx 并创建虚拟主机配置。修改主配置文件并包含虚拟主机配置。启动或重新加载 Nginx。测试配置并查看网站。选择性启用 SSL 并配置 SSL 证书。选择性设置防火墙允许 80 和 443 端口流量。

docker怎么创建容器 docker怎么创建容器 Apr 15, 2025 pm 12:18 PM

在 Docker 中创建容器: 1. 拉取镜像: docker pull [镜像名] 2. 创建容器: docker run [选项] [镜像名] [命令] 3. 启动容器: docker start [容器名]

docker怎么启动容器 docker怎么启动容器 Apr 15, 2025 pm 12:27 PM

Docker 容器启动步骤:拉取容器镜像:运行 "docker pull [镜像名称]"。创建容器:使用 "docker create [选项] [镜像名称] [命令和参数]"。启动容器:执行 "docker start [容器名称或 ID]"。检查容器状态:通过 "docker ps" 验证容器是否正在运行。

See all articles