Golang websocket服務端實現注意點記錄

在工作生產中,很多業務需要用到websocket作爲前後端之間交互的方式, 以下總結一些遇到的問題及相關鏈接:

  • 認證問題:
    - 瀏覽器端的javascript 的websocket建立連接的api較爲單一:
    var aWebSocket = new WebSocket(url [, protocols])
    
    此接口難以攜帶認證憑證等信息。在websocket的initial handshake無法提供自定義的頭部信息. 因此, 要想在建立websocket之前實現身份驗證,讓initial handshake 攜帶token等驗證信息, 辦法有如下:
    • url上添加query, 即"wss://somedomain.com?token=<token>",詳見此鏈接
    • 對於websocket請求的urldomain一致的情況, 在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對象如servicedeployment等不要作額外配置,即,在不配置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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章