日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪(fǎng)問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > javascript >内容正文

javascript

Springboot整合Websocket遇到的坑_websocket session不支持序列化,无法存储至redis_Websocket相关问题总结(Session共享,用户多端登录等)

發(fā)布時(shí)間:2025/3/12 javascript 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Springboot整合Websocket遇到的坑_websocket session不支持序列化,无法存储至redis_Websocket相关问题总结(Session共享,用户多端登录等) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Springboot整合Websocket遇到的坑

一、使用Springboot內(nèi)嵌的tomcat啟動(dòng)websocket

1.添加ServerEndpointExporter配置bean

@Configuration public class WebSocketConfig {/*** 服務(wù)器節(jié)點(diǎn)** 如果使用獨(dú)立的servlet容器,而不是直接使用springboot的內(nèi)置容器,就不要注入ServerEndpointExporter,因?yàn)樗鼘⒂扇萜髯约禾峁┖凸芾? @return*/@Beanpublic ServerEndpointExporter serverEndpointExporter() {return new ServerEndpointExporter();}}

2.在接收連接的類(lèi)加上@ServerEndpoint和@Component

@ServerEndpoint("/connect") @Component

二、使用外部tomcat容器啟動(dòng)websocket

1.刪除ServerEndpointExporter配置bean

2.接收連接的類(lèi)刪除@Component

三、websocket關(guān)閉連接異常

如果客戶(hù)端關(guān)閉了websocket,但服務(wù)端沒(méi)有監(jiān)聽(tīng)到關(guān)閉事件,即onClose方法沒(méi)有調(diào)用,這是會(huì)發(fā)生的情況

此時(shí)如果服務(wù)端向客戶(hù)端推送消息,會(huì)出現(xiàn)異常告訴開(kāi)發(fā)者:關(guān)閉了一個(gè)連接,并重新調(diào)用onClose方法

websocket 分布式開(kāi)發(fā),websocket session不支持序列化,無(wú)法存儲(chǔ)至redis

單websocket服務(wù)器在面對(duì)并發(fā)量很大時(shí)壓力會(huì)很大,而且session儲(chǔ)存在Map中,內(nèi)存壓力也會(huì)很大。于是考慮分布式。

但是分布式存在websocket session共享問(wèn)題,于是考慮radis存儲(chǔ)session,但是遇到websocket session不支持序列化,無(wú)法存儲(chǔ)。

一番搜索后有了以下幾個(gè)方案

  • 使用spring session自定義session.

  • 既然無(wú)法序列化session,那還是存儲(chǔ)在Map中,各服務(wù)器通過(guò)發(fā)布訂閱變相實(shí)現(xiàn)共享websocket session.

  • Websocket相關(guān)問(wèn)題總結(jié)(Session共享,用戶(hù)多端登錄等)

    我們?cè)谑褂脀ebsocket的時(shí)候其實(shí)主要面對(duì)的問(wèn)題就是session共享的問(wèn)題:

    不管是基于Spring實(shí)現(xiàn)的Websocket的WebsocketSession

    還是基于JDK實(shí)現(xiàn)的Session

    亦或者基于netty實(shí)現(xiàn)的ChannelHandlerContext

    用圖來(lái)描述下場(chǎng)景吧:

    OK,大家看到這個(gè)圖了,差不多應(yīng)該明白了Session共享應(yīng)該怎么處理了。其實(shí)原理很簡(jiǎn)單:

    1、我們知道nginx有IP保持的功能,其實(shí)這個(gè)功能就能解決大部分場(chǎng)景的Session共享問(wèn)題。 但是某些極限情況下還是會(huì)有問(wèn)題,比如在瀏覽器沒(méi)有關(guān)閉的情況下同一個(gè)用戶(hù)更換了網(wǎng)絡(luò)的情況導(dǎo)致IP變了,或者對(duì)于某些網(wǎng)絡(luò)的IP是變動(dòng)的情況下,就會(huì)出現(xiàn)Session找不到的情況。

    2、基于上述nginx的原理我們可以進(jìn)行優(yōu)化,還是單例存儲(chǔ)。那么要操作的時(shí)候,我告訴所有的服務(wù)端,你們?nèi)フ疫@個(gè)用戶(hù)的Session,并把消息帶過(guò)去。那么相應(yīng)的節(jié)點(diǎn)根據(jù)用戶(hù)拿到Session了就可以進(jìn)行處理了。

    上面2點(diǎn)大概簡(jiǎn)單的描述了下Session共享的原理,那么有這么個(gè)場(chǎng)景,文字可能不太好表達(dá),我們還是用圖來(lái)說(shuō)明:

    一般出現(xiàn)多端情況也應(yīng)該就上面2種情況,要么允許,要么不允許。我這里簡(jiǎn)單的說(shuō)下不允許的處理流程。

    建立連接的時(shí)候,先獲取老的Session

    Session oldSession = SOCK_MAP.get(baseStudentInfo.getId());

    存在,則推送關(guān)閉消息,不存在告知其他節(jié)點(diǎn)去清楚。當(dāng)然本節(jié)點(diǎn)的的Server要排除在外,這里就通過(guò)IP判斷即可。

    if(oldSession!=null) {oldSession.getBasicRemote().sendObject(close);}else{//關(guān)閉其他節(jié)點(diǎn)的的sessionauthService.pushCloseMessage(close);}//替換SOCK_MAP.put(baseStudentInfo.getId(),session);

    消息監(jiān)聽(tīng)

    String serverIp = IPUtils.getLocalhostIp();logger.info("當(dāng)前IP:"+serverIp);logger.info("content的IP:"+wsMessage.getBody().getContent());//IP不相等,說(shuō)明不是當(dāng)前連接的服務(wù)端,關(guān)閉其他端口if(!serverIp.equals(wsMessage.getBody().getContent())){//關(guān)閉session,并返回給前端customerHandler.closeSession(wsMessage.getBody().getReceiver(), wsMessage);}

    關(guān)閉的方法:

    /*** 關(guān)閉Session* @param studentId* @param closeMessage*/public void closeSession(Long studentId,WsMessage closeMessage){Session session = SOCK_MAP.get(studentId);if(session!=null) {try {session.getBasicRemote().sendObject(closeMessage);SOCK_MAP.remove(studentId);//清除redislogger.info("連接已關(guān)閉:" + studentId);} catch (Exception e) {e.printStackTrace();logger.error("關(guān)閉連接異常");}}}

    這樣基本就避免多端登錄的問(wèn)題,如果允許多端登錄的時(shí)候只需要更改存儲(chǔ),更改發(fā)送消息變成群發(fā)即可。

    總結(jié)

    以上是生活随笔為你收集整理的Springboot整合Websocket遇到的坑_websocket session不支持序列化,无法存储至redis_Websocket相关问题总结(Session共享,用户多端登录等)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。