tcp的keepalive和http的keepalive

  26 Jun 2016


###前言 今天,在看服务器性能调优的时候看到修改Linux内核参数的时候,修改/etc/sysctl.conf来更改内核参数,其中有个net.ipv4.tcp_keepalive_time=600,忽然想到在http协议中也存在一个keepalive配置,那这两个配置有什么关系呢?

http的keep-alive

首先,说一下http协议中的keepalive,其实应该是keep-alive,如图
Image

在http早期,每个http请求都要求打开一个tpc socket连接,并且使用一次之后就断开这个tcp连接。这样就会增加许多的tcp开销,因为要不停的握手,挥手。
然后呢,就有了http的keep-alive,通过使用keep-alive机制,可以减少tcp连接建立的次数,从而减少TIME_WAIT状态连接,以此提高了性能和httpd服务器的吞吐率(更少的tcp连接意味着更少的系统内核调用,socket的accept()和close()调用)。 但是,keep-alive并不是免费的午餐,长时间的tcp连接容易导致系统资源无效占用。配置不当的keep-alive,有时比重复利用连接带来的损失还更大。所以,正确地设置 keep-alive timeout时间非常重要。
在nginx中的参数是keepalive_timeout,Apache中的是KeepAliveTimeout,这个keepalive_timout时间意味着:一个http产生的tcp连接在传送完最后一个相应,还要hold住keepalive_timeout秒后,才开始关闭这个连接。

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连接也相应更少了。

comments powered by Disqus