You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

高负载WebSocket应用卡顿如何解决?附Gorilla Websocket实现代码

1分钟断开原因

  • 没有配置Gorilla WebSocket的心跳保活机制:Gorilla WebSocket默认读超时为60秒,你代码没有设置PongHandler,也没有主动向客户端发送Ping帧,当连接超过60秒没有收到客户端的任何消息时,服务端会主动断开连接,这就是新连接稳定1分钟左右断开的直接原因。

卡顿阻塞原因

  • 互斥锁持有期间存在可能永久阻塞的操作:你在持有全局互斥锁tm.mx的状态下向Collectingchan写数据,如果该通道是无缓冲通道且消费端处理速度跟不上,或者消费端已经异常退出,写通道的操作会永久阻塞,导致tm.mx锁无法释放。后续所有需要操作连接列表、订阅/取消订阅股票的请求都会因为拿不到锁被卡住,整个服务进入假死状态,不再推送数据。
  • 连接清理逻辑性能极差:removeConnection方法删除一个连接时,需要遍历全局所有股票的所有客户端连接,当订阅的股票数量和连接数上来后,该操作耗时会指数级上升,且执行期间全程持有全局锁,会进一步放大阻塞问题。

其他潜在并发问题

  • HTTP Handler签名非法:http.HandleFunc要求注册的Handler签名必须是func(http.ResponseWriter, *http.Request),你当前的echo方法多了Collectingchan参数,该注册逻辑实际无法正常编译运行,推测是你代码中Collectingchan是TicksModel的成员变量,贴代码时错误写成了入参,建议修正该问题,把Collectingchan放到结构体中统一管理。
  • 并发修改Upgrader配置:你在每个连接的Handler中都重新赋值tm.upgrader.CheckOrigin,该操作不是线程安全的,高并发下会出现并发读写问题,导致连接升级异常,建议在初始化TicksModel时就设置好CheckOrigin,不要在请求处理逻辑中修改。
  • 死锁风险:writeMessages方法写消息失败时会调用removeConnection拿全局锁,而如果此时有其他协程已经持有锁在写Collectingchan阻塞,就会出现死锁。

内容的提问来源于stack exchange,提问作者Nurislom Rakhmatullaev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 06:51:01