Envoy WebSocket连接限流需结合rate_limit过滤器与外部计数器(如Redis),max_connections设为略高于后端承载能力(如850),配合Websocat--conncap仅适用于单实例场景,生产环境须外移鉴权与连接统计。

直接上结论:连接数激增导致崩溃,核心不是“加机器”,而是“卡住入口+控住连接+熔断异常路径”。Envoy 做第一道限流闸门,Websocat 或业务层做连接级熔断,心跳与速率限制必须同步落地——三者缺一不可。
Envoy 的 WebSocket 连接数硬限流怎么配
Envoy 本身不解析 WebSocket 协议帧,但它能基于 HTTP Upgrade 请求做连接级限流。关键在 http_connection_manager 的 max_stream_duration 和上游集群的 max_requests_per_connection,但真正起效的是 rate_limit_service 配合全局连接数统计器。
- 必须启用
envoy.rate_limit过滤器,并对接 Redis 或本地计数器(如envoy.redis_proxy)来跟踪当前活跃连接数 -
static_resources.clusters[0].circuit_breakers.thresholds.max_connections要设为略高于你后端实际承载能力(比如后端撑 800 连接,这里设 850),超阈值直接返回 429 - 别依赖
listener.connection_limit:它只限新 TCP 连接,对已升级的 WebSocket 连接无效 - 示例关键片段:
clusters:<br> - name: ws_backend<br> circuit_breakers:<br> thresholds:<br> max_connections: 850
Websocat 的 --conncap 是不是够用
--conncap 是够用的,但仅适用于单实例、无代理、无负载均衡的简单场景。它本质是进程内计数器,靠 AtomicUsize + try_acquire 实现,不跨进程、不跨节点、不持久化。
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
- 生产环境若用了 Kubernetes 或多实例部署,
--conncap 100在每个 Pod 上都生效,等于总容量翻倍,完全失控 - 它不区分合法用户和扫描器:一个恶意 IP 疯狂建连,会快速占满配额,正常用户进不来
- 它不响应连接建立后的异常行为:比如连接成功但不发消息、或疯狂发 ping 不处理 pong,
--conncap不感知 - 替代方案:用 Websocat 的
--on-connect脚本调用外部鉴权服务(如 JWT 校验 + Redis 计数),把连接准入逻辑外移
为什么加了限流还是崩溃?查这三个点
限流配置写了,监控也上了,但流量高峰时照样 OOM 或 CPU 100%,大概率卡在这三个漏点:
-
tokio::net::TcpListener的 backlog 队列溢出:Linux 默认net.core.somaxconn=128,高并发下新连接在内核队列就丢包,需调大并匹配应用层TcpListener::incoming()消费速度 - 未设置单连接读写缓冲区上限:Rust 的
tokio::net::TcpStream默认无界,恶意客户端发超大帧(如 100MB JSON)会直接吃光内存;必须用read_buf+write_buf显式约束,或在协议层用websocket::Message::is_text()前先检查长度 - 心跳超时未触发主动关闭:很多实现只设了
set_read_timeout,但没配set_pong_timeout或没注册set_pong_handler,导致僵尸连接堆积;正确做法是conn.set_pong_handler(|_| { conn.set_read_deadline(Instant::now() + Duration::from_secs(60)); })
最易被忽略的是:限流只管“进”,不管“留”。一个连接进来后持续空转、不发数据也不关,它就永远占着内存和文件描述符——这种连接必须靠心跳超时+主动 close 清理,而不是指望限流器把它拦在外面。










