wss高并发变慢的根源是tls握手和cpu软解密,而非协议本身;优化需聚焦卸载(如netty+openssl)、复用(会话恢复)和裁剪(精简证书链、禁用低效tls特性)。

WSS 加密本身不拖慢高并发,真正卡脖子的是 TLS 握手和 CPU 软解密 —— 优化方向必须聚焦在卸载、复用、裁剪三件事上。
为什么 WSS 在高并发下变慢?不是协议问题,是 TLS 实现问题
WSS 本质是 WebSocket + TLS,而 TLS 的性能瓶颈集中在两个阶段:首次握手(密钥协商)和每帧加解密。移动端或 Java 后端若用默认 OpenSSL 或 JVM 内置 SSLEngine,所有加密运算都走 CPU 软实现,在 5000+ 连接时,CPU usage 往往飙到 80% 以上,延迟毛刺明显。
常见错误现象包括:
- 连接建立耗时从 100ms 突增至 400ms+,且波动剧烈
- 同一台服务器,
wss并发承载量比ws低 35%~50% - GC 频率异常升高,
javax.net.ssl.SSLException: handshake timed out报错增多
Nginx 做 SSL 终结时,必须显式开启 WebSocket 代理头
Nginx 不是“开了 proxy_pass wss://”就自动适配 WebSocket。它默认把 Upgrade 请求当普通 HTTP 转发,导致后端收不到 Sec-WebSocket-Key,握手直接失败。
正确配置的关键点:
- 必须透传
Upgrade和Connection头:proxy_set_header Upgrade $http_upgrade;和proxy_set_header Connection "upgrade"; - 禁用缓冲:
proxy_buffering off;,否则二进制帧可能被截断或粘包 - 设置合理超时:
proxy_read_timeout 86400;(而非默认 60s),避免长连接被误杀 - 若用 OpenSSL 3.0+,可启用
ssl_early_data on;减少 1-RTT 握手延迟
Java 后端用 Netty + OpenSSL 动态库替代 JDK 默认 SSLEngine
JDK 自带的 SSLEngine 是纯 Java 实现,无硬件加速支持;而 Netty 集成的 netty-tcnative 可绑定系统级 OpenSSL 或 BoringSSL,进而调用 CPU 的 AES-NI 指令集,实测加解密吞吐提升 3.2 倍。
操作要点:
- Maven 引入:
netty-tcnative-boringssl-static(含静态链接,免依赖系统库) - 启动时加 JVM 参数:
-Dio.netty.handler.ssl.noOpenSsl=false - 代码中创建
SslContext时显式指定:SslContextBuilder.forServer(cert, key).sslProvider(SslProvider.OPENSSL) - 注意:Android 不支持该方案,需改用 conscrypt 或裁剪 TLS 版本
移动端(Android/iOS)绕不开的加密妥协点
手机端无法像服务端那样挂载硬件加速模块,所以得在安全与性能间做取舍:
- 禁用 TLS 1.0/1.1,但不要盲目启用 TLS 1.3 —— Android 7.0 以下设备不兼容,降级逻辑会引入额外 RTT
- 证书链必须精简,避免客户端下载中间 CA 证书;推荐用
openssl verify -untrusted root.crt chain.crt验证是否自包含 - 心跳间隔设为 45s(非 30s),避开 Android Doze 模式唤醒窗口冲突,实测地铁场景重连率从 32% 降至 9%
- 若业务允许,对非敏感字段(如心跳、状态同步)走明文
ws子通道,仅核心指令走wss
真正难的不是配置哪几行代码,而是判断哪些加密环节可以砍、哪些 TLS 特性其实没被客户端真正用到。比如 ECDSA 证书在低端安卓机上验签慢 3 倍,但如果你的客户端全在 iOS 15+ 或 Chrome 90+ 上跑,那它就是个有效选项;反之,若要兼容微信内置浏览器(X5 内核),就得老老实实用 RSA + SHA256。这些细节,文档不会写,但压测时一眼就能暴露。











