背景:
一個中小型H5游戲,后端使用基於 netty 的socket服務
服務端 分為 分發服務器 & 業務服務器,業務服務器可負載
用戶客戶端與分發服務器連接
分發服務器再作為客戶端與每台業務服務器連接
為了方便快速得知服務宕機的情況,我打算在服務器上做一個宕機通知
因為 分發服務器與業務服務器都處於連接狀態,在連接斷開時都會觸發 channelInactive 方法,所以我預想的是
一旦分發服務器宕機,則業務服務器可以監聽到連接斷開,然后做出警報通知
反之亦然,用分發服務器做業務服務器的宕機警報
代碼寫完測試過后,功能可以沒什么問題,於是更新至線上,過了一天以后,問題就來了
我收到了 業務服務器的警報,說分發服務器宕機了,緊張的我打開游戲看了看,毛事沒有,分發服務器好好的,連接也是正常的
看了一下日志,業務服務器的 channelInactive 方法確實被觸發了。但是是什么原因導致觸發的呢?
// 問題先記下來,正在解決中。。解決完了回來更新。
問題找到了,是因為重啟業務服務時,直接kill了進程,導致,分發服務與業務服務之間的socket沒有正常斷開連接,隨后的某個時刻,分發服務收到了一個請求,試圖將請求轉發到此業務服務時,就出現了異常並觸發了斷開連接,所以就產生了分發服務與當前業務服務斷開連接的假象,其實是與以前已經關閉的業務服務斷開,當前的連接是正常的。
解決方案:在分發請求之前,驗證 channle.isActive()。如果false,則主動做出相應處理。
相關代碼:
時隔多日補充:
自從根據上面的做法實施過后的幾天里, 錯誤的宕機警報確實減少了, 且上線后的正式服務沒有再有過誤報的情況了.... 但是...
測試服誤報邏輯服務宕機的問題沒有了, 但是卻出現了邏輯服務誤報分發服務宕機的情況.並且當我查看后發現分發服務和邏輯服務都是好好的, 也不存在上面所說的老連接未正常斷開的情況!!!...WTF...冤冤相報何時了????
隨后我陷入了沉思, 為什么正式服好好的, 測試服卻會出現這種問題??? 他們有什么區別?
經過我交警腦汁的思考,排錯....終於我還是發現了一個問題!!
正式服: 分發服務開放外網鏈接, 邏輯服務只允許內網連接(也就是只允許分發服務連接)
測試服: 分發服務與邏輯服務皆允許外網連接且都開放了端口(因為貪圖方便, 放在一台服務器上了)
因為從正常邏輯上講, 只有分發服務才會去連接邏輯服務, 所以邏輯服務默認只要是連接了我的那就是分發服務, 並且在任何連接斷開時發出警報!!
由此引發問題: 因為開放了外網端口, 所以有許多網絡爬蟲啊, 端口掃描等等奇奇怪怪的連接發生, 然而邏輯服務卻傻乎乎的把他們當成是分發服務......並且在連接中斷后發出警報!
就這樣, 問題終於找到了, 然后就要去解決了, 怎么解決呢? ...那就讓邏輯服務好好擦亮眼睛吧!
解決方案
分發服務在連接邏輯服務成功后, 需要發送一個指令告訴邏輯服務: 我是分發服務, 我的身份是*****, 這樣邏輯服務就知道這個連接是誰了!