V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
miniyao
V2EX  ›  WebSocket

使用 gevent 作为 Websocket 服务端,浏览器上用 setInterval 定时重复建立 Websocket,结果导致 gevent 不会自动释放之前废弃的连接,内存快要溢出了。怎么自动回收废弃连接呢

  •  
  •   miniyao · 2021-02-17 22:55:17 +08:00 · 1241 次点击
    这是一个创建于 1401 天前的主题,其中的信息可能已经有所发展或是发生改变。
    使用 gevent worker 作为 Websocket 服务端,为了避免断线,浏览器上用 setInterval 定时重复建立 Websocket,结果导致 gevent 不会自动释放之前废弃的连接,内存快要溢出了。

    开始以为客户端重复发起 websocket 连接,会覆盖先前的连接,结果发现没有。

    客户端发起新的 websocket 连接,服务器并没有立即销毁之前废弃的连接,久而久之,内存里堆砌了越来越多的废弃连接。

    问题:
    既希望避免客户端意外断线,没法自动重新连接;
    又希望不要把服务器内存逐渐挤爆了。
    发起重新连接的时候,把客户端已经关闭的 socket 连接清除了。
    怎么自动回收废弃连接呢?
    12 条回复    2021-02-18 15:29:54 +08:00
    ericls
        1
    ericls  
       2021-02-17 23:12:29 +08:00 via iPhone
    断开连接之后 应该自动释放资源的 是不是有东西再断开连接后还存在 reference?
    superrichman
        2
    superrichman  
       2021-02-17 23:18:45 +08:00 via iPhone
    我在 windows 上遇到过类似的资源不释放问题,换 linux 就没问题了
    miniyao
        3
    miniyao  
    OP
       2021-02-17 23:23:43 +08:00
    @ericls setInterval 是强制重连(类似心跳),因为也不知道之前的连接是否还存活。
    服务端只知道新连接建立成功了,之前的连接丢失了(之前的连接没有发送任何数据,和网络异常断线一样)
    miniyao
        4
    miniyao  
    OP
       2021-02-17 23:26:00 +08:00
    @superrichman 是在 linux 服务器上跑的,只是看着内存在持续增长,资源不释放,眼看就要溢出的
    yuelang85
        5
    yuelang85  
       2021-02-17 23:32:38 +08:00
    是否用了连接池?连接池如何管理的?在链接断开时是否没有释放连接池里的引用?
    是否写了 close 方法?
    没有释放,肯定是某地方还存有引用。

    最好贴出代码。
    miniyao
        6
    miniyao  
    OP
       2021-02-17 23:41:54 +08:00
    @yuelang85 没用连接池。

    这个情况就是:重新建立请求连接,让服务端不知道之前的 socket 连接和异常断线有什么区别。

    唯一的区别:就是异常断线,不会给服务器再次带来负载呀。
    yuelang85
        7
    yuelang85  
       2021-02-18 00:12:31 +08:00
    @miniyao 不是的。重连不是恢复断开的链接,而是重新建立链接,之前的那个链接就被抛弃了。

    你是用的 geventwebsocket 吗?看看 WebSocketHandler 实例的 server.clients 里面是不是有废掉的链接?我查了一圈代码,没有找到这货 release 的地方,可能需要手动 release 一下。
    ericls
        8
    ericls  
       2021-02-18 01:15:16 +08:00 via iPhone
    @miniyao 服务器不知道之前的连接状态? 走的什么协议啊? 不是 ASGI?
    Akkuman
        9
    Akkuman  
       2021-02-18 01:35:33 +08:00 via Android
    加心跳,服务端超时丢弃链接
    abersheeran
        10
    abersheeran  
       2021-02-18 11:09:27 +08:00   ❤️ 2
    WebSocket 是自带心跳帧的,不存在服务端不知道客户端已经断线了的情况。
    miniyao
        11
    miniyao  
    OP
       2021-02-18 12:52:11 +08:00
    @yuelang85 是 gevent 的,py 版只有 gevent 和 asyncio 两种主流实现吧,我也没看到销毁方法

    @abersheeran 断线知道状态,没看到自动销毁已废弃 socket 的方法(不知道系统什么时候回收内存,现在就是看着内存慢慢涨)。
    yuelang85
        12
    yuelang85  
       2021-02-18 15:29:54 +08:00
    @miniyao gevent 没有 websocket 协议的支持,是自己实现的协议吗?还是其实连接的是 socket ?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3431 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 00:47 · PVG 08:47 · LAX 16:47 · JFK 19:47
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.