如何维护 socket 链接池

2019-08-07 15:09:50 +08:00
 cz5424

背景

每个任务需要建立一个 tcp 链接, 发送数据到 iot 设备, 在并发量高的情况下,tcp 链接不能有效的复用, 每次链接花费的代价太高

疑问

想要请教一下有没有维护一个 socket 链接池的方法或者例子?

使链接发起之后在一定时间内保持 tcp 链接不中断, 如 rabbitmq 的 60 秒不活跃就关闭链接

3977 次点击
所在节点    Python
29 条回复
BBCCBB
2019-08-07 15:22:24 +08:00
如果你熟悉 java 可以看看 Netty 的 ChannelPool 的实现. 写的非常好.
ShangAliyun
2019-08-07 15:36:22 +08:00
python 语言不清楚,C#下是设置 keepalive 时间自动释放掉不活跃的链接
并发量高需要提高后端负载服务器数量
sujin190
2019-08-07 15:46:59 +08:00
你这是要多路复用吧,如果应用层协议不支持,基本不可行
如果连接重用的话,有状态不行,无状态倒是可以

要么你自己再封装,那就是 vpn 差不多了
cz5424
2019-08-07 17:02:59 +08:00
@sujin190 服务端决定了链接不同设备就必须发起一个 socket 链接, 我这个客户端可能会收到几千个任务,假设其中 50 个是链接到相同设备的,目前用 celery 的设计, 会造成这个设备的链接一直链接断开链接断开. 目的是想让这个 socket 保持住
janxin
2019-08-07 17:05:26 +08:00
本来以为能看懂的,但是后面似乎看不懂了,为什么一个设备要几十个连接...
cz5424
2019-08-07 17:08:29 +08:00
@janxin 因为任务周期决定了....没有 socket 池,就是收到任务建立链接,任务完成释放链接
Player1973
2019-08-07 17:12:33 +08:00
有多少个设备
Player1973
2019-08-07 17:15:33 +08:00
我这边至多会有 5K 多个设备点位、采取的措施是长连接,维持一个设备一个连接不断开
cz5424
2019-08-07 17:15:52 +08:00
@Player1973 目前是 1w+吧, 服务设计预计支持 10w
cz5424
2019-08-07 17:17:22 +08:00
@Player1973 想要的就是维持长链接的方法..比如全局变量..之类的...
Player1973
2019-08-07 17:19:03 +08:00
@cz5424
哦哦、你可以看下我的方案 https://gitee.com/hlmycode/HL_agent.git
DeepRedApple
2019-08-07 17:21:22 +08:00
直接使用 Netty 不就好了 多好的技术
sujin190
2019-08-07 17:36:17 +08:00
@cz5424 #4 你这是通过长连接往 rabbitmq 推消息,然后 celery 处理?没懂你同一设备为啥需要多个连接啊
不同消息完全可以放在一个连接里发送,为啥需要多个连接。。
janxin
2019-08-07 17:50:31 +08:00
@cz5424 看描述你是向设备推送数据才建立连接?这样子只要做个超时时间标记和 fd 表就可以了,断开采用统一的维护机制。对于已经建立连接的设备就使用已有 fd,如果没有则创建;独立检查轮巡是不是已到超时时间,到了就关闭
misaka19000
2019-08-07 17:54:11 +08:00
如果你不主动 close,操作系统是不会主动断开 TCP 连接的,所以你不需要做任何事情,连接就会被维持
misaka19000
2019-08-07 17:56:15 +08:00
哦,你是要连接复用是吧,这个更简单了,做一个 ip:port -> connection(本质上是 fd) 的映射关系,需要使用连接的时候先检索一下存在就直接使用,不存在再创建
xnode
2019-08-07 17:58:01 +08:00
单独开一个进程 做一个定时器,timer 循环检查 长时间的垃圾连接
lolizeppelin
2019-08-07 18:23:53 +08:00
简单可以看看 python redis 的实现

rabbitmq 心跳抄 openstack 的 oslo_messaging,的做法自己处理下就行了

基本上就是
写个优先级锁(避免心跳抢占具体执行),每个 connection 都记录上次使用时间和心跳包时间,用于判断是否发心跳 /是否长期不用

一个线程 /协程专门用于心跳发送,顺便回收长时间不使用的 connection
lolizeppelin
2019-08-07 18:27:08 +08:00
顺便,tcp 层维持链接不一定靠谱,最好在应用层心跳,基本上常用的服务器都有用于心跳检测的 PING 协议包
oahebky
2019-08-07 18:57:06 +08:00
说白了就是要定时发心跳包到链接的另一端,为了不让对端因为链接长时间没有活动而主动断开连接。
所以你应该确定(找到 /定义)一个空包类型,这个空包类型需要是最终接受数据设备能够“知道”的--无意义的包。
然后在代码中开一个线程类,线程类中维护一个链接“池”,将想要保持的暂存链接交给这个运行中的线程类。
至于这个线程类,它的工作就是不停地定时取出链接池内的链接发空包,再返回池。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/589831

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX