miniyao
V2EX  ›  WebSocket

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

  •  
  •   miniyao · Feb 17, 2021 · 2076 views
    This topic created in 1914 days ago, the information mentioned may be changed or developed.
    使用 gevent worker 作为 Websocket 服务端,为了避免断线,浏览器上用 setInterval 定时重复建立 Websocket,结果导致 gevent 不会自动释放之前废弃的连接,内存快要溢出了。

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

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

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

    最好贴出代码。
    miniyao
        6
    miniyao  
    OP
       Feb 17, 2021
    @yuelang85 没用连接池。

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

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

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

    @abersheeran 断线知道状态,没看到自动销毁已废弃 socket 的方法(不知道系统什么时候回收内存,现在就是看着内存慢慢涨)。
    yuelang85
        12
    yuelang85  
       Feb 18, 2021
    @miniyao gevent 没有 websocket 协议的支持,是自己实现的协议吗?还是其实连接的是 socket ?
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2956 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 40ms · UTC 06:12 · PVG 14:12 · LAX 23:12 · JFK 02:12
    ♥ Do have faith in what you're doing.