V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
nnegier
V2EX  ›  Java

[Spring] WebSocket 怎么做到集群?

  •  1
     
  •   nnegier · 2024-01-11 07:08:08 +08:00 · 3729 次点击
    这是一个创建于 369 天前的主题,其中的信息可能已经有所发展或是发生改变。
    31 条回复    2024-01-12 09:55:14 +08:00
    hly9469
        1
    hly9469  
       2024-01-11 08:06:45 +08:00 via Android
    nginx ,跟 spring 关系不大
    YIsion
        2
    YIsion  
       2024-01-11 08:49:41 +08:00
    啊? WebSocket 是有状态的协议,你说的集群的意思应该是指客户端发起请求能连接到一堆服务器中负载压力小的服务器吧。
    seedhk
        3
    seedhk  
       2024-01-11 08:50:11 +08:00
    nginx 做负载均衡啊
    m2276699
        4
    m2276699  
       2024-01-11 09:01:45 +08:00
    盲猜你是不是在问主动推送不知道怎么推?
    zzzzyg
        5
    zzzzyg  
       2024-01-11 09:02:37 +08:00
    MQ
    liangkang1436
        6
    liangkang1436  
       2024-01-11 09:04:24 +08:00 via Android
    一开始跟客户端建立连接的是哪台服务器,后续就必须一直是这台服务器与此客户端通信,在使用 NGINX 进行反向代理的时候,必须保证这一点,否则,在客户端看来,就会断链,为了保证这一点,可以配置 NGINX 的负载均衡策略,保证来自某一个客户端的请求固定映射到某一台服务器,不过为了保险起见,还是应该用一个回话管理器
    kiracyan
        7
    kiracyan  
       2024-01-11 09:06:11 +08:00
    你要的应该是网关服务器,然后再动态分配业务服务器
    qinxi
        8
    qinxi  
       2024-01-11 09:06:34 +08:00
    自己维护一份 userId 跟服务的映射关系呗. 给他发消息就找映射关系到对应的服务
    dlmy
        9
    dlmy  
       2024-01-11 09:08:29 +08:00
    网关,Session 会话管理器,一致性 Hash ?
    jimrok
        10
    jimrok  
       2024-01-11 09:16:38 +08:00
    后端用一个 etcd 或者 zookeeper 管理群集,然后根据客户的 id 用算法映射到群集上,引导客户的连接群集使用的 ip 地址和端口,客户就上了船了。如果群集要下线,发送 websocket 的消息给客户,自己断线然后重新查询群集地址,再连接。
    interim
        11
    interim  
       2024-01-11 09:18:11 +08:00
    先把具体问题抛出来,别把方向整错了。
    yalin
        12
    yalin  
       2024-01-11 09:21:17 +08:00
    我们是 AWS 云上面,结合 API Gateway 和 Spring 一起做的
    monkeyk
        13
    monkeyk  
       2024-01-11 09:26:18 +08:00
    若是做推送服务,何不尝试用这类小而美的服务呢,https://www.goeasy.io/
    visper
        14
    visper  
       2024-01-11 09:31:12 +08:00   ❤️ 2
    估计你说的是,集群系统里面,websocket 连接到了其中一台,但是后续任务在其他台运行怎么推送到特定的人。这种需要后台集群间有自己的通讯机制。比如任务发消息了广播到其他集群机器然后直接推送到连到这台机的 websocket 。
    luobingit
        15
    luobingit  
       2024-01-11 09:37:48 +08:00
    #14 +1
    ionfev
        16
    ionfev  
       2024-01-11 09:39:24 +08:00
    简单实现过,使用 Redis 发布订阅,查资料看到还有 MQ 、Zookeeper 、微服务的服务发现。笔记: https://www.cnblogs.com/ioufev/p/17559480.html
    jorneyr
        17
    jorneyr  
       2024-01-11 09:42:48 +08:00   ❤️ 4
    这个问题其实主要是解决跨 WebSocket Server 发送消息。

    A 在 Server-1
    B 在 Server-2

    A 要给 B 发送私有消息:
    1. A 给 Server-1 发送消息
    2. Server-1 收到消息,先在自己的连接列表里找 B 得连接
    2.1. 如果找到 B 的连接则直接给 B 发送消息
    2.2. 如果没有找到 B 的连接则给所有 WebSocket Server 广播给 B 发送消息
    3. WebSocket Server 收到广播,然后查看如果消息是自己广播的则抛弃,不是则执行消息的动作
    Masoud2023
        18
    Masoud2023  
       2024-01-11 10:25:16 +08:00
    这问题我还真没想过,ws 怎么做负载均衡?
    Aresxue
        19
    Aresxue  
       2024-01-11 11:05:09 +08:00
    这问题想问的是推送,如何把某个用户的信息反向推送到浏览器,浏览器到用户有 nginx 代理 tcp 直接就能找到,这问题说大不大说小不小,简单来说就是维护 user 和 server 的关系,但如果 server 的量级超过 100 就会复杂的多,多活容灾每个细节都值得大费篇章。
    XCFOX
        20
    XCFOX  
       2024-01-11 11:59:43 +08:00   ❤️ 2
    如果是服务端主动推送的场景的话,可以考虑一下使用消息中间件 NATS: https://nats.io/

    NATS 内置了楼上提到的负载均衡、广播等功能。
    NATS 能够通过 SDK 与前端、客户端直接连接。
    NATS 能够很方便地实现水平扩展,NATS 能够与你的用户权限体系集成。

    https://docs.nats.io/running-a-nats-service/configuration/websocket/websocket_conf
    pengtdyd
        21
    pengtdyd  
       2024-01-11 12:02:04 +08:00
    那当然是单独的服务啦,无状态和有状态架构上个人认为不能混用(纯个人理解)。
    kuituosi
        22
    kuituosi  
       2024-01-11 12:23:16 +08:00
    要看具体实现的功能,即使是 websocket 也可以当作临时接入点,所以连接到任意一台就可以
    如果是需要持续状态,比如有游戏服务器,就需要保持 session
    这种可以采用客户端路由,也可以采用网关 session 路由
    imokkkk
        23
    imokkkk  
       2024-01-11 14:52:20 +08:00
    Redis 发布订阅
    imokkkk
        24
    imokkkk  
       2024-01-11 14:56:02 +08:00
    gitrebase
        25
    gitrebase  
       2024-01-11 15:34:07 +08:00
    如果要做服务端推送的话,可以考虑使用 Server-Sent Events ,这是种不用维护 WebSocket 的方案,我前几天刚好写了 demo 来用 SSE + NATS 来做轻量级的聊天室服务( NATS 就是用来做集群间的即时 pubsub 的,用 Redis 的 pubsub 应该也行) https://zhuanlan.zhihu.com/p/676561818
    salmon5
        26
    salmon5  
       2024-01-11 16:14:03 +08:00
    会话保持,植入 cookie 。
    AWS/阿里云 ALB 都支持。
    salmon5
        27
    salmon5  
       2024-01-11 16:15:42 +08:00
    AWS 叫 Sticky sessions(粘性会话) Stickiness
    l0wkey
        28
    l0wkey  
       2024-01-11 16:16:41 +08:00
    换 MQTT 吧
    salmon5
        29
    salmon5  
       2024-01-11 16:22:35 +08:00
    https://socket.io/docs/v4/using-multiple-nodes/#nginx-configuration
    nginx 社区版不支持基于植入 cookie 的,商业版支持
    社区版支持基于源 IP 的,缺点是可能会负载不均匀
    ZeroDu
        30
    ZeroDu  
       2024-01-11 16:26:27 +08:00
    上面说的 mq 发广播这个就是最佳方案了;
    或者 redis 保存一份 client 跟 server 的对应关系,后续就可以操作了
    F7TsdQL45E0jmoiG
        31
    F7TsdQL45E0jmoiG  
       2024-01-12 09:55:14 +08:00
    本质是会话保持,另外现在还有什么场景非要用 websocket 的集群
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1213 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 23:21 · PVG 07:21 · LAX 15:21 · JFK 18:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.