前言
近期在工作中,遇到了一次很有意思的內(nèi)存泄漏靶瘸,把排查過程和思路記下來苫亦,供大家參考和學習,如有不正確的怨咪,歡迎指正屋剑。
起因
最近幾天很多半托管客戶,突然報連接服務失敗诗眨,登上服務器后查看內(nèi)存很高唉匾,為了讓客戶盡快恢復業(yè)務,運維同事第一時間選擇了重啟匠楚。
重啟后巍膘,內(nèi)存肉眼可見的速度漲了上來,研發(fā)同事判斷后芋簿,可能之后又需要重啟峡懈,臨時給客戶部署了備用服務。(不管三七二十一先擴容)
冰山一角
-
??日志
Too many open files 代表已經(jīng)到了當前進程可以打開的最大文件數(shù)益咬,第一時間選擇了先加大當前進程打開的最大文件數(shù)逮诲,讓后續(xù)的請求可以正常處理
echo?-?n?"Max?open?files=85535:85535"?>?/proc/pid/limits
通過命令查看當前已經(jīng)打開的文件數(shù)
lsof?-p?pid?|?wc?-l43326
正常的進程不可能打開這么多fd帜平,所以應該存在連接泄漏
lsof?-?p?pid?|?grep?can't?identify?protocol
jstack打印當前的堆棧
jstack?-l?pid?>?pid.txt
找到當前堆棧中使用http地方,排查代碼梅鹦,檢查代碼有可能沒close連接的地方裆甩。
修復好代碼,上線后齐唆,重啟進程嗤栓,在觀察發(fā)現(xiàn)內(nèi)存很平穩(wěn),打開的文件數(shù)也逐漸平穩(wěn)箍邮。
你以為這么簡單就完事了茉帅?如果就這么簡單,我就不會寫這篇文章了锭弊。
第二天堪澎,第三天陸續(xù)有其他半托管客戶找過來,同樣的問題味滞,內(nèi)存泄漏樱蛤,最大文件數(shù)一直居高不下,直到達到限制剑鞍。
和上面的客戶一樣昨凡,修復同樣的代碼后,均都恢復了正常蚁署。
提問
1便脊、為什么都是半托管的客戶報這個問題,公有云未有客戶反饋
2光戈、這些半托管的客戶為了穩(wěn)定哪痰,代碼已經(jīng)很久沒升級,代碼都是2021年的田度,為什么都跟商量好似的妒御,一起報問題解愤,難道我有bug吸引體質(zhì)镇饺?
3、為什么這些客戶送讲,物理機房隔離狸吞,問題表象卻都一樣圣絮?
4、客戶需要一個合理的解釋,我總不能說網(wǎng)絡抽風了吧维蒙?
所有不合理的地方,其實都有合理的解釋
半托管:后端服務和敏感數(shù)據(jù)在客戶機房袭景,前端網(wǎng)頁在公有云挡育。
理性分析
由于都是半托管客戶,又都是因為fd太多,導致的內(nèi)存泄漏扣癣。
那我們有一點是可以肯定的惰帽,那就是連接過多,導致fd激增父虑,既然是網(wǎng)絡問題该酗,那我們就使用 萬能法則 (遇事不決,先抓個包)
tcpdump?-i?any?tcp?-w?tcp.pcap
抓完包后使用wireshark進行分析士嚎,發(fā)現(xiàn)有很多OPTIONS請求呜魄。
waht? 這個請求是使用jsonp的方式,為什么會存在options請求
在查看原本GET請求的內(nèi)容
然后在公有云相同的服務器抓了個包莱衩,發(fā)現(xiàn)只有get請求爵嗅,沒有options請求,那可以說明這個options請求笨蚁,只有在出現(xiàn)問題的半托管機器上有
但是我們有那么多半托管客戶操骡,報問題的卻只有幾個
大膽假設
我們都知道options是瀏覽器發(fā)的跨域預檢請求,那說明這件事和瀏覽器脫不了干系赚窃,通過抓包文件來看册招,發(fā)options請求的瀏覽器的版本都是chrome 104版本。
嗯勒极,chrome居然又更新了是掰,我們大膽假設一下,內(nèi)存泄漏和chrome版本有關系辱匿。
為了驗證我的假設键痛,我找到了chrome的升級說明。
嗯匾七,果然只有假設才會有答案
附上chrome的升級說明絮短。如果打不過也可以看下github的這個說明
??大概意思就是說:
如果你從公網(wǎng)訪問私有網(wǎng)絡,那么會在chrome104版本昨忆,發(fā)option進行預檢丁频,該請求帶有一個新的標頭(Access-Control-Request-Private-Network: true)。在這個初始階段邑贴,這個請求被發(fā)送席里,但是目前階段你收到可以不響應,后續(xù)的請求還是會正常發(fā)送拢驾,并不會影響到你的業(yè)務奖磁,只會在 DevTools 中顯示警告
下圖帶有private的為私有網(wǎng)絡
好家伙我一看,我處理的半托管客戶繁疤,ip地址都為192x咖为,172x秕狰,10x,全都屬于私有網(wǎng)絡躁染,又都從公有云的網(wǎng)站發(fā)起請求封恰,正好符合104版本描述的條件。
而且服務的代碼比較老褐啡,收到options請求诺舔,沒有正常釋放,導致了內(nèi)存泄漏备畦。
天啦擼低飒,你能想到一個內(nèi)存泄漏,居然是因為chrome自動更新導致的嗎懂盐?
總結(jié)
1褥赊、為什么都是半托管的客戶報這個問題,公有云未有客戶反饋
答:只有半托管客戶滿足公有ip訪問私有ip的條件莉恼,且部分用戶的chrome瀏覽器自動更新了
2拌喉、這些半托管的客戶為了穩(wěn)定,代碼已經(jīng)很久沒升級俐银,代碼都是2021年的尿背,為什么都跟商量好似的,一起報問題捶惜,難道我有bug吸引體質(zhì)田藐?
答:chrome自動更新導致
3、為什么這些客戶吱七,物理機房隔離汽久,問題表象卻都一樣?
答:chrome自動更新導致踊餐,代碼版本都比較老
4景醇、客戶需要一個合理的解釋,我總不能說網(wǎng)絡抽風了吧吝岭?
答:不知道chrome發(fā)表的版本說明三痰,能不能說服客戶
5、是不是只有chrome104版本受影響苍碟?
答:應該和chrome104同版本的其他瀏覽器也會受影響酒觅,測試edge也會有影響
6、如何判斷我的網(wǎng)站受到影響微峰。
答:首先需要滿足公網(wǎng)訪問私有網(wǎng)絡的條件,其次可以在chrome請求或者抓包中抒钱,查看請求頭有沒有該標頭
7蜓肆、訪問內(nèi)網(wǎng)的https受影響不
答:上圖就是訪問https的服務颜凯,會受到影響
8、設置chrome://flags/#block-insecure-private-network-requests 可以避免不
答:我測試104版本沒效果
9仗扬、服務端如何兼容
答:服務器應檢查是否存在Access-Control-Request-Private-Network: true標頭症概。如果請求中存在此標頭,則服務器應檢查Origin標頭和請求路徑以及任何其他相關信息(例如Access-Control-Request-Headers)以確保請求是安全的早芭。通常彼城,您應該允許訪問您控制下的單個源。
一旦您的服務器決定允許該請求退个,它應該響應204 No Content(或200 OK)必要的 CORS 標頭和新的 PNA 標頭募壕。這些標頭包括Access-Control-Allow-Origin和Access-Control-Allow-Private-Network: true,以及其他需要的標頭语盈。
響應示例
HTTP/1.1?204?No?Content
Access-Control-Allow-Origin:?https://foo.exampleAccess-Control-Allow-Private-Network:?true
或者
HTTP/1.1?200?No?Content
Access-Control-Allow-Origin:?https://foo.exampleAccess-Control-Allow-Private-Network:?true
10舱馅、服務端要不要兼容更新
答:我認為是有必要的,現(xiàn)在chrome發(fā)起options請求刀荒,你響應或者不響應都不會阻止后續(xù)的請求代嗤,但是如果他那天在自動更新,你如果未正常處理options請求缠借,就不發(fā)送后續(xù)業(yè)務請求干毅,
嗯。泼返。溶锭。我已經(jīng)聯(lián)想到了一大部分程序員連夜加班修bug的場面了。
本文使用 文章同步助手 同步