长链接及心跳保活原理简介

 

  本文简要的分析了长链接产生的背景以及所解决的问题,并对比了keep-alive与心跳机制对长链接保活的影响,最后详细的介绍了心跳保活的两个关键因素–DHCP协议与NAT原理。若有不当之处,欢迎批评和指正。php


1.短链接,并行链接,持久链接与长链接

(1) 短链接简介

  在互联网发展过程当中,最为普及的应用就是HTTP超文本传输协议,而在早期–HTTP1.0的协议都是创建在TCP协议基础上,其特色就是传输完数据后,立马就释放掉该TCP连接,因此就有了形象的短链接这个称号。下图形象的展现出了在一个事务的处理过程当中,各个阶段的处理时长:html

image_1c8acepra1ko1m287rb1mi3qes9.png-38.9kB

  能够看到,与创建TCP链接,以及传输请求和响应报文的时间相比,事务处理时间多是很短的。短链接的性能瓶颈主要集中在以下几个方面:前端

a.TCP链接的握手时延

image_1c8acqp088hdctrpe113981ucrm.png-50.1kB

  在发送数据以前,TCP要传送两个分组来创建链接(现代的TCP栈都容许客户端在确认分组中发送数据),此时,SYN/SYN+ACK握手会产生一个可测量的时延。android

b.延迟确认

  每一个TCP段都有一个序列号和数据完整性校验和。每一个段的接收者收到无缺的段时,都会向发送者回送小的确认分组。若是发送者没有在指定的窗口时间内收到确认信息,发送者就认为分组已被破坏或损毁,并重发数据。
  因为确认报文很小,因此TCP容许在发往相同方向的输出数据分组中对其进行“捎带”。TCP将返回的确认信息与输出的数据分组结合在一块儿,能够更有效地利用网络。为了增长确认报文找到同向传输数据分组的可能性,不少TCP栈都实现了一种“延迟确认”算法。延迟确认算法会在一个特定的窗口时间(一般是100~200毫秒)内将输出确认存放在缓冲区中,以寻找可以捎带它的输出数据分组。若是在那个时间段内没有输出数据分组,就将确认信息放在单独的分组中传送。nginx

c.TCP慢启动

  TCP链接会随着时间进行自我“调谐”,起初会限制链接的最大速度,若是数据成功传输,会随着时间的推移提升传输的速度,这种调谐被称为TCP慢启动,用于防止因特网的忽然过载和拥塞。
  因为存在这种拥塞控制特性,因此新链接的传输速度会比已经交换过必定量数据的、“已调谐”链接慢一些。git

(2) 短链接的适用场景与优缺点

  短链接多用于操做频繁,点对点的通信,并且链接数不能太多的状况。每一个TCP链接的创建都须要三次握手,每一个TCP链接的断开要四次挥手。适用于并发量大,可是每一个用户又不需频繁操做的状况。
  可是在用户须要频繁操做的业务场景下(如新用户注册,网购提交订单等),频繁的使用短链接则会使性能时延产生叠加,以下如:github

image_1c8adodlr1ad4cr91uu9unf1e3413.png-61.4kB

  所以就产生了一些列关于链接性能的改进方案。算法

(3) 并行链接

  并行链接容许客户端打开多条链接,并行地执行多个事务,每一个事务都有本身的TCP链接。这样能够克服单条链接的空载时间和带宽限制,时延能够重叠起来,并且若是单条链接没有充分利用客户端的网络带宽,能够将未用带宽分配来装载其余对象。
  在PC时代,利用并行链接来充分利用现代浏览器的多线程并发下载能力的场景很是普遍。
  可是并行链接也会产生必定的问题,首先并行链接不必定更快,由于带宽资源有限,每一个链接都会去竞争这有限的带宽,这样带来的性能提高就很小,甚至没什么提高。另外打开大量链接会消耗不少内存资源,从而引起自身的性能问题,所以每一个浏览器,容许对每一个域名的链接数通常是有上限的,以下图所示:浏览器

image_1c8aeqcro1gpnohp1j8ng18pd9.png-89kB

(4) 持久链接

  HTTP1.0版本之后,容许HTTP设备在事务处理结束以后将TCP链接保持在打开状态,以便为将来的HTTP请求重用现存的链接。在事务处理结束以后仍然保持在打开状态的TCP链接被称为持久链接。非持久链接会在每一个事务结束以后关闭。持久链接会在不一样事务之间保持打开状态,直到客户端或服务器决定将其关闭为止。
  如今不少方案都会采用持久链接+新链接结合的方式,这种方式尽量的减小了新建链接的浪费,同时当现有链接没有办法知足需求的时候,能够创建新链接知足需求,比较灵活。
  持久链接的时间参数,一般由服务器设定,好比nginx的keepalivetimeout,keepalive timout时间值意味着:一个http产生的tcp链接在传送完最后一个响应后,还须要hold住keepalive_timeout秒后,才开始关闭这个链接;服务器

  持久链接与并行链接相比,带来的优点以下:

  • 避免了每一个事务都会打开/关闭一条新的链接,形成时间和带宽的耗费;
  • 避免了TCP慢启动特性的存在致使的每条新链接的性能下降;
  • 可打开的并行链接数量其实是有限的,持久链接则能够减小创建的链接的数量;

(5) 长链接

  长链接与持久链接本质上很是的类似,持久链接侧重于HTTP应用层,特指一次请求结束以后,服务器会在本身设置的keepalivetimeout时间到期后才关闭已经创建的链接。长链接则是client方与server方先创建链接,链接创建后不断开,而后再进行报文发送和接收,直到有一方主动关闭链接为止。

  长链接的适用场景也很是的普遍:

  • 监控系统:后台硬件热插拔、LED、温度、电压发生变化等;
  • IM应用:收发消息的操做;
  • 即时报价系统:例如股市行情push等;
  • 推送服务:各类App内置的push提醒服务;

  像以上这些链接,若是每次操做都要创建链接而后再操做的话处理速度会下降,而且时效性也不高。经过长链接,第一次链接上之后每次直接发送数据就能够了,不用再创建TCP链接。


2.长链接保活,Keep-Alive与心跳保活技术

(1) 为什么须要长链接保活

  上一节的分析能够看到,对于客户端而言,使用TCP长链接来实现业务的好处在于:在当前链接可用的状况下,每一次请求都只是简单的数据发送和接受,免去了DNS解析,链接创建,TCP慢启动等时间,大大加快了请求的速度,同时也有利于接收服务器的实时消息。
  在使用TCP长链接的业务场景下,保持长链接的可用性很是重要。若是长链接没法很好地保持,在链接已经失效的状况下继续发送请求会致使迟迟收不到响应直到超时,又须要一次链接创建的过程,其效率甚至还不如直接使用短链接。而链接保持的前提必然是检测链接的可用性,并在链接不可用时主动放弃当前链接并创建新的链接。

(2) 心跳保活

  App实现长链接保活的方式一般是采用应用层心跳,经过心跳包的超时和其余条件(网络切换)来执行重连操做。心跳通常是指某端(绝大多数状况下是客户端)每隔必定时间向对端发送自定义指令,以判断双方是否存活,因其按照必定间隔发送,相似于心跳,故被称为心跳指令。

(3) Keep-Alive能否实现保活?

a.HTTP中的Keep-Alive

  实现HTTP/1.0 keep-alive链接的客户端能够经过包含Connection:Keep-Alive首部请求将一条链接保持在打开状态,若是服务器愿意为下一条请求将链接保持在打开状态,就在响应中包含相同的首部。若是响应中没有Connection: Keep-Alive首部,客户端就认为服务器不支持keep-alive,会在发回响应报文以后关闭链接。HTTP/1.1之后Keep-Alive是默认打开的。

c.TCP中的Keep-Alive

  TCP协议的实现中,提供了KeepAlive报文,用来探测链接的对端是否存活。在应用交互的过程当中,可能存在如下几种状况:

  • 客户端或服务器意外断电,死机,崩溃,重启;
  • 中间网络已经中断,而客户端与服务器并不知道;

  利用保活探测功能,能够探知这种对端的意外状况,从而保证在乎外发生时,能够释放半打开的TCP链接。TCP保活报文交互过程以下:

image_1c8ai46ncp561qieot2n0h15p5m.png-174.7kB

  虽然TCP提供了KeepAlive机制,可是并不能替代应用层心跳保活。缘由主要以下:

  • (1) Keep Alive机制开启后,TCP层将在定时时间到后发送相应的KeepAlive探针以肯定链接可用性。默认时间为7200s(两小时),失败后重试10次,每次超时时间75s。显然默认值没法知足移动网络下的需求;
  • (2) 即使修改了(1)中的默认值,也不能很好的知足业务需求。TCP的KeepAlive用于检测链接的死活而不能检测通信双方的存活状态。好比某台服务器由于某些缘由致使负载超高,没法响应任何业务请求,可是使用TCP探针则仍旧可以肯定链接状态,这就是典型的链接活着但业务提供方已死的状态,对客户端而言,这时的最好选择就是断线后从新链接其余服务器,而不是一直认为当前服务器是可用状态,一直向当前服务器发送些必然会失败的请求。
  • (3) socks代理会让Keep Alive失效。socks协议只管转发TCP层具体的数据包,而不会转发TCP协议内的实现细节的包。因此,一个应用若是使用了socks代理,那么TCP的KeepAlive机制就失效了。
  • (4) 部分复杂状况下Keep Alive会失效,如路由器挂掉,网线直接被拔除等;

  所以,KeepAlive并不适用于检测双方存活的场景,这种场景还得依赖于应用层的心跳。应用层心跳也具有着更大的灵活性,能够控制检测时机,间隔和处理流程,甚至能够在心跳包上附带额外信息。

(4) 影响心跳频率的关键因素

  经过上一节的分析能够看到应用层心跳是检测链接有效性以及判断双方是否存活的有效方式。可是心跳过于频繁会带来耗电和耗流量的弊病,心跳频率太低则会影响链接检测的实时性。业内关于心跳时间的设置和优化,主要基于以下几个因素:

  • 1.NAT超时–大部分移动无线网络运营商在链路一段时间没有数据通信时,会淘汰 NAT表中的对应项,形成链路中断;
  • 2.DHCP租期–DHCP租期到了须要主动续约,不然会继续使用过时IP致使长链接偶然的断连;
  • 3.网络状态变化–手机网络和WIFI网络切换、网络断开和连上等状况有网络状态的变化,也会使长链接变为无效链接;

  网络状态变化致使长链接变为无效链接的缘由很容易理解。可是NAT超时和DHCP租期的问题对长链接保活存在的影响就涉及到网络协议底层的细节了。后续会对这两个原理进行相应的分析。


3.DHCP原理浅析及其对心跳保活的影响

(1) DHCP协议简介

  DHCP协议全称为Dynamic Host Configuration Protocol– 动态主机配置协议,主要用于在一个局域网里为主机动态的分配IP地址。DHCP有三种分配IP地址方式:

  • 自动分配:DHCP给客户端分配永久性的IP地址;
  • 动态分配:DHCP给客户端分配的IP地址过一段时间后会过时,或者客户端能够主动释放该地址(最经常使用的方式);
  • 手动配置:由用户手动为客户端指定IP地址;

(2) DHCP工做流程详解

  DHCP协议为客户端分配IP的过程大体以下:

DHCP分配IP的过程

1.DHCP Discover

  DHCP客户端(须要上网的设备)以广播(由于客户端还不知道DHCP服务器的IP地址)的方式发送DHCP Discover包,来寻找DHCP服务器,即向地址255.255.255.255发送特定的广播信息。网络上每一台安装了TCP/IP协议的主机都会收到该广播消息,但只有DHCP服务器才会作出响应。

DHCPDiscover1.png-31.2kB

DHCPDiscover2.png-70kB

2.DHCP Offer

  在该阶段,DHCP服务器提供IP地址。在网络中接收到DHCP Discover包的DHCP服务器,都会作出响应。这些DHCP服务器从还没有出租的IP地址中挑选一个给客户端,向客户端发送一个包含IP地址和其余设置的DHCP Offer包。

DHCPOffer1.png-36.6kB

DHCPOffer2.png-128.8kB

3.DHCP Request

DHCP确认.png-218.1kB
  该阶段须要DHCP客户端选择某台DHCP服务器提供的IP地址,如上图所示,能够看到3台DHCP服务器都向客户端发送了DHCP Offer,此时,DHCP客户端只能接受第一个收到的DHCP Offer包信息。而后,以广播的方式回答一个DHCP Request请求信息,该信息中包含它所选定的DHCP服务器请求IP地址的内容。

DHCPRequest.png-84.4kB

4.DHCP ACK

  确认阶段,DHCP服务器确认所提供的的IP地址阶段,告诉DHCP客户端可使用它所提供的IP地址。

DHCP_ACK.png-88.7kB

(3) DHCP的续租问题

  在DHCP ACK报文中,有3个关于续租时间相关的字段:

  • Lease Time:
    IP地址租约时间,超过了这个时间后,IP地址被DHCP服务器收回;
  • Renewal Time:
    默认为Lease Time的1/2,表示客户端须要进行续约的时间。客户端发送一个DHCP REQUEST消息给原始的DHCP服务器,并等待回复。DHCP服务器返回DHCP ACK则表示赞成续期,客户端更新本身的Renewal Time与Rebinding Time便可。
  • Rebinding Time:
    默认为Lease Time的7/8,客户端在续期失败的状况下,Rebinding Time到期时,会向局域网内广播发送一条DHCP REQUEST消息,若是尚未DHCP服务器响应直至租约Lease Time到期,将恢复到初始状态。

  DHCP完成的状态变迁流程以下:

DHCP状态图.PNG-156.6kB

(4) DHCP租期问题对心跳保活的影响

  在设计心跳频率时,DHCP租期是一个不肯定因素,可是原则是心跳的最大间隔应该低于DHCP的租期时间。
  另外,在Android的一些版本上,存在DHCP租期到了不会主动续约而且会继续使用过时IP的bug。这个问题致使的问题表象是,在超过租期的某个时间点(没有规律)会致使IP过时,老的TCP链接不能正常收发数据。而且系统没有网络变化事件,只有等应用判断主动创建新的TCP链接才引发安卓设备从新向DHCP Server申请IP租用。详情可见–Android 2.1 - 4.1.1 Allows DHCP Lease to Expire, Keeps Using IP Address。


4.NAT原理浅析及其对心跳保活的影响

(1) NAT技术产生的背景

  在网络协议制定的初期设计网络地址的时候,32bits位长即2的32次幂台终端设备连入互联网已是一个很是大的数量了,再加上增长ip的长度(即便是从4字节增到6字节)对当时设备的计算、存储、传输成本也是至关巨大的。所以IP地址设计为了32位,而且在早期全部须要上网的设备都有本身的IP地址,也就是说那个时候没有内网和外网的区别,全部客户端都是直接链接到互联网的。
  进入20世纪90年代以后,互联网逐步向公众普及,接入互联网的设备数量也快速增加,若是还用原来的方法接入,过不了多久,可分配的地址就用光了。若是不能保证每台设备有惟一不重复的地址,就会从根本上影响网络包的传输,这是一个很是严重的问题。若是任由这样发展下去,不久的未来,一旦固定地址用光,新的设备就没法接入了。在这个背景下NAT技术诞生了(虽然ipv6也是解决办法,但始终普及不开来,并且将来到底ipv6够不够用还是未知)。

(2) NAT技术的基本工做原理

a.NAT技术的本质

  NAT技术主要是为了解决公网IP地址不足的问题,因此才会采起这种地址转换的策略。本质上就是让一群机器公用同一个IP,这样就暂时解决了IP短缺的问题。

b.私有地址与公有地址

  不一样内网之间是彻底独立的。内网之间不会有网络包流动,即便内网A的某台服务器和内网B的某台客户端具备相同的IP地址也不要紧,由于它们之间不会进行通讯。只要在每一个内网本身的范围内,可以明确判断网络包的目的地就能够了,是否和其余局域网中的内网地址重复可有可无,只要每一个局域网本身的网络是相互独立的,
就不会出现问题。
  解决地址不足的问题,利用的就是这样的原理,即局域网的内部设备的地址不必定要和其余局域网中的内部设备地址不重复。这样一来,局域网的内部设备就不须要分配固定地址了,从而大幅节省了IP地址。内部设备分配IP地址的方式,就是经过上一节的DHCP协议进行。内网地址的分配有相应的规则,规定某些地址是用于内网的,这些地址叫做私有地址,而原来的固定地址则叫做公有地址。
  在内网中可用做私有地址的范围仅限如下这些:

  • 10.0.0.0~10.255.255.255
  • 172.16.0.0~172.31.255.255
  • 192.168.0.0~192.168.255.255

  在制定私有地址规则时,这些地址属于公有地址中尚未分配的范围。换句话说,私有地址自己并无什么特别的结构,只不过是将公有地址中没分配的一部分拿出来规定只能在内网使用它们而已。

c.地址转换(NAT)机制的加入

  当内网和互联网之间须要传输包的时候,问题就出现了,由于若是不少地方都出现相同的地址,包就没法正确传输了。所以当公司内网和互联网链接的时候,须要采用下图这样的结构,即将公司内网分红两个部分,一部分是对互联网开放的服务器,另外一部分是公司内部设备。其中对互联网开放的部分分配公有地址,能够和互联网直接进行通讯。相对地,内网部分则分配私有地址,内网中的设备不能和互联网直接收发网络包,而是经过一种特别的机制进行链接,这个机制就叫地址转换。

公有地址和私有地址.png-70.6kB

d.地址转换(NAT)的基本原理

  地址转换的基本原理是在转发网络包时对IP头部中的IP地址和端口号进行改写,以下图所示:TCP链接操做的第一个包被转发到互联网时,会将发送方IP地址从私有地址改写成公有地址。这里使用的公有地址是地址转换设备的互联网接入端口的地址。与此同时,端口号也须要进行改写,地址转换设备会随机选择一个空闲的端口。而后,改写前的私有地址和端口号,以及改写后的公有地址和端口号,会做为一组相对应的记录保存在地址转换设备内部的一张表(NAT表)中。

地址转换的基本原理.png-103kB

  改写发送方IP地址和端口号以后,包就被发往互联网,最终到达服务器,而后服务器会返回一个包。服务器返回的包的接收包是原始包的发送方,所以返回的包的接收方就是改写后的公有地址和端口号。这个公有地址实际上是地址转换设备的地址,所以这个返回包就会到达地址转换设备。接下来,地址转换设备会从地址对应表中经过公有地址和端口号找到相对应的私有地址和端口号,并改写接收方信息,而后将包发给局域网的内部设备,这样包就可以到达原始的发送方了。

e.为何须要改写端口号?

  早期的地址转换机制是只改写地址,不改写端口号的。使用这种方法的前提是私有地址和公有地址必须一一对应,也就是说,有多少台设备须要同时访问互联网,就须要多少个公有地址。访问动做结束后能够删除对应表中的记录,这时同一个公有地址能够分配给其余设备使用。
  后续随着互联网的发展,同一个局域网里的设备也愈来愈多。改写端口号正是为了解决这个问题。客户端一方的端口号原本就是从空闲端口中随机选择的,所以改写了也不会有问题。端口号是一个16比特的数值,总共能够分配出几万个端口,所以若是用公有地址加上端口的组合对应一个私有地址,一个公有地址就能够对应几万个私有地址,这种方法提升了公有地址的利用率。

(3) NAT技术带来的弊端

  首先,NAT使IP会话的保持时效变短。由于NAT表中的每一条记录,在会话静默的这段时间,NAT网关会进行老化操做。这是任何一个NAT网关必须作的事情,由于IP和端口资源有限,通讯的需求无限,因此必须在会话结束后回收资源。一般TCP会话经过协商的方式主动关闭链接,NAT网关能够跟踪这些报文,但老是存在例外的状况,要依赖本身的定时器(NAT超时机制)去回收资源。经过NAT超时机制回收会带来一个问题,若是应用须要维持链接的时间大于NAT网关的设置,通讯就会意外中断。由于网关回收相关转换表资源之后,新的数据到达时就找不到相关的转换信息,必须创建新的链接。

  其次,NAT在实现上将多个内部主机发出的链接复用到一个IP上,这就使依赖IP进行主机跟踪的机制都失效了。基于用户行为的日志分析也变得困难,由于一个IP被不少用户共享,若是存在恶意的用户行为,很难定位到发起链接的那个主机。NAT隐蔽了通讯的一端,把简单的事情复杂化了。

  NAT一下对IP端到端模型产生了破坏。NAT经过修改IP首部的信息变换通讯的地址。可是在这个转换过程当中只能基于一个会话单位。当一个应用须要保持多个双向链接时,麻烦就很大。NAT不能理解多个会话之间的关联性,没法保证转换符合应用须要的规则。当NAT网关拥有多个公有IP地址时,一组关联会话可能被分配到不一样的公网地址,这一般是服务器端没法接受的。更为严重的是,当公网侧的主机要主动向私网侧发送数据时,NAT网关没有转换这个链接须要的关联表,这个数据包没法到达私网侧的主机。这些反方向发送数据的链接总有应用协议的约定或在初始创建的会话中进行过协商。

(4) NAT超时机制对心跳保活

  上一节已经分析到,NAT超时机制会带来一个问题,若是应用须要维持链接的时间大于NAT网关的设置,通讯就会意外中断。由于网关回收相关转换表资源之后,新的数据到达时就找不到相关的转换信息,必须创建新的链接。当这个新数据是由公网侧向私网侧发送时,就会发生没法触发新链接创建,也不能通知到私网侧的主机去重建链接的状况。这时候通讯就会中断,不能自动恢复。即便新数据是从私网侧发向公网侧,由于重建的会话表每每使用不一样于以前的公网IP和端口地址,公网侧主机也没法对应到以前的通讯上,致使用户可感知的链接中断。
  因此广泛的一个作法就是使用心跳保活,在一段时间没有数据须要发送时,主动发送一个NAT能感知到而又没有实际数据的保活消息–心跳,这么作的主要目的就是重置NAT的会话定时器。理想的状况下,客户端应当以略小于NAT超时时间的间隔来发送心跳包。根据微信团队测试的一些数据,一些经常使用网络的NAT超时时间以下表所示:

地区/网络 NAT超时时间
中国移动3G和2G 5分钟
中国联通2G 5分钟
中国电信3G 大于28分钟
美国3G 大于28分钟
台湾3G 大于28分钟

5.小结

  本文简单的总结了一些短链接的劣势,以及几种改进的链接方案,并引出长链接的概念和相关的使用场景,并详细对比了keep-alive和心跳机制的不一样之处,强调心跳机制对长链接保活的重要意义。并对影响心跳时间的两个关键–DHCP与NAT进行了简单的介绍。如今动态心跳的方案也愈来愈普及,网上已经有很多文章作了相关的分享,本文参考文献部分也有相关的连接。若有不当之处,敬请批评指正。


参考文献

1. TCP Keepalive HOWTO
2. 移动端IM开发须要面对的技术问题
3. 为何说基于TCP的移动端IM仍然须要心跳保活
4. DHCP General Operation and Client Finite State Machine
5. dhcp.figure
6. Android 2.1 - 4.1.1 Allows DHCP Lease to Expire, Keeps Using IP Address。
7. 《网络是怎么链接的》–3.4.2节:地址转换的基本原理
8. 《HTTP权威指南》–第4章:链接管理
9. 前端性能–浅谈域名发散与域名收敛
10. Tcp Keepalive 和 HTTP Keepalive详解
11.Android端消息推送总结:实现原理、心跳保活、遇到的问题等
12.P2P技术详解(一):NAT详解——详细原理、P2P简介
13.知乎问答–NAT与DHCP的区别
14.一种Android端IM智能心跳算法的设计与实现探讨

相关文章
相关标签/搜索