springboot + websocket + redis實現多服務器消息主動推送

集成的東西就不多講了,導入依賴jar包,然後codeing就行了,主要說說過程中遇到的幾個坑。

第一個坑就是多服務器的問題,由於項目是多節點通過nginx分發請求來實現的,所以會導致長連接建立在一臺服務器上,後續的請求回被分發到另一臺服務器上,但是當前服務器並沒有建立長連接,導致消息發送不到前端。

首先想到的方法是websocket的session共享,通過將session序列化到redis裏來實現,但是websocket的session不支持序列化,這個方法pass。然後想到隊列來解決,通過發佈消息,然後訂閱的流程,這樣多臺服務器都能訂閱到消息,然後都去發送消息,這樣就能解決了。但是感覺這個用消息隊列太大材小用了,就想到了redis的訂閱/發佈功能,將消息發不到redis的指定頻道上面,然後再redis的配置文件中配置訂閱就可以,這樣多臺服務器定拿到了消息內容,都去發送,只有建立了長連接的那臺服務器才能發送成功,這樣就解決了多服務器消息發送不準確的問題了。

 

第二個坑是建立長連接在一臺服務器上,前端調用send給後臺發送消息有可能被分發到另一臺服務器上,由於前端隔一分鐘會發送一次請求,來確認長連接有沒有斷,斷了的話會進行重連,如果請求被分發到了另一臺服務器上的話,這樣消息就會發送失敗,前臺就不能確定是請求分發的問題還是真的是長連接斷了。最後採取的解決辦法是,nignx固定ip請求到一臺服務器上。

 

第三個坑是springboot部署到服務器上啓動之後,主程序的run方法之後的代碼沒有執行,導致websocket需要的應用上下文對象沒有注入進去,導致連接websocket報錯了。在本地啓動項目,主程序的run方法後面的代碼是可以執行的,不知道爲什麼到服務器上就不能執行了,最後採用了遠程調試jar包的方法,定位到了錯誤。解決辦法是既然後面的代碼不能執行,那就把代碼寫到run方法的前面去,給springApplication對象添加了一個監聽,實現ApplicationListener接口,這樣就能在啓動的同時拿到應用上下文對象了。

解決了這三個坑之後,websocket多服務器下實現消息的主動推送就完成了。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章