V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
NGINX
NGINX Trac
3rd Party Modules
Security Advisories
CHANGES
OpenResty
ngx_lua
Tengine
在线学习资源
NGINX 开发从入门到精通
NGINX Modules
ngx_echo
cccRaim
V2EX  ›  NGINX

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

  •  1
     
  •   cccRaim ·
    cccraim · 2017-04-27 17:33:08 +08:00 · 9653 次点击
    这是一个创建于 2751 天前的主题,其中的信息可能已经有所发展或是发生改变。

    服务端

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

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

    第 1 条附言  ·  2017-05-01 23:43:43 +08:00

    本地压测解决了。可喜可贺可喜可贺。本来还想改websocket-bench源码的,还好还没开始改。

    负载均衡服务器:

    依然采用nginx,nginx的1.7.2版本以后自带hash了,自定义配置各种策略,所以不用装consistent_hash。

    测试工具:

    测试工具换成jmeter。
    因为websocket-bench可自定义的东西太少,并且如果要根据nginx负载均衡的策略来看,我压测的每个请求必须得每个请求都不太一样,此处我采用jmeter的random函数,我在请求的参数加上了${__Random(1,100)},这是jmeter的随机函数,当然范围可自定义,倒是实现了压测时每个请求都不太一样。

    所以根据我上面的改动,nginx的配置改动如下

    #ip_hash;
    hash $request_uri; # 根据请求的uri来分配
    

    感谢@ivyliner 的回复让我在绞尽脑汁想找测试工具的时候让我把解决问题出发点换到了服务器上面(虽然他本人肯定没意识到),之前绕的路太多了,辛酸泪就不说了。甚至在jmeter的ws的sample没有模拟ip功能的情况下,想要改java代码(我真是不想活了, QAQ我明明是个前端)

    13 条回复    2017-05-02 08:44:23 +08:00
    djhuahao
        1
    djhuahao  
       2017-04-27 18:02:32 +08:00
    为何不抓个包试试呢?
    devops
        2
    devops  
       2017-04-27 18:05:23 +08:00   ❤️ 1
    用 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
        3
    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
        4
    cassia  
       2017-04-27 18:12:09 +08:00
    session 共享做了吗?
    ivyliner
        5
    ivyliner  
       2017-04-27 18:13:01 +08:00   ❤️ 1
    可以增加一下 consistent_hash 试试
    cccRaim
        6
    cccRaim  
    OP
       2017-04-27 18:31:24 +08:00
    @cassia 使用的是同一个 redis,不是 session 问题吧
    vuuv
        7
    vuuv  
       2017-04-27 21:49:41 +08:00 via Android
    websocket 协议本身有会话校验的,需要确保同一会话的请求由同一服务处理。
    可以考虑在现有网卡上配置多个 IP 或者创建一批虚拟网卡,然后绑定 IP 压测,Nginx 开启 hash。
    ryd994
        8
    ryd994  
       2017-04-28 06:03:48 +08:00 via Android
    IP hash 应该能用啊………
    本地压测好办,127.0.0.1/8 下面的任何地址都可以用,
    ip addr 127.0.0.2 dev lo
    自己写个脚本加一堆地址就好了
    测试工具一一对应绑在地址上
    再再再不行,上 docker 啊,上虚拟机啊,上 AWS 啊
    反正 AWS 又不是长跑,没多少钱的
    vebuqi
        9
    vebuqi  
       2017-04-28 09:03:52 +08:00 via Android
    感觉应该用 sticky 策略
    yernsun
        10
    yernsun  
       2017-04-28 10:32:41 +08:00
    可以通过追加 cookie 之类的解决,然后通过 cookie 值进行 hash
    cccRaim
        11
    cccRaim  
    OP
       2017-04-28 20:18:36 +08:00
    @vebuqi sticky 试了,没用,测试工具估计不记录 cookie
    cccRaim
        12
    cccRaim  
    OP
       2017-05-01 22:53:53 +08:00
    @panlilu haproxy 试过了,好像策略上也不满足我的要求,jmeter 的 ip 欺骗好像只限于 http,ws 的还不支持
    cccRaim
        13
    cccRaim  
    OP
       2017-05-02 08:44:23 +08:00
    当然选择改 websocket-bench 源码也是可以的,不过我没开始看
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4635 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 10:02 · PVG 18:02 · LAX 02:02 · JFK 05:02
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.