#1247·skynet

最近在阿里雲上轉用 skynet built in https 後,出現奇怪的 socket 問題

Author: tomlau10Created Oct 12, 2020Updated Dec 29, 2025

抱歉因為這個問題奇怪非常 無法定位到問題在哪裡,很難作出精簡的描述 請容我用比較長的篇幅做描述


背景

  • skynet 版本: 1.3.0rc release tag 的 commit
  • 我們的項目 在國外使用 google kubernetes engine (GKE) 在國內使用阿里雲 container kubernetes (ACK)
  • 在早期由於 skynet 框架沒有 https 支援 我們額外用 nodejs 寫了個 https proxy micro service 在另外的 container 跑 並將 server 所有 http / https request 都用 http request + 改 header host 方式 先發到這個 https proxy GKE 及 ACK 2邊也是這樣使用,一直正常
  • 針對 http(s) request,我們是有個 httpc skynet service 來集中做管理 並限制並發連接數上限 256 超過的話,http request 會在該 service 排隊處理 不過正常情況下,最大並發連接多數 < 5的
  • 到7月左右我們修改了提到的 httpc service 的代碼 可以直接使用 skynet built in https 去掉 nodejs proxy 的使用 並且測試通過後於 8月底 server 更新版本推出 奇怪的 socket 情況就開始出現了。。。

問題

  • GKE 上的 server 一直正常 (直到今天也正常)
  • 但是 ACK 上偶爾會有大量玩家回報 lag / 爆 ping (幾乎是全個服,客服從當前世界頻截圖得出這樣的判斷)
  • 不論人多還是人少 / 早上下午或凌晨都曾出現 一開始是週末才出現,嚴重時一天可以爆 ping 幾次 後來是隔天就出現一次
  • 當出現問題時,server log 會有一堆 socket error / closed 的 msg
2020-09-13 13:40:54.051721 [:00000013] socket: error on 107963 Connection reset by peer
2020-09-13 13:40:54.057327 [:00000013] socket: error on 107965 Connection reset by peer
2020-09-13 13:40:54.059430 [:00000013] fd = 107963, [Socket Error]
2020-09-13 13:40:54.060925 [:00000013] fd = 107965, [Socket Error]
2020-09-13 13:41:20.986025 [:00000013] socket: error on 108220 Connection reset by peer
2020-09-13 13:41:20.988263 [:00000013] socket: error on 108222 Connection reset by peer
2020-09-13 13:41:20.994423 [:00000013] fd = 108220, [Socket Error]
2020-09-13 13:41:20.996318 [:00000013] fd = 108222, [Socket Error]
...

這裡 service 13 是我們的 httpd service 做法是參考 skynet/example/simpleweb.lua 用另外端口來監聽外部 command eg shutdown / reboot / gm 後台對 server 做操作 且這個端口跟 game client 連接端口不相同 (下個部分再解釋為什麼這 httpd service 會經常有這麼多 socket 嘗試連接)

早期的測試

  • 由於 GKE 並沒有出現問題,所以最初懷疑跟 ACK 有關 ACK 的 loadbalancer 針對 exposed tcp port 有個 不能關掉的 health check loadbalancer 會不斷做 health check,這解釋了 httpd service 經常都會有 socket connect 而當連接失敗被判 unhealthy,loadbalancer 就會不再 route 該端口 的 traffic 到該 instance
  • 上邊的 service 13 socket error log 應該就是 health check 的 connection 而出現 error 感覺 是果不是因 即 network 異常,所有 connection 都被 pause / close 了 因此 log 才會出現 error 而並非 health check error 導致 container network 被中斷
  • 上點提到 httpd 端口跟 server 端口不相同 若果單純 httpd 端口出異常,理應不影響 game client 端口的 但當爆 ping 情況出現時,總有上述的 error log 相伴 所以暫時能解釋的,要麼是 skynet 框架中的 socket 處理有異常 要麼是 ACK 中 game server container 網絡有異常 單純到這裡來看,後者概率較高 因為同份代碼,在 GKE 下用相近 deployment 方式都沒有異常
  • 所以我們試著修改 ACK deployment 中的 health check interval 和加大 unhealthy 判定的 threshold 但完全沒有改善到問題。。。

後期的測試

  • 這個問題一直沒進展
    直到9月底左右,回想起問題是於 8月底更新 才出現 背景中提到當時 改用了 built in https 由於十一假期臨近,想到什麼方式也只能試試 於是抱著測試的心態,revert 了上述改動,轉回原有的 https proxy 方式 結果竟然問題就消失了
  • 然後就這樣過了愉快的十一假期
    到上週六早上 server 例行重啟前 我嘗試再改回去用 built in https 結果不到一天再次出現爆 ping 情況 ... server log 情況同前
2020-10-10 18:37:14.192075 [:00000013] socket: error on 127594 Connection reset by peer
2020-10-10 18:37:14.200870 [:00000013] socket: error on 127596 Connection reset by peer
2020-10-10 18:37:14.202783 [:00000013] fd = 127594, [Socket Error]
2020-10-10 18:37:14.203821 [:00000013] fd = 127596, [Socket Error]
2020-10-10 20:25:45.290115 [:00000013] socket: error on 135587 Connection reset by peer
2020-10-10 20:25:45.290139 [:00000013] socket closed
2020-10-10 23:18:56.362953 [:00000013] socket: error on 149113 Connection reset by peer
2020-10-10 23:18:56.363672 [:00000013] socket: error on 149115 Connection reset by peer
2020-10-10 23:18:56.363847 [:00000013] fd = 149113, [Socket Error]
2020-10-10 23:18:56.364811 [:00000013] fd = 149115, [Socket Error]
...

嚇得我慌忙又換回去 https proxy 的做法
然後週日就又回復正常了

暫時結論

  • 貌似只有使用 skynet built in https 時,才會在 ACK 出現這個問題 => skynet 問題,ACK 未必有問題
  • 然而 GKE 上同一套代碼,無論運行 https proxy 還是 skynet built in https 都沒事 => skynet 沒問題,是 ACK 問題
  • 但以上2點好像又互相予盾 因而無從判斷究竟是單純 skynet https 還是單純 ACK 的問題 又或是 ACK + skynet https 才會出問題。。。 並且目前也沒有進一步訊息判斷 哪一個環節 出問題

請問各位有遇過這種奇怪情況嗎? 有沒有 debug 方向建議? 個人還是希望能用上 skynet https 的 這樣 server 架構可以簡潔點,去掉 nodejs https proxy