技术解析

对 websocket 服务器进行压测, nginx 负载均衡,该怎么做?
0
2021-05-20 21:33:33
idczone

服务端

node+socket.io

测试工具

我使用的是websocket-bench进行并发测试。

服务器和测试都在本地。node 端采用多进程多端口。

问题:400 错误

但是测试的过程中发现,负载只在一个 ws 服务器的时候是没问题的,但是同时使用多个 ws 服务器,就会出现 400 错误,请求错误。

我初步估计是发送 ws 的 key 的时候和之后升级协议分配到了不同的服务器,导致不认这个请求,所以报 400 错误。如果还有其他可能,请指正。

nginx 配置如下

upstream io_nodes {
    #ip_hash; # 实际需求肯定采用这个策略,但是本地压测使用的都是同一个 ip,将会导致请求只分配到同一个服务器上
    server 127.0.0.1:8001;
    server 127.0.0.1:8002;
    server 127.0.0.1:8003;
    server 127.0.0.1:8004;
}

server {
    listen 8088;
    server_name server.com;

    error_log  logs/error.log debug;
    access_log  logs/access.log;
    
    location / {
        proxy_set_header Upgrade $http_upgrade;
        proxy_set国外服务器_header Connection "upgrade";
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_http_version 1.1;
        proxy_pass http://io_nodes;
    }
}

求解决方法

  1. 或许是希望好心人能提供能解决这种情况的测试工具
  2. 或许是一个正确的 nginx 配置或一致性策略
  3. 或许是个更好的服务端架构

我的毕设不解决这个问题大概就要吹了- -


为何不抓个包试试呢?

用 go 写,就不需要 nginx 了。有 cloudflare 为这个背书呢 https://blog.cloudflare.com/exposing-go-on-the-internet/
"""
The days of needing NGINX in front of all Go services are gone
"""

nginx 的负载模式在没有装额外插件的情况下只有 轮询 最小连接 iphash 3 种,应该是满足不了你的需求的。
比较方便的方案是用 haproxy 代替 nginx,详细配置参考 http://toon.io/configuring-haproxy-multiple-engine-io-servers/ 这篇文章。
分布式的压测工具有很多(比如 Tsung、jmeter ),但是学习曲线大都比较陡,尤其是要压 socket.io 这种。

session 共享做了吗?

可以增加一下 consistent_hash 试试

使用的是同一个 redis,不是 session 问题吧

websocket 协议本身有会话校验的,需要确保同一会话的请求由同一服务处理。
可以考虑在现有网卡上配置多个 IP 或者创建一批虚拟网卡,然后绑定 IP 压测,Nginx 开启 hash。

IP hash 应该能用啊………
本地压测好办,127.0.0.1/8 下面的任何地址都可以用,
ip addr 127.0.0.2 dev lo
自己写个脚本加一堆地址就好了
测试工具一一对应绑在地址上
再再再不行,上 docker 啊,上虚拟机啊,上 AWS 啊
反正 AWS 又不是长跑,没多少钱的

感觉应该用 sticky 策略

可以通过追加 cookie 之类的解决,然后通过 cookie 值进行 hash

sticky 试了,没用,测试工具估计不记录 cookie

haproxy 试过了,好像策略上也不满足我的要求,jmeter 的 ip 欺骗好像只限于 http,ws 的还不支持

当然选择改 websocket-bench 源码也是可以的,不过我没开始看

数据地带为您的网站提供全球顶级IDC资源
在线咨询
专属客服