我研究過大猩猩/ websocket包的Godoc。如何確保Golang大猩猩的併發WebSocket包
在Godoc它明確提出
併發 連接支持一個併發的讀寫器和一個並行的作家。 (NextWriter,SetWriteDeadline,WriteMessage,WriteJSON,EnableWriteCompression,SetCompressionLevel)並且不超過一個goroutine調用讀取方法(NextReader,SetReadDeadline,ReadMessage ,ReadJSON,SetPongHandler,SetPingHandler)。
Close和WriteControl方法可以與所有其他方法同時調用 方法。
然而,在由包提供的示例中的一個
func (c *Conn) readPump() {
defer func() {
hub.unregister <- c
c.ws.Close()
}()
c.ws.SetReadLimit(maxMessageSize)
c.ws.SetReadDeadline(time.Now().Add(pongWait))
c.ws.SetPongHandler(func(string) error {
c.ws.SetReadDeadline(time.Now().Add(pongWait)); return nil
})
for {
_, message, err := c.ws.ReadMessage()
if err != nil {
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway) {
log.Printf("error: %v", err)
}
break
}
message = bytes.TrimSpace(bytes.Replace(message, newline, space, -1))
hub.broadcast <- message
}
}
此行
c.ws.SetPongHandler(func(string) error {
c.ws.SetReadDeadline(time.Now().Add(pongWait)); return nil
})
和這條線
_, message, err := c.ws.ReadMessage()
似乎是不同步的,因爲第一行是一個回調函數,因此它應該在的goroutine調用在包中創建和第二行是在調用serveWs
更重要的是夠程執行,應該怎麼確保不超過一個goroutine同時調用SetReadDeadline
,ReadMessage
,SetPongHandler
,SetPingHandler
?
我嘗試使用互斥鎖並在每次調用上述函數時將其鎖定,並在事後解鎖,但很快我發現問題。通常(在這個例子中)ReadMessage
在for循環中被調用。但是,如果Mutext在ReadMessage之前被鎖定,那麼沒有其他讀取功能可以獲取鎖定並執行,直到接收到下一條消息爲止
有沒有更好的方法來處理這個併發問題?提前致謝。
在包內部學習之後,如果我沒有誤讀它,ping和pong回調函數實際上是在與調用ReadMessage()相同的GoRoutine中執行的。所以這個例子仍然保證了併發性。而SetPingHandler()和SetPongHandler()它們也需要同步,但在這個例子中,它們在任何ReadMessage()被調用之前被調用,所以它沒問題。 – user7509214