• spring cloud整合 websocket 的那些事


    我们知道, 现在很多浏览器都已经是直接支持 websocket 协议的了,  除此之外, sockjs, 也可以实现 websocket 功能.. 当然, 其原理是不同的.

    一开始 websocket 已经做好了,  但是后面发现 websocket不能穿透zuul ,

    出现

    com.netflix.zuul.exception.ZuulException: Forwarding error ... 等问题.

    找到了 https://blog.csdn.net/moshowgame/article/details/80511158

    修改了ZuulFilter , 貌似行了, 结果仍然各种问题.. 

    真是郁闷了.  网上的关于springboot + websocket 资料很多

    https://blog.csdn.net/qq_39320953/article/details/77852126 基本可用

    https://blog.csdn.net/jie873440996/article/details/70257558 非常详细

    https://blog.csdn.net/haoyuyang/article/details/53364372 很好

    https://segmentfault.com/a/1190000006617344 stomp介绍

    https://blog.csdn.net/nongshuqiner/article/details/78792079 sockjs介绍

    好像stomp能解决问题....  哦, 改stomp吧, 但很快遇到问题:

    org.springframework.web.socket.sockjs.SockJsMessageDeliveryException: Failed to ..

    原来js 也是需要改的..

    参考 https://my.oschina.net/robinjiang/blog/898557

    , 但是 zuul + websocket 的资料就少了. 

    其实也是找到了几个的, 但是呢, 不能完全拿过来用, 因为1 没有它们的源代码, 2 认证机制不一样..  怎么办呢? 升级到 zuul2 ? 使用 spring-cloud-gateway? spring-cloud-gateway 下载了一个示例, 基本是可行的.  但是, 这样的话, 需要整个升级, 改动也太大了..

    终于找到了 一篇: https://github.com/mthizo247/spring-cloud-netflix-zuul-websocket 

    示例也亲测可用, 但是, 拿过来到我们项目就不行了,  出现各种问题, 

    首先是   认证机制不一样.. 我们登录都是基于token 的, mthizo247是基于spring security的, 发送点对点消息遇到各种问题:

    annotation.support.MissingSessionUserException: No "user" header in message:

    找到答案: 

    You are trying to subscribe to a user destination so the user must be authenticated.

    If that is an anonymous user who want to subscribe to the topic, answer to this questionwill help.

    You'll have to assign an anonymous identify to the user and there are two options:

    1. Configure a sub-class of DefaultHandshakeHandler that overrides determineUserand assigns some kind of identity to every WebSocketSession.

    2. The WebSocket session will fall back on the value returned from HttpServletRequest.getUserPrincipal on the handshake HTTP request. You could have a servlet Filter wrap the HttpServletRequest and decide what to return from that method. Or if you're using Spring Security which has the AnonymousAuthenticationFilter, override its createAuthentication method.

    https://stackoverflow.com/questions/36616167/spring-websocket-missingsessionuserexception-no-user-header-in-message

    http://www.itkeyword.com/doc/0662498046730811x767/spring-websocket-missingsessionuserexception-no-user-header-in-message

    https://stackoverflow.com/questions/36847814/spring-websocket-send-message-from-a-queue-to-a-user-convertandsendtouser-not-wo

    这个通过 stomp 建立连接时候 设置 nativeHeaders 解决了, nativeHeaders  也是很难获取到的, 后面 通过stomp 发出的event , 终于是解决了.

    另外, mthizo247 群发消息会出现 重复消息的情况, 这就尴尬了..  这个问题比较难比较, 我仔细调试过mthizo247的源码, 发现里面session 的数量刚好出现了重复, 这样就导致了 前端接收到重复消息,,, 怎么办呢 ? 

    我后面想出了一个折中的解决方案: 

    https://github.com/mthizo247/spring-cloud-netflix-zuul-websocket/issues/4 


    问题好像解决了, 但是, convertAndSendToUser 好像不工作了??

     simpMessagingTemplate convertAndSendToUser

    哦, 仔细一看是代码bug, mthizo247  也需要配合修改.. 

    问题好像解决了, 但是, 又,

    Failed to send message to ExecutorSubscribableChannel[clientInboundChannel

    ...

    NoClassDefFoundErrorc org/springframework/integration/channel/DirectChannel

    ...

    分析了下, 好像是sleuth 出来捣乱, dependency 中先屏蔽它吧, 然后呢, 有发现一个NosuchMethodError 之类的错误, 仔细分析, 发现是 spring-message的版本不一致, 当然, 这个是由于spring-boot 版本不一致导致的...  改吧..

    但是,  我们前后端是分离的, 前端除了浏览器, 还有nodejs 服务器呢..  浏览器刷新之后, stomp 连接就断开了, 但是 nodejs 服务器 和zuul 的连接确实没有断开的..

    复制代码
    sockjs.js:3559 'protocols_whitelist' is DEPRECATED. Use 'transports' instead.
    
    Opening Web Socket...
    Web Socket Opened...
    
    
    >>> CONNECT
    token:u1
    accept-version:1.1,1.0
    heart-beat:10000,10000
    
    <<< CONNECTED
    version:1.1
    heart-beat:0,0
    user-name:u1
    
    connected to server undefined
    
    >>> SUBSCRIBE
    id:sub-0
    destination:/user/queue/notifications
    
    
    
    浏览器刷新出现:
    
    >>> CONNECT
    token:u1
    accept-version:1.1,1.0
    heart-beat:10000,10000
    
    Whoops! Lost connection to http://10.10.10.76:9999/lk-websocket
    复制代码

    因为nodejs 服务器的存在, 浏览器刷新 会进行重连,  然后导致重新建立连接, 但是, 当前用户的连接以及存在了, 所以就无法再建立了, 所以就  Lost connection ...   怎么办呢?  nodejs  端处理吧...    当连接断开的时候, nodejs 服务器检测到了, 然后也同样的像zuul 主动发起一个连接断开的请求.. 

     

    版权声明
    本文原创发表于 博客园,作者为 阿K 
    本文欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。
  • 相关阅读:
    关于vue中的语法糖v-model
    Cocos2d-x shader学习1: 灰度shader
    nginx多域名配置
    lua和c的亲密接触
    LeetCode 2. Add Two Numbers 解题报告
    LeetCode 1. Two Sum 解题报告
    【翻译】LPeg编程指南
    Cocos2d-x中的CC_CALLBACK_X详解
    C++ 11 学习3:显示虚函数重载(override)
    C++ 11 学习2:空指针(nullptr) 和 基于范围的for循环(Range-based for loops)
  • 原文地址:https://www.cnblogs.com/laixin09/p/9598650.html
Copyright © 2020-2023  润新知