首頁 >運維 >Nginx >nginx代理socket.io服務的坑怎麼解決

nginx代理socket.io服務的坑怎麼解決

王林
王林轉載
2023-05-13 12:43:131818瀏覽

nginx代理了兩台socket.io伺服器。 socket.io的工作模式是polling升級到websocket

現象

透過nginx請求服務時,出現了大量的400錯誤,有時能升級到websocket,有時候會一直報錯。但直接透過 ip 連接埠 存取時,100%能成功。

nginx代理socket.io服務的坑怎麼解決

分析

sid

sid是我們這個問題的關鍵。在初始建立連線時(polling模式就是在模擬一個長連線),客戶端會啟動這樣的要求:

https://***/?eio=3&transport=polling&t=1540820717277-0

服務端收到後會建立一個對象,綁定在這個連接上,同時傳回一個sid(session id),來標記這個會話。會話指什麼呢,會話是一連串的交互,這些交互之間是有聯繫的,在我們這個場景下就是,下一次的http請求到來,我需要找到之前綁定在理論上的長連接(這裡還沒有websocket,所以是理論上的)上的那個物件。我們知道http請求是無狀態的,每個請求之間獨立,所以socket.io引入了sid來做這件事。服務端收到請求後會產生一個sid,看下response:

複製程式碼 程式碼如下:

{"sid":"eogal3frqlptoalp5est","upgrades":["websocket"] ,"pinginterval":8000,"pingtimeout":10000}

之後每次要求都需要帶上這個sid,建立websocket請求的連線也不例外。所以說,sid是polling,以及polling升級到websocket的關鍵。這之後的請求類似:

https://***/?eio=3&transport=polling&t=1540820717314-1&sid=eogal3frqlptoalp5est

or

wss://***/?eio=3&transport=websocket&t=1540820717314-1&sid=eogal3frqlptoalp5est

那麼問題來了,如果請求是帶上的sid不是服務端產生的會怎麼樣呢?服務端會不認識,給你回傳一個400,並告訴你

invalid sid

我們遇到的便是這個問題,nginx預設的負載平衡策略是輪詢,所以請求有可能會打到不是生成這sid的機器上去,這時候我們就會收到一個400,如果運氣好,可能也會打到原來的機器上,運氣更好一點,甚至能堅持到websocket連接建立。

解決

這裡提出兩種方案

  1. #nginx的負載平衡採用ip_hash,這樣可以保證一個客戶端的請求都走到一台伺服器上

  2. 不使用polling模式,只使用websocket

##這兩種方案各有利弊。第二種顯而易見,不支援websocket的古老瀏覽器和客戶端將沒辦法運作。第一種的問題隱藏得比較深,試想,如果你增減了機器會怎樣,這時候ip_hash策略的模將變化,之前的連接將全部失效,而對於微服務,擴增容是很頻繁的操作(特別是產品處於發展期),這種有損的擴縮容很大機率是不能接受的。

以上是nginx代理socket.io服務的坑怎麼解決的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除