在工作生產中,很多業務需要用到websocket
作爲前後端之間交互的方式, 以下總結一些遇到的問題及相關鏈接:
- 認證問題:
- 瀏覽器端的javascript 的websocket建立連接的api較爲單一:
此接口難以攜帶認證憑證等信息。在websocket的var aWebSocket = new WebSocket(url [, protocols])
initial handshake
無法提供自定義的頭部信息. 因此, 要想在建立websocket
之前實現身份驗證,讓initial handshake
攜帶token
等驗證信息, 辦法有如下:url
上添加query
, 即"wss://somedomain.com?token=<token>"
,詳見此鏈接- 對於
websocket
請求的url
與domain
一致的情況, 在cookies
中保存認證token
, 發起initial handshake
也會自動攜帶cookies
- 可用性問題:
- 使用應用層心跳機制, 即客戶端定時發送
ping
, 服務端響應pong
。 - 客戶端實現斷線重連。
- 使用應用層心跳機制, 即客戶端定時發送
- 性能問題:
-
若涉及到複雜的
websocket
服務端的業務處理邏輯, 可根據需要在handler
內分別啓動運行讀和寫信息的goroutine
, 在這種情況下,可對服務端的開銷和效率作優化。 主要是圍繞goroutine和IO作優化。 -
若業務需求不大, 在
handler
處用for循環來處理即可,即每個ws
連接以單線程方式同步處理接收和發送,詳見此鏈接,
-
c, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Print("upgrade:", err)
return
}
defer c.Close()
for {
mt, message, err := c.ReadMessage()
if err != nil {
log.Println("read:", err)
break
}
log.Printf("recv: %s", message)
err = c.WriteMessage(mt, message)
if err != nil {
log.Println("write:", err)
break
}
}
- 多實例部署問題:
kubernetes nginx controller
原生支持websocket
連接, 因此若http/https
服務在K8s
運行正常, 服務端能收正常收發http/https
報文, 且配置tls
證書正確,即可支持websocket
連接。但是websocket
連接會在默認時間內(1 min
)被服務端顯式關閉, 因此需要額外在ingress上配置連接超時參數, 其餘k8s
對象如service
和deployment
等不要作額外配置,即,在不配置sticky sessions的情況下, 也不會出現同一個ws
連接會請求到後端的不同pod
,具體原因詳見此鏈接。
Reference:
- https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/WebSocket#Syntax
- https://stackoverflow.com/questions/4361173/http-headers-in-websockets-client-api
- https://yeti.co/blog/token-based-header-authentication-for-websockets-behind-nodejs/
- https://speakerdeck.com/eranyanay/going-infinite-handling-1m-websockets-connections-in-go
- https://www.freecodecamp.org/news/million-websockets-and-go-cc58418460bb/
- https://github.com/gorilla/websocket/blob/master/examples/echo/server.go
- https://kubernetes.github.io/ingress-nginx/user-guide/miscellaneous/#websockets
- https://github.com/kubernetes/ingress-nginx/blob/master/docs/examples/affinity/cookie/README.md
- https://stackoverflow.com/questions/15266702/proxying-websockets-with-tcp-load-balancer-without-sticky-sessions