Drinker
V2EX  ›  Java

一个 Java 项目如果需要启用上万个 websocket,有什么好办法么

  •  
  •   Drinker · Feb 26, 2020 · 14782 views
    This topic created in 2442 days ago, the information mentioned may be changed or developed.

    大概是这样,对方有个 api,这个 api 对应的参数有个上万个,每个参数对应一个 websocket,现在要做的是拿到参数,每个参数启动一个 websocket 去保存发送下来的数据,保存现在使用消息队列应该没什么问题,就是如果启动了上万个 websocket 会不会内存直接爆炸?或者还是有没有其他的办法,老哥们。

    92 replies  •  2020-02-27 17:50:48 +08:00
    GM
    GM
    Feb 26, 2020
    1
    你不会做个遍历一个一个去连接吗?
    misaka19000
    misaka19000
    Feb 26, 2020
    2
    测一下不就知道了
    sudodo
    sudodo
    Feb 26, 2020
    3
    上万个 ws,一台服务器是不可能的啊……
    Drinker
    Drinker
    OP
    Feb 26, 2020
    4
    @GM 连接么可以连接,关键问题是内存会不会爆掉,现在在做技术方案,上万个 websocket,且每个 websocket 同一时间很大概率会有信息传过来,所以性能这块需要考虑一下。所以问问各位老大哥有没有什么好办法。
    lbfeng
    lbfeng
    Feb 26, 2020
    5
    不是每个 websocket 链接占一个端口么?
    misaka19000
    misaka19000
    Feb 26, 2020
    6
    你测一下每个 ws 要多少内存,然后算一下不就知道内存够不够了
    Drinker
    Drinker
    OP
    Feb 26, 2020
    7
    @misaka19000 上万个 websocket,且每个 websocket 同一时间很大概率会有信息传过来,感觉不用测,性能可能有点悬,所以咨询一下各位老大哥。
    misaka19000
    misaka19000
    Feb 26, 2020
    8
    @lbfeng #5 每个 ws 占一个 fd,所有的 ws 可以共用一个端口啊
    binux
    binux
    Feb 26, 2020❤️9
    9
    你问下对面是怎么做到同时支持上万个 websocket 的。
    GM
    GM
    Feb 26, 2020
    10
    说实话,你们这个获取数据方式有点奇葩。
    Drinker
    Drinker
    OP
    Feb 26, 2020
    11
    @sudodo 我也感觉不行,如果多台服务器,类似这种案例这个有没有现有的解决方案,老哥。
    Vegetable
    Vegetable
    Feb 26, 2020
    12
    @lbfeng 你说的好像是出口,服务端就开一个吧
    Drinker
    Drinker
    OP
    Feb 26, 2020
    13
    @lbfeng 一个端口就可以了。
    GM
    GM
    Feb 26, 2020
    14
    先把每个参数丢到一个队列里去,然后做个 100 线程的线程池,每个线程做个死循环从队列拿参数、启动 ws 获取数据、关闭 ws,保证内存不爆。

    如果内存足够,那就启动 500、1000 个线程。
    Drinker
    Drinker
    OP
    Feb 26, 2020
    15
    @misaka19000 嗯,内存这个可以测试看看,如果每个 websocket 同一时间数据量很大,cpu 也是一个问题,麻烦。
    ryd994
    ryd994
    Feb 26, 2020 via Android
    16
    讲道理,这不就是 C10K 问题?
    Drinker
    Drinker
    OP
    Feb 26, 2020
    17
    @binux 这个方法可以,可以问问对面技术是咋做到的,(*^_^*)
    janxin
    janxin
    Feb 26, 2020
    18
    内存可以估算出来的,会不会爆炸也不知道你的内存多少啊...
    Drinker
    Drinker
    OP
    Feb 26, 2020
    19
    @GM 对方提供获取数据方法就这些,而且数据还是实时的,就是现在如果你不连接获取到数据,时间已过就没数据啦。
    Drinker
    Drinker
    OP
    Feb 26, 2020
    20
    @janxin 嗯,cpu 这个也是个问题,同一时刻,有个几千个 websocket 同时有数据过来,内存不炸,cpu 也不会爆满吧。
    Drinker
    Drinker
    OP
    Feb 26, 2020
    21
    @GM 数据具有实时性,很大概率需要全部 websocket 开着,不能关闭,关闭了数据就没了。
    liuguang
    liuguang
    Feb 26, 2020
    22
    这种事情 go 和 rust 应该可以做到。至于 java,用 nginx 反代分流,每台 Java 服务器处理一部分 ws 流量,应该也可以搞定.
    casillasyi
    casillasyi
    Feb 26, 2020
    23
    jvm 本身就是个负担。这种场景建议用 rust
    polythene
    polythene
    Feb 26, 2020
    24
    做 sharding 吧,单机器估计扛不住
    sagaxu
    sagaxu
    Feb 26, 2020 via Android
    25
    参数不能作为 message 的一部分吗?
    zzcworld
    zzcworld
    Feb 26, 2020
    26
    建议拆成 worker,每个 worker 连接几千个 websockets。如果能订阅多个 channel,减少 websockets 连接,也是一个好办法
    sagaxu
    sagaxu
    Feb 26, 2020 via Android
    27
    @polythene 2 代树莓派开 2 万个 websocket 毫无压力,比树莓派性能还差的服务器?
    @liuguang Java 正常服务器单机 100K 个 websocket 应该问题不大
    envooy
    envooy
    Feb 26, 2020 via Android
    28
    对参数 hash 然后想办法分布式多台服务器。数据落地可以想办法被动写回或者主动扔到 redis 然后再定时持久化。
    wizardoz
    wizardoz
    Feb 26, 2020
    29
    内存会不会爆炸取决于你的内存有多少,而且直觉上这个内存消耗不大。
    我觉得最应该考虑的问题是多线程方式处理每个连接还是通过异步 IO 的方式处理。如果异步 IO,我相信对服务器的要求不高。
    如果是多线程,那么服务器就难了。
    XRR
    XRR
    Feb 26, 2020
    30
    @sagaxu 100000 个 websocket 都超过服务器的端口数了,肯定不行,服务器一共就六万多个逻辑端口
    gemini767
    gemini767
    Feb 26, 2020
    31
    团队没有专业人员建议 http 轮训,简单有效,最重要的可控
    liqingcan
    liqingcan
    Feb 26, 2020
    32
    什么需求需要这么多 websocket im 类的需求?这玩意也不会用一台机器吧。挺好奇的
    lscho
    lscho
    Feb 26, 2020
    33
    @XRR 想啥呢。。。websocket 和端口有什么关系,又不是 TCP。

    实践出真知,几万个 websocket 连接数肯定是没啥问题的,几十万也没问题,需要考虑的就是数据量问题,数据量过大同时进来肯定不行。
    gemini767
    gemini767
    Feb 26, 2020
    34
    @sagaxu 开 2w 个 socket 和支持 2w 个长链接业务还是有很大差别的吧
    realpg
    realpg
    Feb 26, 2020
    35
    你们老板需要一个架构师。。。
    pubby
    pubby
    Feb 26, 2020 via Android
    36
    会不会理解有偏差,上万个参数其实可以一起传的?
    envooy
    envooy
    Feb 26, 2020 via Android
    37
    @lscho 我记得 spring websocket 默认是一个连接一个 socket 用的是异步套接字。如果是 epoll,两万个 websocket,cpu 包处理速度够的话应该没问题。怕 socket 的 receive buffer 过大。导致内核内存缓冲区不够用。如果内核内存满了的话一直在用虚拟内存怕是电脑会卡死?
    realpg
    realpg
    Feb 26, 2020
    38
    我这里有个类似的东西。
    也是客户端 开 4400 个 TCP 连接到远程,然后保存下推流,解码,入库。
    用了 12 台垃圾 1U 服务器,服务器总成本一万五千元……
    realpg
    realpg
    Feb 26, 2020
    39
    @pubby #36
    你没理解他的业务模型。
    freemoon
    freemoon
    Feb 26, 2020
    40
    你这个场景有点像是对 ws 服务端做鲁棒性测试
    freemoon
    freemoon
    Feb 26, 2020
    41
    哪有正常的逻辑是一方使用上 W 个端口去连接 ws 的,我建议楼主把逻辑理清楚说清楚,无厘头。。。
    Xusually
    Xusually
    Feb 26, 2020
    42
    需要长链接吗?
    怎么感觉你这场景是股票行情信息同步推送?
    Drinker
    Drinker
    OP
    Feb 26, 2020
    43
    @ryd994 哈哈,我去搜了一下,这个的确和 C10K 的场景差不多。
    Drinker
    Drinker
    OP
    Feb 26, 2020
    44
    @sagaxu 相当于 ws 连接前缀相同,加了参数就是一个 ws 连接,现在参数的变化有一万多种,所以就有一万多连接。
    Drinker
    Drinker
    OP
    Feb 26, 2020
    45
    @ftfunjth 嗯,我们这边考虑一下。谢谢。
    Drinker
    Drinker
    OP
    Feb 26, 2020
    46
    @wizardoz 主要就是通过 WebSocketClient 来连接,不过没找到 onMessage 是异步 IO 还是多线程,搜了一下,好像都没提到。现在暂时的想法是 onMessage 有信息的时候立马推到 jms 里面,另外一台服务从队列里面一个个取出数据保存起来。
    Drinker
    Drinker
    OP
    Feb 26, 2020
    47
    @gemini767 嗯,这边考虑一下,谢谢。
    Drinker
    Drinker
    OP
    Feb 26, 2020
    48
    @liqingcan 有点类型直播的这种,比如虎牙直播,每个直播间的信息其实是一个 ws 连接,现在我知道一万个房间号,我就可以连接一万个房间的直播信息,然后把直播信息保存下来。类似这种。
    Drinker
    Drinker
    OP
    Feb 26, 2020
    49
    @realpg 哈哈,都在考虑方案当中。
    fancy111
    fancy111
    Feb 26, 2020
    50
    上万个 WS 是肯定没问题的,问题是带宽会爆
    Drinker
    Drinker
    OP
    Feb 26, 2020
    51
    @pubby 有点类型直播的这种,比如虎牙直播,每个直播间的信息其实是一个 ws 连接,现在我知道一万个房间号,我就可以连接一万个房间的直播信息,然后把直播信息保存下来。类似这种。
    Drinker
    Drinker
    OP
    Feb 26, 2020
    52
    @lasuar 有点类型直播的这种,比如虎牙直播,每个直播间的信息其实是一个 ws 连接,现在我知道一万个房间号,我就可以连接一万个房间的直播信息,然后把直播信息保存下来。类似这种。
    Drinker
    Drinker
    OP
    Feb 26, 2020
    53
    @Xusually 对呢。很类似。不能断,断了数据就没了。启动就需要很多连接。对方提供的只是 ws。
    freemoon
    freemoon
    Feb 26, 2020
    54
    @Drinker 直播的 N 个 ws 连接是存在于服务端,只会占用服务端一个 ws 服务端口,程序存储的 N 个 conn 对象都是占用的同一个的端口,你这个场景就类似于拿一台机器模拟上 W 个 ws 客户端,所以才需要上 W 个端口,不要搞混了。
    tinybaby365
    tinybaby365
    Feb 26, 2020❤️2
    56
    之前用 golang 实现过,单机用了 24GB 的内存,大概 160w 个连接。诀窍是省内存,降低你服务的每个连接的内存消耗,我没用 net/http,虽然我用的 websocket 库是依赖 net/http,但 go 的鸭子类型可以让我用一个简陋消耗更小的 conn 替代。
    另一个就是降低系统 socket 的读写 buffer。root 权限加 rlimit 设置,突破单进程的限制。
    maichael
    maichael
    Feb 26, 2020❤️1
    57
    我记得之前看过测试,一台还可以的机器撑 100 万左右的 Websocket 没问题。
    aguesuka
    aguesuka
    Feb 26, 2020 via Android
    58
    理论上 nio10k 个 tcp 连接没有问题,用 netty 试试呗。我估计系统瓶颈 io,cpu,然后才是内存
    no1xsyzy
    no1xsyzy
    Feb 26, 2020
    59
    @Drinker 附加信息不要一个个回复,可以 append,可以 @ 多个人。不然你容易被降权导致别人根本收不到你的消息。
    no1xsyzy
    no1xsyzy
    Feb 26, 2020
    60
    @lasuar #41 可是楼主也没提到端口啊,是上面有人(#5、#30 )觉得一个链接一个端口,而且已经被人反驳了。
    zjsxwc
    zjsxwc
    Feb 26, 2020
    61
    1 万连接,java 没有问题的
    realpg
    realpg
    Feb 26, 2020
    62
    @lasuar #41
    你没见过不代表不存在且不合理
    我这就有跟楼主一样的 只是 TCP

    一个服务用几千个 TCP 频道实时广播信息
    一般一个客户只需要订阅一个频道

    但是因为性能问题,自建的地区中继,就得所有频道信息 relay
    就是一组服务器几千个客户端
    zfish
    zfish
    Feb 26, 2020
    63
    使用 elixir/erlang 开发吧,上万并发不要太轻松
    freemoon
    freemoon
    Feb 26, 2020
    64
    对于 ws 服务端来说,一台普通服务器倒不是说承受上 w 个 client 连接无压力,这个还要看消息 size 和传输频率,几十万人直播间那种一台机器的网卡都受不住了。
    sampeng
    sampeng
    Feb 26, 2020 via iPhone
    65
    先搞清楚 ws 和 tcp 的关系…另外有一句说一句。你确定对方能支持上万的 qps ?
    gamexg
    gamexg
    Feb 26, 2020
    66
    上万个没难度啊
    网关类单服务器连入几十万连接,连接空闲时 120m 一个 ping,外加数据传输网卡跑到 500M+,毫无问题。
    gamexg
    gamexg
    Feb 26, 2020
    67
    @gamexg #66 120m->120s
    freemoon
    freemoon
    Feb 26, 2020
    68
    @realpg 好吧,只能说确实太少见了,这得是多大的项目规模了
    x66
    x66
    Feb 26, 2020
    69
    这是要爬直播平台的弹幕和礼物吧
    Drinker
    Drinker
    OP
    Feb 26, 2020
    71
    @tinybaby365 好呢,我们这边考虑一下,谢谢。
    @maichael 好的,找个时间测试一波看看。
    @no1xsyzy 多谢提醒,我这边已经被禁止回复好几次啦,哈哈
    @zfish 多谢建议,我们去了解一下。
    @lasuar 嗯,我们先测试一下看看,谢谢。
    @sampeng 对方可以搞,实时的几万个频道的广播,现在就是不知道对方怎么弄的,/(ㄒoㄒ)/~~
    @gamexg 好呢,我们测试一下,谢谢
    @x66 不是,类似这种消息中转和消息概要记录。
    @paoqi2048 谢谢,我们了解一下。
    keenkiller
    keenkiller
    Feb 26, 2020 via Android
    72
    上万个没啥难度啊…你可以用 mqtt broker,开源的都能单机上万了
    pinews
    pinews
    Feb 26, 2020
    73
    小白请教一下
    这个 api 对应的参数有个上万个,每个参数对应一个 websocket !每个参数对应的难道不应该是一个频道吗?
    zfish
    zfish
    Feb 26, 2020❤️1
    74
    @Drinker elixir 单机 4GB 开百万进程( Erlang 的虚拟进程,实际上底层是 Erlang 实现了自己的 CPU 调度算法,并不依赖操作系统的调度,所以可以做到极其低成本的开销去切换进程),每个进程都是独立的内存分配,百万用户的长链接都可以用百万的进程去独立负责通信,所以 Erlang 在游戏领域后台 /电信领域使用的很多,不过 Erlang 的语法有点奇怪,可以用基于 Erlang 的 Elixir 去开发
    zfish
    zfish
    Feb 26, 2020
    75
    @zfish ![]( https://img.bmpi.dev/c5a8569f-42b1-63de-15a5-25d77f29a050.png) Elixir 的 Web 框架 Phoenix 单机两百万 WS 长链接,毫无压力
    noisywolf
    noisywolf
    Feb 26, 2020
    76
    1、用 nginx+lua,就是 OpenResty,每个连接挂个 redis 的 pubsub
    2、用 go,轻松解决
    SjwNo1
    SjwNo1
    Feb 26, 2020
    77
    gogogo
    Isu
    Isu
    Feb 26, 2020
    78
    建议换 elixir + phoenix channel, 特别香 ( 逃 ~
    Isu
    Isu
    Feb 26, 2020
    79
    @zfish #75 elixir 握爪
    zjq123
    zjq123
    Feb 26, 2020 via Android
    80
    @zfish 我觉得主要是 socket 肯定涉及到内核 只不过 erl 在伪进程调度方面实现了自己一套 不涉及到操作系统进城管理了 而只涉及到内核 socket 部分
    onion83
    onion83
    Feb 26, 2020
    81
    我觉得沟通是不是有点问题?把 webscoket 当 http 来玩了?一般的使用方法都是建立一次连接,然后不断收发数据就好了,同步响应还是异步响应,这个要看业务,连接是可以复用的。
    wufakeyou
    wufakeyou
    Feb 26, 2020❤️1
    82
    生产环境,C#+阿里云 4 核 8G,8000 个 socket 在线,资源占用 30%左右。对物联网项目来说,1W 个 socket 规模其实很小了。
    Drinker
    Drinker
    OP
    Feb 26, 2020
    83
    @tairan2006 好呢,有方向就好,我们先去看看。
    @pinews 如果说频道的话不太准确,大概就是如果 type=1 那么对面服务会把对应的 1 的数据传过来,如果是 2 那么对应的数据就是 2,但是不能说传 type=1,2 这种,他们会认为 type 是非法的。
    @zfish 好的,谢谢提供思路,我们去看看。
    @no1xsyzy 谢谢提供思路。
    @SjwNo1 哈哈,好呢,我们去看看相关的资料。
    @lfcyme 好的,谢谢提供思路。
    @onion83 大概就是如果 type=1 那么对面服务会把对应的 1 的数据传过来,如果是 2 那么对应的数据就是 2,但是不能说传 type=1,2 这种,他们会认为 type 是非法的。所以每一个 type 的值,都对应一个 ws 连接。每个 ws 连接自行接收数据。
    @wufakeyou 好的,谢谢提供案例,我们这边做下技术调研。
    cz5424
    cz5424
    Feb 26, 2020
    84
    golang,1w 小意思
    cz5424
    cz5424
    Feb 26, 2020
    85
    @wufakeyou 同物联网,1w+, 低于 30%,golang,tcp
    monkeyWie
    monkeyWie
    Feb 26, 2020
    86
    java 上 netty 轻松搞定好吧
    pythonee
    pythonee
    Feb 26, 2020
    87
    云服务 api gateway ?
    wellsc
    wellsc
    Feb 26, 2020
    88
    扔给 nginx 处理
    laozhang
    laozhang
    Feb 27, 2020 via iPhone
    89
    32g 的机器 100 万 ws 连接应该没问题。对 我说的单机。go 写的。
    barbery
    barbery
    Feb 27, 2020
    90
    换 go
    sicauxeon
    sicauxeon
    Feb 27, 2020
    91
    经典的 C10K 问题。但是看你具体的使用场景,如果不行的话,就负载均衡做吧。
    lixm
    lixm
    Feb 27, 2020
    92
    楼主这个是客户端啊, 单机不够就堆机器呗, 还不至于 C10K
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   2963 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 294ms · UTC 12:45 · PVG 20:45 · LAX 04:45 · JFK 07:45
    ♥ Do have faith in what you're doing.