1 檢查當前預估服務支持優雅退出
部署預估服務,rollingUpdate,使用Jmeter一直發壓力請求
發現會有很多失敗的請求
確認當前預估服務不支持優雅退出
2 檢查預估服務的框架是否支持優雅退出
當前light4j的版本是1.5.14
發現light4j從1.5.15開始支持graceful shutdown
3 更新版本為1.5.15
啟動預估服務后,直接給java程序發SIGTERM信號,kill -SIGTERM JAVAPID,發現java程序能夠優雅退出
但是通過RollingUpdate,發現java程序沒有優雅退出
4 k8s優雅退出步驟
4.0 刪除POD
4.1 POD進入Terminating狀態
4.2 與此同時,k8s會將POD從對應的service刪除
4.3 與此同時,有preStop hook的容器,會先執行preStop hook, 如果preStop hook的時間超出了Grace period,kubelet會發送SIGTERM
4.4 與此同時,沒有preStop hook的容器,kubelet發送SIGTERM信號給啟動進程
5 Bash Trap 信號
由于預估服務的鏡像是通過bash script啟動,而不是直接在Dockerfile里面執行java程序,由上面的知識可知,POD刪除的時候,kubelet會發送SIGTERM信號給Bash Script進程。
現在會有一個問題,bash是不能傳遞信號的
所以需要在bash腳本里面捕獲信號,并給java程序發SIGTERM信號
6 Lifecycle preStop
通過Bash Trap信號傳遞給JAVA進程后,發現RollingUpdate操作還是會有失敗的請求,壓測qps 500的時候,會有20個請求失敗,表現為503, connect refuse
分析:
請求持續不斷的過來,這個時候進程收到了SIGTERM信號后開始處理沒有完成的請求,但是在切流量的過程中,就是kubelet發送SIGTERM信號和把POD從service拿掉的過程中,有一點請求漏過來了
所以需要確保切流量之后,進程收到SIGTERM之前,不要有流量進來。
加上lifecycle preStop
再次測試,RollingUpdate幾次,發現沒有失敗的請求了