对 websocket 服务器进行压测, nginx 负载均衡,该怎么做?

2017-04-27 17:33:08 +08:00
 cccRaim

服务端

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. 或许是个更好的服务端架构

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

9702 次点击
所在节点    NGINX
13 条回复
djhuahao
2017-04-27 18:02:32 +08:00
为何不抓个包试试呢?
devops
2017-04-27 18:05:23 +08:00
用 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
"""
panlilu
2017-04-27 18:07:39 +08:00
nginx 的负载模式在没有装额外插件的情况下只有 轮询 最小连接 iphash 3 种,应该是满足不了你的需求的。
比较方便的方案是用 haproxy 代替 nginx,详细配置参考 http://toon.io/configuring-haproxy-multiple-engine-io-servers/ 这篇文章。

分布式的压测工具有很多(比如 Tsung、jmeter ),但是学习曲线大都比较陡,尤其是要压 socket.io 这种。
cassia
2017-04-27 18:12:09 +08:00
session 共享做了吗?
ivyliner
2017-04-27 18:13:01 +08:00
可以增加一下 consistent_hash 试试
cccRaim
2017-04-27 18:31:24 +08:00
@cassia 使用的是同一个 redis,不是 session 问题吧
vuuv
2017-04-27 21:49:41 +08:00
websocket 协议本身有会话校验的,需要确保同一会话的请求由同一服务处理。
可以考虑在现有网卡上配置多个 IP 或者创建一批虚拟网卡,然后绑定 IP 压测,Nginx 开启 hash。
ryd994
2017-04-28 06:03:48 +08:00
IP hash 应该能用啊………
本地压测好办,127.0.0.1/8 下面的任何地址都可以用,
ip addr 127.0.0.2 dev lo
自己写个脚本加一堆地址就好了
测试工具一一对应绑在地址上
再再再不行,上 docker 啊,上虚拟机啊,上 AWS 啊
反正 AWS 又不是长跑,没多少钱的
vebuqi
2017-04-28 09:03:52 +08:00
感觉应该用 sticky 策略
yernsun
2017-04-28 10:32:41 +08:00
可以通过追加 cookie 之类的解决,然后通过 cookie 值进行 hash
cccRaim
2017-04-28 20:18:36 +08:00
@vebuqi sticky 试了,没用,测试工具估计不记录 cookie
cccRaim
2017-05-01 22:53:53 +08:00
@panlilu haproxy 试过了,好像策略上也不满足我的要求,jmeter 的 ip 欺骗好像只限于 http,ws 的还不支持
cccRaim
2017-05-02 08:44:23 +08:00
当然选择改 websocket-bench 源码也是可以的,不过我没开始看

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/357759

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX