关于Keepalive的那些事

服务端不少同窗包括本身对keepalive理解不清晰,常常搞不清楚,TCP也有keepalive,HTTP也有keepalive,高可用也叫keepalive,常常混淆这几个概念。作下这几个概念的简述,尽管名字基本上是同样的,可是所表示意义和范畴却截然不同。nginx

高可用 Keepalived

Keepalived是一个基于VRRP协议来实现的服务高可用方案,能够利用其来避免IP单点故障。它的做用是检测服务器的状态,若是有一台服务器宕机,或出现故障,Keepalived将检测到,使用其余服务器代替该服务器的工做,当服务器工做正常后Keepalived自动将服务器加入到服务器群中。
Keepalived通常不会单独出现,而是与其它负载均衡技术(如lvs、haproxy、nginx)一块儿工做来达到集群的高可用。web

一个简单的使用例子,将域名解析到一台负载均衡机器上,而后负载均衡反向代理到WEB机器上。中间的负载均衡只有一台,无法作到高可用,至少须要作到两台,那配置成两台机器以后,Keepalived就能够保证服务只有一个对外的虚拟IP,若是MASTER的负载均衡出现故障的时候,自动切换到BACKUP负载均衡上,服务不受任何影响。Keepalived来保证这些。服务器

咱们之前有过一套稍显复杂的服务配置,Keepalived给HAProxy提供高可用,而后HAProxy给Twemproxy提供高可用和负载均衡,Twemproxy给Redis集群提供高可用和负载均衡。提供负载均衡服务的基本都会保证高可用,咱们使用最多的Nginx做为反向代理服务器的时候,就能保证web服务的高可用。网络

nginx+keepalived 搭建高可用的服务教程有不少。感兴趣的能够本身试下搭建。负载均衡

TCP 的keepalive

TCP的keepalive主要目的是及时的释放服务器资源。
经过TCP协议客户端与服务器创建链接以后,若是客户端一直不发送数据,或者隔很长时间才发送一次数据,当链接好久没有数据传输时如何去肯定对方还在线,究竟是掉线了仍是确实没有数据传输,链接是保持仍是关闭,多长时间或者在什么样的机制下链接应该关闭释放资源。TCP的keepalive就是为了解决这个问题才引入的。
TCP的keepalive主要是三个参数来控制tcp

tcp_keepalive_time 7200
心跳周期
tcp_keepalive_intvl 75
侦测包发送间隔
tcp_keepalive_probes 9
侦测包重试次数

解释下这个流程和参数。
客户端与服务器创建链接后,若是双方在tcp_keepalive_time(7200S)后,没有任何数据的传输,服务器就会每隔tcp_keepalive_intvl(75S)向客户端发送探测包,判断客户端的链接状态,大概包括客户端崩溃、强制关闭了应用、主机不可达等的异常状态。若是侦测包发送了tcp_keepalive_probes(9)次以后仍然没有收到客户端的回复(就是ack包),服务器就会认为这个链接已经不可用了,能够丢弃或者关闭了。阿里云

Nginx 的keepalive

TCP层已经有keepalive,为何应用层的Nginx还须要keepalive?
我理解的是,使用TCP的keepalive的保证传输层链接的可用性,默认配置都是2小时的检测周期。Nginx的keepalive来保证应用层的链接的可用性。一个在第四层传输层上保证可用性,一个在第七层应用层上保证应用层协议链接的可用性。
有本书里面有提到:
为何TCP keepalive不能替代应用层心跳?心跳除了说明应用程序还活着(进程还在,网络通畅),更重要的是代表应用程序还能正常工做。而TCP keepalive由操做系统负责探查,即使进程死锁或者阻塞,操做系统也会如常收发TCP keepalive信息,对方没法得知这一异常。操作系统

nginx keepalive跟TCP的配置基本一致,只不过名字不同罢了。配置说明以下代理

so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]

so_keepalive=30m::10 表示开启tcp侦测,30分钟后无数据收发会发送侦测包,时间间隔使用系统默认的,发送10次侦测包。code

HTTP的keepalive

HTTP的keepalive比较常见,就是将短连接变成长连接。短链接是每一个请求响应,客户端和服务器都要新建一个链接,完成以后当即断开链接;当使用keepalive长链接时,客户端到服务器端的创建链接,响应完成后链接不断开,下次请求直接服用原来的链接,这样就避免了重复创建链接和断开链接的开销。

那么客户端和服务器端是怎么约定使用长链接通讯仍是短链接通讯。
主要Connection头部

客户端请求长链接头部:Connection: keep-alive
服务端赞成使用长链接的响应头部:Connection: keep-alive
二者缺一不可,若是服务器端不支持长链接:Connection: Close
若是是HTTP/1.1默认使用长链接,不管头部是否是 Connection: keep-alive

注意的点:
Connection只对当前的链接双方有效,而且Connection头部不向后传递,只标识本身的链接状态。
若是是多级代理又是什么流程?
在这里插入图片描述
1客户端与代理服务器1建连的时候带了Connection: keep-alive,可是代理服务器1不支持长链接,回复了Connection: Close,因此使二者用短链接
2代理服务器1与代理服务器2建连的时候使用Connection: Close短链接,代理服务器2回复了Connection: Close,因此二者使用短链接
3代理服务器2与web机器建连的时候使用了Connection: keep-alive,web机器支持长链接,也回复了Connection: keep-alive,因此二者使用长链接

HTTP的keepalive是开发者最长遇到的,因此要格外注意。不是服务器要求使用长链接链接就是长链接,是须要双方都赞成才能使用长链接通讯。之前遇到过阿里云的SLB就不支持长链接,WEB服务器或者代理服务器跟SLB链接的都是短链接。