【故障公告】推薦系統中轉站撐爆伺服器 TCP 連線引發的故障
上週五下午,我們在部落格中部署了推薦系統,在博文下方顯示“最新IT新聞”的地方顯示自動推薦的關聯博文。我們用的推薦系統是第四正規化的推薦服務,我們自己只是搭建了一個推薦系統中轉站(基於 ASP.NET Core),接收來自部落格前端的請求,然後將請求轉發給第四正規化的推薦服務,並將響應內容轉發給部落格前端。
這個中轉站的功能非常簡單,就是一個 http 請求/響應搬運工,簡單到讓我們忽視了它會給伺服器帶來的潛在壓力 —— 一邊與部落格前端的請求/響應會產生大量 TCP 連線,一邊與推薦服務的請求/響應會產生大量 TCP 連線,而且由於推薦資料的動態變化特點而無法使用快取。在同樣的負載下,這個搬運工會比其他應用消耗更多的 TCP 連線。
從上週五發布到昨天,由於訪問量沒有達到特別高的高峰,所以問題沒有暴露。今天上午訪問量達到更高峰時,問題出現了。部署在 docker swarm 叢集上的很多站點時不時地出現 500 錯誤,日誌中頻繁出資料庫或 memcached 伺服器網路連線失敗的錯誤。開始我們還以為是之前多次遇到過的節點伺服器不穩定問題引起的,於是將叢集中的伺服器一臺一臺下線、重啟、上線,但這樣操作之後問題依舊。接著把懷疑物件放到了 memcached 伺服器,是不是 memcached 伺服器不穩定引起,於是重啟 memcached 伺服器,但問題依然。
在用完之前的招式、百思不得其解之時突然想到可能是叢集中某些伺服器的 TCP 連線過多達到了限制(Linux 的限制或者阿里雲的限制),如果站在這個角度分析,不管故障的表現還是日誌中的錯誤都可以得到合理的詮釋。於是立馬鎖定了原因,然後自然就想到了我們上週五部署的推薦系統中轉站,趕緊將其下線,500 錯誤即刻消失,叢集上的所有應用都會恢復正常。
非常抱歉,這次故障給大家帶來麻煩了,請大家諒解。我們會吸取這次上線推薦系統時不夠深思熟慮、過於輕敵的教訓,認真反思,努力改進自己的工作。
更新:後來升級至 .NET Core 2.2 Preview 3 ,並將 System.Net.Http 升級至 4.3.4 之後沒出現這個問題,問題與 https://github.com/dotnet/corefx/pull/32568 有關。