其他模块依赖 Redis 共享缓存和资源, 可以比较方便的实现多实例同时跑。
定时任务只好跑个单实例, 尽量让它简单化不出故障.
Socket 这块怎么办比较好呢, 我需要维护几百个长链接.
想做到升级服务不中断
现在的想法式尽量抽取 Socket 服务端, 后期尽量不修改...
1
buruoyanyang 2022-04-28 08:44:07 +08:00
插眼,我们也有这样的需求,想学习
|
2
THESDZ 2022-04-28 08:54:54 +08:00 1
1.Socket 多实例,不做任何状态保存,状态存到外部,例如每次传输携带 token 等
2.采取环形 hash 的方式进行节点分配 |
3
licoycn 2022-04-28 09:01:16 +08:00 1
只要有完善重连机制即可,做好状态维护
|
4
coala OP |
6
coala OP |
7
littlefishcc 2022-04-28 09:21:46 +08:00 1
2 和 3 楼方法已经说出来了,连接要重连机制,不管你是长连接还是短连接,这块可以借鉴微信开源的网络库 mars
我感觉作者想要一个类似 ngnix 代理,可以考虑在业务程序前加一个前置程序(一般游戏登录服务器),然后再分配到具体业务服务器。 A[前置] + (B+C+...)[业务服务器] B+C 等业务服务器状态通过 redis 同步数据。 |
9
sujin190 2022-04-28 09:23:11 +08:00 1
Socket 这种应该是统一接到接入网关的吧,网关不包含实际业务逻辑,一般很少需要更新重启吧,之后对内部的调用就是常规的负载均衡了
|
10
MoYi123 2022-04-28 09:34:20 +08:00 2
之前给公司做了一个比较骚的方案. 用 unix domain 传文件描述符更新长连接服务.
https://github.com/mmooyyii/mmooyyii/tree/master/codes/share_socket 看下这个代码吧. |
11
caryqy 2022-04-28 09:40:20 +08:00 1
增加一个 gateway 层,所有长连接都在这里,逻辑简单化,做到长期不需要修改
gateway 与内部 rpc 通信 |
12
nothingistrue 2022-04-28 09:45:11 +08:00 1
能跑 HTTP 负载均衡的网关,通常经过配置后就能支持长连接的负载均衡,至少 ngnix 和 caddy 是可以的,负载均衡这里不是问题。但是你这个想要的不是负责均衡而是 AB 升级,这对于长连接来说,光靠服务器就不行了。
简单来说,你可以设计个重新连接协议:服务器下发切换服务器指令,指令里面带上新服务的 IP ,客户端收到这个指令后,断开当前连接去连接那个新 IP 。更新的时候:首先开启 B 服务器,同时 A 服务阻止新的连接;然后 A 服务器给所有当前连接下发切换服务器指令;当 A 服务器的所有连接都断开,或者超过指定时间后,A 服务器搞停、更、启这一套;之后你想切回 A 服务器就重走上面的流程,不想切就结束了(因为 B 服务器应该已经更新过了)。 不建议客户端在感知到连接断开后自动重新启动。除非你能保证常规客户端连接成功(连接加注册加鉴权等)的几率接近 100%,否则当连接失败的客户端多了之后,会形同与向服务器发动拒绝服务攻击。 |
13
Chengxians 2022-04-28 09:46:25 +08:00 1
最近弄 socket 启动多实例注册到 nacos , 每个实例 socket 连接存到内存中得 每个实例都订阅了 redis ,A 发 B 或者群发得时候用 redis 推送,每个实例监听到就找自己实例有没有这个连接,有就发送,没有得实例就浪费点资源查找
|
14
fds 2022-04-28 09:47:49 +08:00 1
啥服务重启要 1 分钟呀?启动新的可以先不关闭旧的,新的每秒尝试 bind 端口,等新的 ready 了再停旧的,这样也就不到 2s 的切换时间。
进阶版在 linux 下是可以进程间传递 socket 连接,不断连的,但是要处理好状态、读写缓存啥的,比较麻烦。 |
15
sciel 2022-04-28 10:06:35 +08:00 2
https://github.com/Terry-Mao/goim 可以看看 goim 的结构,不错~
|
16
lotusp 2022-04-28 10:19:41 +08:00 1
在微服务上下文里,不管是短连接还是长连接,前端打交道的后端应该都不止一个
可以专门为长连接建立一个 gateway ,这一层对前端是长连接,对后端可以长连接,也可以短连接 后端服务升级重启做到优雅退出,就不影响前端 |
17
xuanbg 2022-04-28 13:57:38 +08:00 1
微服务升级不中断 Socket 是不可能的
|
18
GopherDaily 2022-04-28 14:23:00 +08:00 1
不中断是不可能的,做好重连就行。
长链接的负载均衡可以参考下 grpc 相关的 |
20
meeop 2022-04-28 15:17:15 +08:00
为什么要不中断,连接就是要随意可中断才行,断了重连就是
|
21
meeop 2022-04-28 15:17:46 +08:00
反之如果不能中断,那用户网随便抖一下客户端就崩了这不合适吧
|
22
meeop 2022-04-28 15:19:42 +08:00
@coala 断了重连的耗时应该是毫秒级别的,根本不会有感知.能断 2 分钟大概是你没做滚动升级吧.保证任何时刻都有可用服务器供连接就行
|
23
coala OP @meeop 客户端有重连机制, 就是现在不会很快重连, (太快重连怕服务器顶不住哇)
Socket 实现的比较简陋, 就是单机, 然后走网关连过来, 多机不知道咋整太菜这不是来问了 |
25
meeop 2022-04-28 16:34:25 +08:00
@coala ab 升级简陋的办法是先不停止 a,先启动好 b,b 起好后把流量打到 b,然后关闭 a
就算手动操作,这个切流量也就是 ng 刷下配置的事,很快的 |
26
xylophone21 2022-04-28 16:47:11 +08:00
@sciel 这个机制看起来确实很 cool ,想问一下有使用的案例或者数据吗?我们之前对 MQTT 服务做集群也考虑过类似的方案,但 MQTT 可能跨节点订阅,导致所有的流量实际还是要打到所有的节点上。但似乎没有哪个 MQTT 集群用了这种方式来做集群。
|
27
xylophone21 2022-04-28 16:53:12 +08:00 1
另外,如果你只有几百个长链接的话,可以试试 MQTT ,单机绰绰有余。这个服务本身因为抽象的很好,也不需要修改和升级,业务逻辑订阅主体后丢队列里,重启切换一些消费者就好。
|
28
mouyong 2022-04-28 19:33:59 +08:00
workerman gatewayworker
|
29
aSmallNewbie 2022-04-29 22:04:13 +08:00
之前使用消息队列解决的
|