java连接access_关于k8s下使用Ingress保持长连接的异常情况排查
寫在前面的話
應(yīng)某位友人需求,幫整理下工作中的發(fā)生的一些值得記錄的文章。于是在友人描述后,為其整理為了文章,供大家一起參考探討。
問題描述
在我們中應(yīng)用有一個(gè)使用到`Http Long Poll`的場(chǎng)景,它需要一個(gè)http請(qǐng)求保持最長(zhǎng)30秒,用于即使獲取到最新的數(shù)據(jù)。在k8s環(huán)境下,發(fā)現(xiàn)應(yīng)該存在偶發(fā)的異常,表現(xiàn)為長(zhǎng)連接沒有正常關(guān)閉,拋出異常:
java.net.SocketException: Unexpected end of file from server問題排查
首先我們先對(duì)應(yīng)用程序的代碼進(jìn)行了排查,并沒有發(fā)現(xiàn)代碼上的bug,可以排除是由于代碼bug導(dǎo)致的這個(gè)問題。
接下來考慮的方式就是抓包,分別在三個(gè)節(jié)點(diǎn)上進(jìn)行抓包:應(yīng)用程序所在pod、ingress-nginx所在pod、服務(wù)端pod。
分別執(zhí)行以下shell腳本:
tcpdump tcp -s 0 -w ./target.cap抓取當(dāng)前網(wǎng)卡下的所有tcp流量,然后使用wireshark進(jìn)行分析。發(fā)現(xiàn)了一個(gè)比較奇怪的現(xiàn)象:
從上到下三張圖片分別是應(yīng)用程序端、nginx端、服務(wù)端的抓包數(shù)據(jù),可以發(fā)現(xiàn)連接的關(guān)閉是由nginx這個(gè)節(jié)點(diǎn)發(fā)起的,應(yīng)用端和服務(wù)端同時(shí)收到了來自nginx的FIN ACK包,要求關(guān)閉當(dāng)前連接,并且都開始執(zhí)行四次握手過程。但是在這個(gè)過程中又發(fā)生了什么異常導(dǎo)致這個(gè)過程并沒有正常完成。
通過觀察大量的抓包數(shù)據(jù)后發(fā)現(xiàn)這個(gè)情況發(fā)生的非常多,但并不是每次都會(huì)導(dǎo)致連接的異常關(guān)閉,大部分還是能夠正常關(guān)閉連接并建立新的連接的。
通過仔細(xì)觀察發(fā)現(xiàn)被異常關(guān)閉的連接,都是發(fā)生在Seq=1的情況下,這個(gè)原因還不是很清楚。
那為什么nginx會(huì)主動(dòng)發(fā)起關(guān)閉連接呢?
Nginx 排查
這時(shí)候首先想到的就是nginx的日志,在翻查了nginx的access.log后,發(fā)現(xiàn)在相同的時(shí)間段,nginx都發(fā)生了reload現(xiàn)象:
backend reload requiredingress backend successfully reloaded難道是由于nginx的reload導(dǎo)致的問題嗎?
通過查詢發(fā)現(xiàn),nginx reload的大致流程為:
- reload命令觸發(fā)nginx生成新的worker進(jìn)程用于接受新的連接請(qǐng)求
- old worker 進(jìn)程不再接受請(qǐng)求
- 對(duì)于仍然存在于old worker進(jìn)程上的keep alive的連接,主動(dòng)發(fā)送FIN ACK 包,通知對(duì)方關(guān)閉當(dāng)前連接
- 當(dāng)所有old worker 上的連接都關(guān)閉或者超過worker-shutdown-timeout所設(shè)定的時(shí)間后,會(huì)關(guān)閉old worker 進(jìn)程
通過查詢k8s上ingress的默認(rèn)配置發(fā)現(xiàn),worker-shutdown-timeout被設(shè)置為了10s,這時(shí)候基本可以確定問題了,由于old worker關(guān)閉的窗口時(shí)間只有10s,如果在這個(gè)時(shí)間段內(nèi)有連接還沒有完成關(guān)閉,而此時(shí)old worker已經(jīng)被關(guān)閉了,client端當(dāng)然不能正常處理請(qǐng)求,因?yàn)樗B接的server端已經(jīng)被提前關(guān)閉了。
解決
找到問題原因了當(dāng)然接下來就是解決了,將worker-shutdown-timeout該字段的值增大為:3600s,即1小時(shí),理論上這個(gè)時(shí)間足夠該worker上的連接全部完成關(guān)閉了。
在調(diào)整了k8s上ingress的這個(gè)參數(shù)后,又進(jìn)行了反復(fù)測(cè)試,并沒有再次發(fā)現(xiàn)同樣的問題,該問題得到解決。
遺留
然后,為什么是Seq=1的連接會(huì)發(fā)生這個(gè)異常,還是沒有完全想明白。
#職場(chǎng)眾生相##職場(chǎng)達(dá)人說##我要上頭條#
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的java连接access_关于k8s下使用Ingress保持长连接的异常情况排查的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 单例 读写锁_你用对锁了吗?浅
- 下一篇: 用java创建窗口程序,创建窗口的应用程