首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python 学习手册
Python Cookbook
Python 基础教程
Python Sites
PyPI - Python Package Index
http://www.simple-is-better.com/
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
cz5424
V2EX  ›  Python

如何维护 socket 链接池

  •  1
     
  •   cz5424 · 204 天前 · 2314 次点击
    这是一个创建于 204 天前的主题,其中的信息可能已经有所发展或是发生改变。

    背景

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

    疑问

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

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

    第 1 条附言  ·  204 天前
    可能用任务的方式描述会清晰一些

    目前设计:

    开始任务-> 建立链接-> 发送数据- >关闭链接->任务结束

    理想中的设计

    开始任务-> 查找有没有已经建立的链接(没有则建立)-> 发送数据->任务结束
    29 回复  |  直到 2019-08-12 08:54:46 +08:00
    BBCCBB
        1
    BBCCBB   204 天前
    如果你熟悉 java 可以看看 Netty 的 ChannelPool 的实现. 写的非常好.
    ShangAliyun
        2
    ShangAliyun   204 天前
    python 语言不清楚,C#下是设置 keepalive 时间自动释放掉不活跃的链接
    并发量高需要提高后端负载服务器数量
    sujin190
        3
    sujin190   204 天前
    你这是要多路复用吧,如果应用层协议不支持,基本不可行
    如果连接重用的话,有状态不行,无状态倒是可以

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

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

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

    一个线程 /协程专门用于心跳发送,顺便回收长时间不使用的 connection
    lolizeppelin
        19
    lolizeppelin   204 天前
    顺便,tcp 层维持链接不一定靠谱,最好在应用层心跳,基本上常用的服务器都有用于心跳检测的 PING 协议包
    oahebky
        20
    oahebky   204 天前 via Android
    说白了就是要定时发心跳包到链接的另一端,为了不让对端因为链接长时间没有活动而主动断开连接。
    所以你应该确定(找到 /定义)一个空包类型,这个空包类型需要是最终接受数据设备能够“知道”的--无意义的包。
    然后在代码中开一个线程类,线程类中维护一个链接“池”,将想要保持的暂存链接交给这个运行中的线程类。
    至于这个线程类,它的工作就是不停地定时取出链接池内的链接发空包,再返回池。
    lloovve
        21
    lloovve   204 天前 via iPhone
    断开除非你客户端定时自动链接服务器
    lazyfighter
        22
    lazyfighter   204 天前
    netty 不是现成的吗
    iamsk
        23
    iamsk   204 天前
    可以基于 socketpool 实现一个,其中 max_lifetime 设置生命周期
    https://github.com/benoitc/socketpool
    基于这个比较简单,也可以参考 redis 的 python 库实现,见 connection.py
    MMMMMMMMMMMMMMMM
        24
    MMMMMMMMMMMMMMMM   204 天前
    跟网游一样,发心跳包

    别无他法
    realpg
        25
    realpg   204 天前
    这种场景…… UDP 大法好……
    cabing
        26
    cabing   204 天前
    你自己也可以做个吧。

    把连接放到容器里面,加上定时器,定时心跳。
    cz5424
        27
    cz5424   204 天前 via iPhone
    谢谢各位大佬,下班了没看信息,等我慢慢消化一波
    cz5424
        28
    cz5424   203 天前
    @lazyfighter
    @BBCCBB
    @DeepRedApple

    不是 java, 在 python 环境下, 我会去参考它的实现
    Tracy1997
        29
    Tracy1997   199 天前
    楼主有方案了吗,能不能贴下代码。最近也要写一个 TCP 服务器,接受几千个长连接一直发数据过来然后保存到数据库,还没想好怎么弄。多路复用可以吗?
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3031 人在线   最高记录 5168   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 15:02 · PVG 23:02 · LAX 07:02 · JFK 10:02
    ♥ Do have faith in what you're doing.