每个任务需要建立一个 tcp 链接, 发送数据到 iot 设备, 在并发量高的情况下,tcp 链接不能有效的复用, 每次链接花费的代价太高
想要请教一下有没有维护一个 socket 链接池的方法或者例子?
使链接发起之后在一定时间内保持 tcp 链接不中断, 如 rabbitmq 的 60 秒不活跃就关闭链接
1
BBCCBB 2019-08-07 15:22:24 +08:00
如果你熟悉 java 可以看看 Netty 的 ChannelPool 的实现. 写的非常好.
|
2
ShangAliyun 2019-08-07 15:36:22 +08:00
python 语言不清楚,C#下是设置 keepalive 时间自动释放掉不活跃的链接
并发量高需要提高后端负载服务器数量 |
3
sujin190 2019-08-07 15:46:59 +08:00
你这是要多路复用吧,如果应用层协议不支持,基本不可行
如果连接重用的话,有状态不行,无状态倒是可以 要么你自己再封装,那就是 vpn 差不多了 |
4
cz5424 OP @sujin190 服务端决定了链接不同设备就必须发起一个 socket 链接, 我这个客户端可能会收到几千个任务,假设其中 50 个是链接到相同设备的,目前用 celery 的设计, 会造成这个设备的链接一直链接断开链接断开. 目的是想让这个 socket 保持住
|
5
janxin 2019-08-07 17:05:26 +08:00
本来以为能看懂的,但是后面似乎看不懂了,为什么一个设备要几十个连接...
|
7
Player1973 2019-08-07 17:12:33 +08:00
有多少个设备
|
8
Player1973 2019-08-07 17:15:33 +08:00
我这边至多会有 5K 多个设备点位、采取的措施是长连接,维持一个设备一个连接不断开
|
9
cz5424 OP @Player1973 目前是 1w+吧, 服务设计预计支持 10w
|
10
cz5424 OP @Player1973 想要的就是维持长链接的方法..比如全局变量..之类的...
|
11
Player1973 2019-08-07 17:19:03 +08:00
|
12
DeepRedApple 2019-08-07 17:21:22 +08:00
直接使用 Netty 不就好了 多好的技术
|
13
sujin190 2019-08-07 17:36:17 +08:00
@cz5424 #4 你这是通过长连接往 rabbitmq 推消息,然后 celery 处理?没懂你同一设备为啥需要多个连接啊
不同消息完全可以放在一个连接里发送,为啥需要多个连接。。 |
14
janxin 2019-08-07 17:50:31 +08:00
@cz5424 看描述你是向设备推送数据才建立连接?这样子只要做个超时时间标记和 fd 表就可以了,断开采用统一的维护机制。对于已经建立连接的设备就使用已有 fd,如果没有则创建;独立检查轮巡是不是已到超时时间,到了就关闭
|
15
misaka19000 2019-08-07 17:54:11 +08:00
如果你不主动 close,操作系统是不会主动断开 TCP 连接的,所以你不需要做任何事情,连接就会被维持
|
16
misaka19000 2019-08-07 17:56:15 +08:00 1
哦,你是要连接复用是吧,这个更简单了,做一个 ip:port -> connection(本质上是 fd) 的映射关系,需要使用连接的时候先检索一下存在就直接使用,不存在再创建
|
17
xnode 2019-08-07 17:58:01 +08:00
单独开一个进程 做一个定时器,timer 循环检查 长时间的垃圾连接
|
18
lolizeppelin 2019-08-07 18:23:53 +08:00
简单可以看看 python redis 的实现
rabbitmq 心跳抄 openstack 的 oslo_messaging,的做法自己处理下就行了 基本上就是 写个优先级锁(避免心跳抢占具体执行),每个 connection 都记录上次使用时间和心跳包时间,用于判断是否发心跳 /是否长期不用 一个线程 /协程专门用于心跳发送,顺便回收长时间不使用的 connection |
19
lolizeppelin 2019-08-07 18:27:08 +08:00
顺便,tcp 层维持链接不一定靠谱,最好在应用层心跳,基本上常用的服务器都有用于心跳检测的 PING 协议包
|
20
oahebky 2019-08-07 18:57:06 +08:00 via Android
说白了就是要定时发心跳包到链接的另一端,为了不让对端因为链接长时间没有活动而主动断开连接。
所以你应该确定(找到 /定义)一个空包类型,这个空包类型需要是最终接受数据设备能够“知道”的--无意义的包。 然后在代码中开一个线程类,线程类中维护一个链接“池”,将想要保持的暂存链接交给这个运行中的线程类。 至于这个线程类,它的工作就是不停地定时取出链接池内的链接发空包,再返回池。 |
21
lloovve 2019-08-07 19:40:25 +08:00 via iPhone
断开除非你客户端定时自动链接服务器
|
22
lazyfighter 2019-08-07 19:55:42 +08:00
netty 不是现成的吗
|
23
iamsk 2019-08-07 20:30:00 +08:00
可以基于 socketpool 实现一个,其中 max_lifetime 设置生命周期
https://github.com/benoitc/socketpool 基于这个比较简单,也可以参考 redis 的 python 库实现,见 connection.py 。 |
24
MMMMMMMMMMMMMMMM 2019-08-07 20:59:22 +08:00
跟网游一样,发心跳包
别无他法 |
25
realpg 2019-08-07 21:12:25 +08:00
这种场景…… UDP 大法好……
|
26
cabing 2019-08-07 21:18:06 +08:00
你自己也可以做个吧。
把连接放到容器里面,加上定时器,定时心跳。 |
27
cz5424 OP 谢谢各位大佬,下班了没看信息,等我慢慢消化一波
|
28
cz5424 OP |
29
Tracy1997 2019-08-12 08:54:46 +08:00
楼主有方案了吗,能不能贴下代码。最近也要写一个 TCP 服务器,接受几千个长连接一直发数据过来然后保存到数据库,还没想好怎么弄。多路复用可以吗?
|