使用 Server-Sent Events(SSE)的 Go 服務在 Kubernetes (k8s) 上部署時,重點在於確保客戶端的連線能夠繫結到特定的後端 Pod,並在升級和更新時能夠優雅地處理。以下是針對你的需求的實現思路:
1. 客戶端與單個 Pod 的繫結
為了保證客戶端連線到一個固定的 Pod,可以使用 Session Affinity 或 Sticky Sessions:
-
Session Affinity (基於IP):
- Kubernetes 的 Service 預設是無狀態的,即負載均衡器會將流量隨機分發到後端 Pod。
- 配置 Service 的
SessionAffinity
為ClientIP
,這樣 Kubernetes 會基於客戶端的 IP 地址,將流量始終分發到同一個 Pod。
-
透過負載均衡器(例如 Ingress/Nginx)實現 Sticky Session: 如果你的應用使用了外部負載均衡器(如 NGINX Ingress Controller),可以透過它支援的 Sticky Session 特性來繫結客戶端和 Pod。例如:
- 對於 NGINX,可以啟用
nginx.ingress.kubernetes.io/affinity: cookie
。
- 對於 NGINX,可以啟用
2. K8s 的優雅退出與升級
在升級或重啟 Pod 時,SSE 的連線中斷會導致客戶端需要重新連線。為了實現優雅退出和升級,可以做以下操作:
(1) 確保 Pod 優雅退出
-
配置 Pod 的
preStop
生命週期鉤子,處理服務關閉邏輯:- 在 Pod 中配置一個
preStop
Hook,通知應用有新的流量即將終止,允許應用清理資源。
- 在 Pod 中配置一個
-
配置
terminationGracePeriodSeconds
,確保 Pod 有足夠時間完成清理:
(2) 啟用 Kubernetes 的滾動更新
透過 Deployment
配置滾動更新策略,確保升級時服務的可用性:
3. 客戶端是否需要重連?
-
重連的必要性:如果 Pod 被銷燬或者負載均衡器將流量切到其他 Pod,客戶端連線會中斷,因此需要支援自動重連邏輯。
-
實現自動重連:
- 在客戶端的 SSE 程式碼中實現斷線重連(一般使用
EventSource
的onerror
和setTimeout
機制):
- 在客戶端的 SSE 程式碼中實現斷線重連(一般使用
-
減小重連影響:在服務端實現連線恢復機制,比如透過快取(Redis)儲存客戶端的狀態,重連後快速恢復狀態。
4. 總結
- 客戶端繫結單 Pod:
- 優先使用 Kubernetes 的
SessionAffinity
或者外部負載均衡器的 Sticky Session 特性。
- 優先使用 Kubernetes 的
- 優雅退出與升級:
- 使用
preStop
鉤子和滾動更新策略,避免客戶端頻繁重連。
- 使用
- 自動重連機制:
- 在客戶端實現斷線重連邏輯,同時在服務端快取狀態,減少重連對服務的影響。
這樣既能實現客戶端與單個 Pod 的繫結,也能在升級和退出時最大程度減少對客戶端的影響。如果還有其他需求或細節,歡迎繼續討論!