大概是这样,对方有个 api,这个 api 对应的参数有个上万个,每个参数对应一个 websocket,现在要做的是拿到参数,每个参数启动一个 websocket 去保存发送下来的数据,保存现在使用消息队列应该没什么问题,就是如果启动了上万个 websocket 会不会内存直接爆炸?或者还是有没有其他的办法,老哥们。
1
GM 2020-02-26 10:24:57 +08:00
你不会做个遍历一个一个去连接吗?
|
2
misaka19000 2020-02-26 10:24:59 +08:00
测一下不就知道了
|
3
sudodo 2020-02-26 10:28:46 +08:00
上万个 ws,一台服务器是不可能的啊……
|
4
Drinker OP @GM 连接么可以连接,关键问题是内存会不会爆掉,现在在做技术方案,上万个 websocket,且每个 websocket 同一时间很大概率会有信息传过来,所以性能这块需要考虑一下。所以问问各位老大哥有没有什么好办法。
|
5
lbfeng 2020-02-26 10:30:32 +08:00
不是每个 websocket 链接占一个端口么?
|
6
misaka19000 2020-02-26 10:30:57 +08:00
你测一下每个 ws 要多少内存,然后算一下不就知道内存够不够了
|
7
Drinker OP @misaka19000 上万个 websocket,且每个 websocket 同一时间很大概率会有信息传过来,感觉不用测,性能可能有点悬,所以咨询一下各位老大哥。
|
8
misaka19000 2020-02-26 10:31:35 +08:00
@lbfeng #5 每个 ws 占一个 fd,所有的 ws 可以共用一个端口啊
|
9
binux 2020-02-26 10:33:18 +08:00 9
你问下对面是怎么做到同时支持上万个 websocket 的。
|
10
GM 2020-02-26 10:33:37 +08:00
说实话,你们这个获取数据方式有点奇葩。
|
14
GM 2020-02-26 10:36:12 +08:00
先把每个参数丢到一个队列里去,然后做个 100 线程的线程池,每个线程做个死循环从队列拿参数、启动 ws 获取数据、关闭 ws,保证内存不爆。
如果内存足够,那就启动 500、1000 个线程。 |
15
Drinker OP @misaka19000 嗯,内存这个可以测试看看,如果每个 websocket 同一时间数据量很大,cpu 也是一个问题,麻烦。
|
16
ryd994 2020-02-26 10:38:57 +08:00 via Android
讲道理,这不就是 C10K 问题?
|
18
janxin 2020-02-26 10:39:59 +08:00
内存可以估算出来的,会不会爆炸也不知道你的内存多少啊...
|
20
Drinker OP @janxin 嗯,cpu 这个也是个问题,同一时刻,有个几千个 websocket 同时有数据过来,内存不炸,cpu 也不会爆满吧。
|
22
liuguang 2020-02-26 10:48:40 +08:00
这种事情 go 和 rust 应该可以做到。至于 java,用 nginx 反代分流,每台 Java 服务器处理一部分 ws 流量,应该也可以搞定.
|
23
casillasyi 2020-02-26 10:51:53 +08:00
jvm 本身就是个负担。这种场景建议用 rust
|
24
polythene 2020-02-26 10:56:37 +08:00
做 sharding 吧,单机器估计扛不住
|
25
sagaxu 2020-02-26 10:56:51 +08:00 via Android
参数不能作为 message 的一部分吗?
|
26
zzcworld 2020-02-26 10:57:37 +08:00
建议拆成 worker,每个 worker 连接几千个 websockets。如果能订阅多个 channel,减少 websockets 连接,也是一个好办法
|
27
sagaxu 2020-02-26 11:03:01 +08:00 via Android
|
28
ftfunjth 2020-02-26 11:04:44 +08:00 via Android
对参数 hash 然后想办法分布式多台服务器。数据落地可以想办法被动写回或者主动扔到 redis 然后再定时持久化。
|
29
wizardoz 2020-02-26 11:04:50 +08:00
内存会不会爆炸取决于你的内存有多少,而且直觉上这个内存消耗不大。
我觉得最应该考虑的问题是多线程方式处理每个连接还是通过异步 IO 的方式处理。如果异步 IO,我相信对服务器的要求不高。 如果是多线程,那么服务器就难了。 |
31
gemini767 2020-02-26 11:09:39 +08:00
团队没有专业人员建议 http 轮训,简单有效,最重要的可控
|
32
liqingcan 2020-02-26 11:11:51 +08:00
什么需求需要这么多 websocket im 类的需求?这玩意也不会用一台机器吧。挺好奇的
|
33
lscho 2020-02-26 11:13:47 +08:00
@XRR 想啥呢。。。websocket 和端口有什么关系,又不是 TCP。
实践出真知,几万个 websocket 连接数肯定是没啥问题的,几十万也没问题,需要考虑的就是数据量问题,数据量过大同时进来肯定不行。 |
35
realpg 2020-02-26 11:16:31 +08:00
你们老板需要一个架构师。。。
|
36
pubby 2020-02-26 11:17:39 +08:00 via Android
会不会理解有偏差,上万个参数其实可以一起传的?
|
37
ftfunjth 2020-02-26 11:19:33 +08:00 via Android
@lscho 我记得 spring websocket 默认是一个连接一个 socket 用的是异步套接字。如果是 epoll,两万个 websocket,cpu 包处理速度够的话应该没问题。怕 socket 的 receive buffer 过大。导致内核内存缓冲区不够用。如果内核内存满了的话一直在用虚拟内存怕是电脑会卡死?
|
38
realpg 2020-02-26 11:20:15 +08:00
我这里有个类似的东西。
也是客户端 开 4400 个 TCP 连接到远程,然后保存下推流,解码,入库。 用了 12 台垃圾 1U 服务器,服务器总成本一万五千元…… |
40
lasuar 2020-02-26 11:28:46 +08:00
你这个场景有点像是对 ws 服务端做鲁棒性测试
|
41
lasuar 2020-02-26 11:29:51 +08:00
哪有正常的逻辑是一方使用上 W 个端口去连接 ws 的,我建议楼主把逻辑理清楚说清楚,无厘头。。。
|
42
Xusually 2020-02-26 11:33:05 +08:00
需要长链接吗?
怎么感觉你这场景是股票行情信息同步推送? |
44
Drinker OP @sagaxu 相当于 ws 连接前缀相同,加了参数就是一个 ws 连接,现在参数的变化有一万多种,所以就有一万多连接。
|
46
Drinker OP @wizardoz 主要就是通过 WebSocketClient 来连接,不过没找到 onMessage 是异步 IO 还是多线程,搜了一下,好像都没提到。现在暂时的想法是 onMessage 有信息的时候立马推到 jms 里面,另外一台服务从队列里面一个个取出数据保存起来。
|
48
Drinker OP @liqingcan 有点类型直播的这种,比如虎牙直播,每个直播间的信息其实是一个 ws 连接,现在我知道一万个房间号,我就可以连接一万个房间的直播信息,然后把直播信息保存下来。类似这种。
|
50
fancy111 2020-02-26 11:51:19 +08:00
上万个 WS 是肯定没问题的,问题是带宽会爆
|
51
Drinker OP @pubby 有点类型直播的这种,比如虎牙直播,每个直播间的信息其实是一个 ws 连接,现在我知道一万个房间号,我就可以连接一万个房间的直播信息,然后把直播信息保存下来。类似这种。
|
52
Drinker OP @lasuar 有点类型直播的这种,比如虎牙直播,每个直播间的信息其实是一个 ws 连接,现在我知道一万个房间号,我就可以连接一万个房间的直播信息,然后把直播信息保存下来。类似这种。
|
54
lasuar 2020-02-26 12:01:23 +08:00
@Drinker 直播的 N 个 ws 连接是存在于服务端,只会占用服务端一个 ws 服务端口,程序存储的 N 个 conn 对象都是占用的同一个的端口,你这个场景就类似于拿一台机器模拟上 W 个 ws 客户端,所以才需要上 W 个端口,不要搞混了。
|
55
CodeCore 2020-02-26 12:12:20 +08:00 via iPhone
|
56
tinybaby365 2020-02-26 12:16:05 +08:00 2
之前用 golang 实现过,单机用了 24GB 的内存,大概 160w 个连接。诀窍是省内存,降低你服务的每个连接的内存消耗,我没用 net/http,虽然我用的 websocket 库是依赖 net/http,但 go 的鸭子类型可以让我用一个简陋消耗更小的 conn 替代。
另一个就是降低系统 socket 的读写 buffer。root 权限加 rlimit 设置,突破单进程的限制。 |
57
maichael 2020-02-26 12:22:39 +08:00 1
我记得之前看过测试,一台还可以的机器撑 100 万左右的 Websocket 没问题。
|
58
aguesuka 2020-02-26 12:34:59 +08:00 via Android
理论上 nio10k 个 tcp 连接没有问题,用 netty 试试呗。我估计系统瓶颈 io,cpu,然后才是内存
|
59
no1xsyzy 2020-02-26 12:37:35 +08:00
@Drinker 附加信息不要一个个回复,可以 append,可以 @ 多个人。不然你容易被降权导致别人根本收不到你的消息。
|
61
zjsxwc 2020-02-26 12:40:51 +08:00
1 万连接,java 没有问题的
|
62
realpg 2020-02-26 12:57:04 +08:00
@lasuar #41
你没见过不代表不存在且不合理 我这就有跟楼主一样的 只是 TCP 一个服务用几千个 TCP 频道实时广播信息 一般一个客户只需要订阅一个频道 但是因为性能问题,自建的地区中继,就得所有频道信息 relay 就是一组服务器几千个客户端 |
63
zfish 2020-02-26 12:58:39 +08:00
使用 elixir/erlang 开发吧,上万并发不要太轻松
|
64
lasuar 2020-02-26 13:01:55 +08:00
对于 ws 服务端来说,一台普通服务器倒不是说承受上 w 个 client 连接无压力,这个还要看消息 size 和传输频率,几十万人直播间那种一台机器的网卡都受不住了。
|
65
sampeng 2020-02-26 13:06:11 +08:00 via iPhone
先搞清楚 ws 和 tcp 的关系…另外有一句说一句。你确定对方能支持上万的 qps ?
|
66
gamexg 2020-02-26 13:16:16 +08:00
上万个没难度啊
网关类单服务器连入几十万连接,连接空闲时 120m 一个 ping,外加数据传输网卡跑到 500M+,毫无问题。 |
69
x66 2020-02-26 13:37:10 +08:00
这是要爬直播平台的弹幕和礼物吧
|
70
paoqi2048 2020-02-26 13:42:30 +08:00
|
71
Drinker OP |
72
tairan2006 2020-02-26 13:59:14 +08:00 via Android
上万个没啥难度啊…你可以用 mqtt broker,开源的都能单机上万了
|
73
pinews 2020-02-26 14:23:37 +08:00
小白请教一下
这个 api 对应的参数有个上万个,每个参数对应一个 websocket !每个参数对应的难道不应该是一个频道吗? |
74
zfish 2020-02-26 14:38:00 +08:00 1
@Drinker elixir 单机 4GB 开百万进程( Erlang 的虚拟进程,实际上底层是 Erlang 实现了自己的 CPU 调度算法,并不依赖操作系统的调度,所以可以做到极其低成本的开销去切换进程),每个进程都是独立的内存分配,百万用户的长链接都可以用百万的进程去独立负责通信,所以 Erlang 在游戏领域后台 /电信领域使用的很多,不过 Erlang 的语法有点奇怪,可以用基于 Erlang 的 Elixir 去开发
|
75
zfish 2020-02-26 14:50:10 +08:00
@zfish ![]( https://img.bmpi.dev/c5a8569f-42b1-63de-15a5-25d77f29a050.png) Elixir 的 Web 框架 Phoenix 单机两百万 WS 长链接,毫无压力
|
76
noisywolf 2020-02-26 15:27:06 +08:00
1、用 nginx+lua,就是 OpenResty,每个连接挂个 redis 的 pubsub
2、用 go,轻松解决 |
77
SjwNo1 2020-02-26 15:36:01 +08:00
gogogo
|
78
lfcyme 2020-02-26 15:52:25 +08:00
建议换 elixir + phoenix channel, 特别香 ( 逃 ~
|
80
zjq123 2020-02-26 16:07:52 +08:00 via Android
@zfish 我觉得主要是 socket 肯定涉及到内核 只不过 erl 在伪进程调度方面实现了自己一套 不涉及到操作系统进城管理了 而只涉及到内核 socket 部分
|
81
onion83 2020-02-26 16:19:55 +08:00
我觉得沟通是不是有点问题?把 webscoket 当 http 来玩了?一般的使用方法都是建立一次连接,然后不断收发数据就好了,同步响应还是异步响应,这个要看业务,连接是可以复用的。
|
82
wufakeyou 2020-02-26 16:36:51 +08:00 1
生产环境,C#+阿里云 4 核 8G,8000 个 socket 在线,资源占用 30%左右。对物联网项目来说,1W 个 socket 规模其实很小了。
|
83
Drinker OP @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 好的,谢谢提供案例,我们这边做下技术调研。 |
84
cz5424 2020-02-26 17:16:13 +08:00
golang,1w 小意思
|
86
monkeyWie 2020-02-26 17:43:12 +08:00
java 上 netty 轻松搞定好吧
|
87
pythonee 2020-02-26 20:25:31 +08:00
云服务 api gateway ?
|
88
wellsc 2020-02-26 20:33:44 +08:00
扔给 nginx 处理
|
89
laozhang 2020-02-27 03:17:01 +08:00 via iPhone
32g 的机器 100 万 ws 连接应该没问题。对 我说的单机。go 写的。
|
90
barbery 2020-02-27 09:43:22 +08:00
换 go
|
91
sicauxeon 2020-02-27 13:51:02 +08:00
经典的 C10K 问题。但是看你具体的使用场景,如果不行的话,就负载均衡做吧。
|
92
lixm 2020-02-27 17:50:48 +08:00
楼主这个是客户端啊, 单机不够就堆机器呗, 还不至于 C10K
|