一、前言
TCP 本身并没有长短连接的区别,长短与否,完全取决于我们怎么用它。
- 短连接:每次通信时,创建Socket,一次通信结束,调用socket.close()。这就是一般意义上的短连接,短连接的好处是管理起来比较简单,存在的连接都是可用的连接,不需要额外的控制手段。
- 长连接:每次通信完毕后,不会关闭连接,这样就可以做到连接的复用。长连接的好处便是省去了创建连接的耗时。
二、连接保活
为什么需要连接的保活?当双方已经建立了连接,但因为网络问题,链路不通,这样长连接就不能使用了。需要明确的一点是,通过netstat,lsof等指令查看到连接的状态处于ESTABLISHED状态并不是一件非常靠谱的事,因为连接可能已死,但没有被系统感知到,更不用提假死这种疑难杂症了。如何保证长连接可用是一件技术活。
1、连接的保活:KeepAlive
KeepAlive并不是TCP协议的一部分,但是大多数操作系统都实现了这个机制。KeepAlive机制开启后,在一定时间内在链路上没有数据传送的情况下,TCP层将发送相应的KeepAlive探针以确定连接可用性,探测失败后重试10次,每次间隔时间75s,所有探测失败后,才认为当前连接已经不可用。
- tcp_keepalive_time(空闲时间,一般时间为7200s)
- tcp_keepalive_probes(重试次数,默认10次)
- tcp_keepalive_intvl(重试间隔 75s)
在 Netty 中开启 KeepAlive:
bootstrap.option(ChannelOption.TCP_NODELAY, true)
Linux 操作系统中设置 KeepAlive 相关参数,修改 /etc/sysctl.conf 文件:
net.ipv4.tcp_keepalive_time=90
net.ipv4.tcp_keepalive_intvl=15
net.ipv4.tcp_keepalive_probes=2
KeepAlive机制是在网络层面保证了连接的可用性,但站在应用框架层面我们认为这还不够,主要体现在以下几个方面:
- KeepAlive 的开关是在应用层开启的,但是具体参数(如重试测试,重试间隔时间)的设置却是操作系统级别的,位于操作系统的 /etc/sysctl.conf配置中,这对于应用来说不够灵活。
- KeepAlive 的保活机制只在链路空闲的情况下才会起到作用,假如此时有数据发送,且物理链路已经不通,操作系统这边的链路状态还是 ESTABLISHED,这时会发生什么?自然会走 TCP 重传机制,要知道默认的 TCP 超时重传,指数退避算法也是一个相当长的过程。
- KeepAlive 本身是面向网络的,并不是面向于应用的,当连接不可用时,可能是由于应用本身GC问题,系统load高等情况,但网络仍然是通的,此时,应用已经失去了活性,所以连接自然应该认为是不可用的。
2、连接保活:应用层心跳
简单来说,就是客户端会开启一个定时任务,定时对已经建立连接的对端应用发送请求(这里的请求是特殊的心跳请求),服务端则需要特殊处理该请求,返回响应。如果心跳持续多次没有收到响应,客户端会认为连接不可用,主动断开连接。不同的服务治理框架对心跳,建连,断连,拉黑的机制有不同的策略,但大多数的服务治理框架都会在应用层做心跳,Dubbo也不例外。
网友评论