Keep-Alive
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连接。
测试结果证实是后者
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分钟足够了。
使用http keep-alvie,可以减少服务端TIME_WAIT数量(因为由服务端httpd守护进程主动关闭连接)。道理很简单,相较而言,启用keep-alive,建立的tcp连接更少了,自然要被关闭的tcp连接也相应更少了。
HTTP 1.0中默认是关闭的,需要在http头加入"Connection: Keep-Alive",才能启用Keep-Alive;HTTP 1.1中默认启用Keep-Alive,如果加入"Connection: close",才关闭。
在HTTP/1.0版本中,并没有官方的标准来规定Keep-Alive如何工作,因此实际上它是被附加到HTTP/1.0协议上,如果客户端浏览器支持Keep-Alive,那么就在HTTP请求头中添加一个字段 Connection: Keep-Alive,当服务器收到附带有Connection: Keep-Alive的请求时,它也会在响应头中添加一个同样的字段来使用Keep-Alive。这样一来,客户端和服务器之间的HTTP连接就会被保持,不会断开(超过Keep-Alive规定的时间,意外断电等情况除外),当客户端发送另外一个请求时,就使用这条已经建立的连接。
从HTTP/1.1起,默认都开启了Keep-Alive,保持连接特性,简单地说,当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接
Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间
心跳包
很多应用层协议都有HeartBeat机制,通常是客户端每隔一小段时间向服务器发送一个数据包,通知服务器自己仍然在线,并传输一些可能必要的数据。使用心跳包的典型协议是IM,比如QQ/MSN/飞信等协议。
心跳包 之所以叫心跳包是因为:它像心跳一样每隔固定时间发一次,以此来告诉服务器,这个客户端还活着。事实上这是为了保持长连接,至于这个包的内容,是没有什么特别规定的,不过一般都是很小的包,或者只包含包头的一个空包。
在TCP的机制里面,本身是存在有心跳包的机制的,也就是TCP的选项:SO_KEEPALIVE。系统默认是设置的2小时的心跳频率。但是它检查不到机器断电、网线拔出、防火墙这些断线。而且逻辑层处理断线可能也不是那么好处理。一般,如果只是用于保活还是可以的。
心跳包一般来说都是在逻辑层发送空的echo包来实现的。下一个定时器,在一定时间间隔下发送一个空包给客户端,然后客户端反馈一个同样的空包回来,服务器如果在一定时间内收不到客户端发送过来的反馈包,那就只有认定说掉线了。
其实,要判定掉线,只需要send或者recv一下,如果结果为零,则为掉线。但是,在长连接下,有可能很长一段时间都没有数据往来。理论上说,这个连接是一直保持连接的,但是实际情况中,如果中间节点出现什么故障是难以知道的。更要命的是,有的节点(防火墙)会自动把一定时间之内没有数据交互的连接给断掉。在这个时候,就需要我们的心跳包了,用于维持长连接,保活。
在获知了断线之后,服务器逻辑可能需要做一些事情,比如断线后的数据清理呀,重新连接呀……当然,这个自然是要由逻辑层根据需求去做了。
总的来说,心跳包主要也就是用于长连接的保活和断线处理。一般的应用下,判定时间在30-40秒比较不错。如果实在要求高,那就在6-9秒。
TCP协议的KeepAlive机制
学过TCP/IP的同学应该都知道,传输层的两个主要协议是UDP和TCP,其中UDP是无连接的、面向packet的,而TCP协议是有连接、面向流的协议。
所以非常容易理解,使用UDP协议的客户端(例如早期的“OICQ”,听说OICQ.com这两天被抢注了来着,好古老的回忆)需要定时向服务器发送心跳包,告诉服务器自己在线。
然而,MSN和现在的QQ往往使用的是TCP连接了,尽管TCP/IP底层提供了可选的KeepAlive(ACK-ACK包)机制,但是它们也还是实现了更高层的心跳包。似乎既浪费流量又浪费CPU,有点莫名其妙。
具体查了下,TCP的KeepAlive机制是这样的,首先它貌似默认是不打开的,要用setsockopt将SOL_SOCKET.SO_KEEPALIVE设置为1才是打开,并且可以设置三个参数tcp_keepalive_time/tcp_keepalive_probes/tcp_keepalive_intvl,分别表示连接闲置多久开始发keepalive的ack包、发几个ack包不回复才当对方死了、两个ack包之间间隔多长,在我测试的Ubuntu Server 10.04下面默认值是7200秒(2个小时,要不要这么蛋疼啊!)、9次、75秒。于是连接就了有一个超时时间窗口,如果连接之间没有通信,这个时间窗口会逐渐减小,当它减小到零的时候,TCP协议会向对方发一个带有ACK标志的空数据包(KeepAlive探针),对方在收到ACK包以后,如果连接一切正常,应该回复一个ACK;如果连接出现错误了(例如对方重启了,连接状态丢失),则应当回复一个RST;如果对方没有回复,服务器每隔intvl的时间再发ACK,如果连续probes个包都被无视了,说明连接被断开了。
Ref:
绛旓細1銆佺郴缁熺殑鎵╁睍鏂瑰紡 2銆侀泦缇ょ被鍨 1銆侀泦缇ょ殑瀹炵幇 2銆丠A闆嗙兢鐨勫疄鐜 HA Nginx Proxy Service闇瑕佺殑鍏抽敭璧勬簮 AIS鍙敤鎬у鍛樼粍锛岃瀹氶珮鍙敤闆嗙兢绾 1銆侀泦缇ょ殑鍒嗚锛坧artion锛夎绉颁箣涓洪泦缇ょ殑鍒嗗尯锛坧artion锛変篃琚О涔嬩负鑴戣锛坆rain-split锛夛級涓轰簡閬垮厤鍑虹幇鍒嗚锛屼簨鍏堝仛濂藉喅绛栵紝鍦ㄦ瘡涓富鏈轰笂閮芥湁涓绁紝绁ㄦ暟澶氱殑...
绛旓細1銆佷粈涔堟槸Keep-Alive妯″紡?鎴戜滑鐭ラ亾HTTP鍗忚閲囩敤鈥滆姹-搴旂瓟鈥濇ā寮,褰撲娇鐢ㄦ櫘閫氭ā寮,鍗抽潪KeepAlive妯″紡鏃,姣忎釜璇锋眰/搴旂瓟瀹㈡埛鍜屾湇鍔″櫒閮借鏂板缓涓涓繛鎺,瀹屾垚涔嬪悗绔嬪嵆鏂紑杩炴帴(HTTP鍗忚涓烘棤杩炴帴鐨勫崗璁);褰撲娇鐢↘eep-Alive妯″紡(鍙堢О鎸佷箙杩炴帴銆佽繛鎺ラ噸鐢)鏃,Keep-Alive鍔熻兘浣垮鎴风鍒版湇鍔″櫒绔殑杩炴帴鎸佺画鏈夋晥,褰撳嚭鐜板鏈嶅姟鍣...
绛旓細Httpd瀹堟姢杩涚▼锛屼竴鑸兘鎻愪緵浜keep-alive timeout鏃堕棿璁剧疆鍙傛暟銆傛瘮濡俷ginx鐨刱eepalive_timeout锛屽拰Apache鐨凨eepAliveTimeout銆傝繖涓猭eepalive_timout鏃堕棿鍊兼剰鍛崇潃锛氫竴涓猦ttp浜х敓鐨則cp杩炴帴鍦ㄤ紶閫佸畬鏈鍚庝竴涓搷搴斿悗锛岃繕闇瑕乭old浣弅eepalive_timeout绉掑悗锛屾墠寮濮嬪叧闂繖涓繛鎺ャ傚綋httpd瀹堟姢杩涚▼鍙戦佸畬涓涓搷搴斿悗锛岀悊搴...
绛旓細浣跨敤keep-alive缂撳瓨涓嶄簡iframe鐣岄潰鍘熷洜 銆1銆戝師鐞嗭細Vue 鐨勭紦瀛樻満鍒跺苟涓嶆槸鐩存帴瀛樺偍 DOM 缁撴瀯锛岃屾槸灏 DOM 鑺傜偣鎶借薄鎴愪簡涓涓釜 VNode鑺傜偣銆傚洜姝わ紝Vue 鐨 keep-alive 缂撳瓨涔熸槸鍩轰簬 VNode鑺傜偣 鑰屼笉鏄洿鎺ュ瓨鍌 DOM 鑺傜偣銆傚湪闇瑕佹覆鏌撶殑鏃跺欎粠Vnode娓叉煋鍒扮湡瀹濪OM涓娿傘2銆戝弬鏁帮細Keep-alive 缁勪欢鎻愪緵浜 include...
绛旓細2.绯荤粺鍙敤鐜囩畻娉曚緥锛 -1涓9锛氾紙1-90%锛*365=36.5澶 ---> 琛ㄧず璇ョ郴缁1骞存椂闂撮噷鏈澶氬彲鑳界殑涓氬姟涓柇鏃堕棿鏄36.5澶 -2涓9锛氾紙1-99%锛*365=3.65澶 ---> 琛ㄧず璇ョ郴缁1骞存椂闂撮噷鏈澶氬彲鑳界殑涓氬姟涓柇鏃堕棿鏄3.65澶 淇濊瘉绯荤粺鍙疄鏃朵笉闂存柇鐨勪娇鐢ㄣ傝蒋浠讹細keepalive keepalive鏄氳繃v...
绛旓細HTTP鐨勯暱杩炴帴鍜岀煭杩炴帴鏈川涓婃槸TCP闀胯繛鎺ュ拰鐭繛鎺ャ傜煭杩炴帴 鐭繛鎺ワ紝椤惧悕鎬濅箟锛屼笌闀胯繛鎺ョ殑鍖哄埆灏辨槸锛屽鎴风鏀跺埌鏈嶅姟绔殑鍝嶅簲鍚庯紝绔嬪埢鍙戦丗IN娑堟伅锛屼富鍔ㄩ噴鏀捐繛鎺ャ備篃鏈夋湇鍔$涓诲姩鏂繛鐨勬儏鍐碉紝鍑℃槸鍦ㄤ竴娆℃秷鎭氦浜掞紙鍙戣姹-鏀跺搷搴旓級涔嬪悗绔嬪埢鏂紑杩炴帴鐨勬儏鍐甸兘绉颁负鐭繛鎺ャ傞暱杩炴帴/http keep-alive 涔熷彨...
绛旓細鍦╤ttp鏃╂湡锛屾瘡涓猦ttp璇锋眰閮借姹傛墦寮涓涓猼pc socket杩炴帴锛屽苟涓斾娇鐢ㄤ竴娆′箣鍚庡氨鏂紑杩欎釜tcp杩炴帴銆備娇鐢keep-alive鍙互鏀瑰杽杩欑鐘舵侊紝鍗冲湪涓娆CP杩炴帴涓彲浠ユ寔缁彂閫佸浠芥暟鎹屼笉浼氭柇寮杩炴帴銆傞氳繃浣跨敤keep-alive鏈哄埗锛屽彲浠ュ噺灏憈cp杩炴帴寤虹珛娆℃暟锛屼篃鎰忓懗鐫鍙互鍑忓皯TIME_WAIT鐘舵佽繛鎺ワ紝浠ユ鎻愰珮鎬ц兘鍜屾彁楂榟ttpd鏈嶅姟鍣ㄧ殑...
绛旓細鏈皬鑺傛垜浠皢浠嬬粛 Vue 鐨勫姩鎬佺粍浠讹紝浠ュ強缂撳瓨 keep-alive 鐨勪娇鐢ㄣ傚寘鎷姩鎬佺粍浠剁殑浣跨敤鏂规硶锛屼互鍙婂浣曚娇鐢 keep-alive 瀹炵幇缁勪欢鐨勭紦瀛樻晥鏋溿傚姩鎬佺粍浠舵槸璁╁涓粍浠朵娇鐢ㄥ悓涓涓寕杞界偣锛屽苟鍔ㄦ佸垏鎹傚姩鎬佺粍浠舵槸 Vue 鐨勪竴涓珮绾х敤娉曪紝浣嗗叾瀹炲畠鐨勪娇鐢ㄩ潪甯哥畝鍗曘俴eep-alive 鏄 vue 鐨勫唴缃粍浠讹紝鑳藉湪缁勪欢鍒囨崲杩囩▼...
绛旓細鍦ㄤ慨鏀瑰巻鍙查仐鐣檅ug鏃讹紝鍦ㄧ埗缁勪欢涓皟鐢ㄤ簡瀛愮粍浠讹紝浣跨敤浜嗗悇绉嶆柟娉曘傞兘璇佹槑瀛愮粍浠剁殑鏁版嵁宸茬粡鏇存柊浜嗐備絾鏄紝瀛愮粍浠跺氨鏄棤娉曢噸鏂版覆鏌擄紝璋冩煡浜嗕袱澶╁啣鎬濊嫤鎯筹紝鎺掗櫎浜嗗悇绉嶉棶棰樸傜粓浜庢煡鍒颁簡涓涓创杩戠殑绛旀锛屽師鏉ュ湪vue涓 璇ョ粍浠跺湪鏈鍒濆氨琚仛鎴愪簡涓叡閫氱粍浠讹紝琚<keep-alive>鍖呬簡璧锋潵锛岀敤鏉ョ紦瀛樼敤鎴锋墍閫夌殑淇℃伅銆傝繖...
绛旓細瀵艰嚧鐨勫師鍥犳槸鍥犱负褰撳紩鍏keep-alive 鐨勬椂鍊欏畠鐨勫间负true鏃讹紝椤甸潰绗竴娆¤繘鍏ワ紝閽╁瓙鐨勮Е鍙戦『搴廲reated-> mounted-> activated锛岄鍑烘椂瑙﹀彂deactivated銆傚綋鍐嶆杩涘叆锛堝墠杩涙垨鑰呭悗閫锛夋椂锛屽彧瑙﹀彂activated銆傛墍浠ヤ細瀵艰嚧C绗竴娆¤繘鍏鐨勬椂鍊欎細鍒锋柊銆備慨鏀笰椤甸潰鐨刡eforeRouteLeave鏇挎崲涓篵eforeRouteEnter褰揃杩涘叆A鐨勬椂鍊欎慨鏀...