V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
geew
V2EX  ›  问与答

有关 ab 压力测试的一个奇怪的现象

  •  
  •   geew · 2016-09-26 18:33:06 +08:00 · 6278 次点击
    这是一个创建于 3005 天前的主题,其中的信息可能已经有所发展或是发生改变。
    我用 ab 200 个并发 60000 次请求 服务器没多大压力 结果如下:

    Concurrency Level: 200
    Time taken for tests: 14.812 seconds
    Complete requests: 60000
    Failed requests: 0
    Total transferred: 42060000 bytes
    HTML transferred: 28560000 bytes
    Requests per second: 4050.64 [#/sec] (mean)
    Time per request: 49.375 [ms] (mean)
    Time per request: 0.247 [ms] (mean, across all concurrent requests)
    Transfer rate: 2772.95 [Kbytes/sec] received

    Connection Times (ms)
    min mean[+/-sd] median max
    Connect: 0 0 0.4 0 7
    Processing: 4 47 112.2 34 3049
    Waiting: 4 47 112.2 34 3049
    Total: 8 47 112.2 34 3049

    Percentage of the requests served within a certain time (ms)
    50% 34
    66% 36
    75% 38
    80% 40
    90% 44
    95% 49
    98% 68
    99% 1022
    100% 3049 (longest request)


    但是同事用 php 开了 30 个进程 同时请求 服务器会概率性报 502, 60000 个请求下来, 错误的请求非常多
    错误日志:
    2016/09/26 18:27:37 [crit] 21240#0: *1235685 connect() to 172.17.10.173:7007 failed (99: Cannot assign requested address) while connecting to upstream, client: 172.17.10.173, server: 172.17.10.173

    看了 nginx 的访问日志, ab 测试的时候 每秒请求达到 4 千多次

    但是同事的请求每秒才三千多 为啥同事的请求会有很多失败的呢? 谁能解答一下疑惑吗 不胜感激了
    第 1 条附言  ·  2016-09-26 20:10:36 +08:00

    就这么简单的开20个进程来刷都会报错....用ab跑400个并发都没啥 是不是ab的并发是假的啊...

    python

    # coding: utf8
    
    import requests
    if __name__ == '__main__':
    import sys
    argv = sys.argv
    c = argv[1]
    for i in range(int(c)):
        req = requests.get('http://172.17.10.173:7000/user/profile/?user_id=50')
        print req.json()
    

    bash脚本

    #!/bin/bash
    
    for((i=0; i<20; i++));
        do
    
            echo $i
            python t.py 3000 &
    
    done;
    
    第 2 条附言  ·  2016-09-26 21:02:49 +08:00
    以上 python 脚本会导致服务器停止响应的问题应该是 过多的请求导致了 过多的 tcp time_wait 状态导致以后的请求无法绑定端口 然后就报错了....

    实际看服务器上的 time_wait 也确实非常多

    用 ab 测试就不会有这个问题 最多的 time_wait 也就一万多...

    不知道为啥会这样, 估计是 ab 对并发请求做了优化吧
    第 3 条附言  ·  2016-09-26 21:12:53 +08:00
    好吧 我想我知道原因了

    是客户端的 TIME_WAIT 过多导致客户端无法建立连接了 是自己把自己刷死了 跟服务器没关系....
    23333
    第 4 条附言  ·  2016-09-27 18:53:40 +08:00

    总结一下吧

    • ab的并发测试没问题

    • 只是我们在多次查询的时候的写法有问题, 导致了客户端产生过多的time-wait状态进而影响了新连接的建立, 最终的情况就是客户端建立不了连接无法请求

    • 关于time-wait, 根据tcp的断开的四次握手, 主动断开方会产生time-wait的状态并保持两个msl(60秒)时间, 从而占用连接资源

    • 客户端多次请求服务端的时候, 由于每次都是新建连接(没有复用之前的连接) 而且头部默认 Connection:keep-alive, 从而导致了主动断开连接的一方是客户端, 当请求过多(20*3000)的时候, 客户端会产生大量的time-wait, 然后就没有然后了. 这个解决方法很简单, 设置每次请求的 conneciton为close, 把关闭连接提交给服务端, 但是这样会导致服务端产生大量的time-wait从而影响服务端. 所以最终的解决方案两个端都要做相应的处理

    • 客户端: 多次请求复用连接, 设置keep-alive, 比如python的话 可以用 requests.session() 新建一个会话, 每次使用该会话进行请求, 测试表明, 这种情况下不会产生过多的time-wait

    • 服务端: 更改tcp的系统参数: (以下设置表明不重用tw的连接, 但是打开系统快速回收tw)

        sysctl -w net.ipv4.tcp_tw_reuse=0
        sysctl -w net.ipv4.tcp_tw_recycle=1
        sysctl -w net.ipv4.tcp_timestamps=1
      

      添加了这几个配置之后, 可以明显的看到服务端的tw状态连接数不会过大, 维持在一个可以接受的范围了.

    参考:

    http://huoding.com/2013/12/31/316
    http://www.qmailer.net/archives/92.html
    http://www.cnblogs.com/yjf512/p/5327886.html
    
    15 条回复    2016-10-20 23:11:03 +08:00
    Citrus
        1
    Citrus  
       2016-09-26 18:48:43 +08:00
    99: Cannot assign requested address
    目测是你变量没控制好,有其它程序干扰;或者你同事是在 Nginx 同一台机器上压同一台,导致连接数超了。
    Nexvar
        2
    Nexvar  
       2016-09-26 18:55:00 +08:00 via Android
    用 php 开 30 多个进城。。。
    AB 的优点就在用少量线程实现多连接多请求
    geew
        3
    geew  
    OP
       2016-09-26 18:55:40 +08:00
    @Citrus 30 个进程不是 30 个并发吗? 他在他机子上用 ab 测试的结果跟我的差不多 但是本机跑 30 个进程来刷就会有问题 环境问题的可能性比较小
    geew
        4
    geew  
    OP
       2016-09-26 18:56:53 +08:00
    @Nexvar 我不了解 php 但是他的需求是需要在一定时间内查询多个东西 所以才会用多个进程来进行处理的 貌似 php 没有线程吧
    Citrus
        5
    Citrus  
       2016-09-26 19:00:22 +08:00   ❤️ 1
    @geew 首先明确几个问题:
    1. 你的 ab 测试时和 Nginx 是否是同一台机器
    2. PHP 测试时,是否和 Nginx 同一台机器
    3. Nginx 的 KeepAlive 设置的是多少
    4. 系统的 TCP KeepAlive 是多少
    5. 测试间隔是多少
    6. 测试期间是否确认绝对没有其他人再使用这台机器,包括定时任务等可能你没注意到的东西
    geew
        6
    geew  
    OP
       2016-09-26 19:26:39 +08:00
    @Citrus
    1. 不是同一台机器, 同一个内网
    2. 同 1, 他在他机子上用 ab 测试结果跟我用 ab 测试差距不大
    3. 没有特别设置, 默认值吧, 话说默认值多少....
    4. 也没用特别设置
    5. 间隔几分钟吧
    6. 这个没法保证, 但是 php 跑进程测试和 ab 测试的环境基本都是一致的
    Citrus
        7
    Citrus  
       2016-09-26 20:34:13 +08:00
    @geew ab 的完整命令发一下? url 请打码。
    geew
        8
    geew  
    OP
       2016-09-26 20:40:13 +08:00
    @Citrus 哈哈 没事 内网的 url
    ab -n 60000 -c 200 http://172.17.x.y:8888/user/profile/?user_id=50
    halfcrazy
        9
    halfcrazy  
       2016-09-26 21:05:55 +08:00 via Android
    @geew ab 加上-k 试试
    geew
        10
    geew  
    OP
       2016-09-26 21:13:23 +08:00
    @halfcrazy 哈哈 谢谢 你看我最后几条附言
    geew
        11
    geew  
    OP
       2016-09-26 21:21:20 +08:00
    @halfcrazy 但是 ab 测试的时候 服务端会产生很多的 TIME_WAIT 但也不是问题

    netstat -ant | grep "TIME_WAIT" | wc -l
    63873

    为啥客户端 TIME_WAIT 一到两万多就开始崩了
    ovear
        12
    ovear  
       2016-09-26 21:31:20 +08:00
    @geew ....额。。你用 http1.1 测试试。。不然端口不够是这样的。。
    Citrus
        13
    Citrus  
       2016-09-26 22:05:26 +08:00
    @geew 从一开始就猜到是你 TIME_WAIT 的原因。。。不过没想到是你客户端撑不住。 ulimit 看看限制。
    geew
        14
    geew  
    OP
       2016-09-27 10:03:51 +08:00
    @Citrus 看哪个
    core file size (blocks, -c) 0
    data seg size (kbytes, -d) unlimited
    scheduling priority (-e) 0
    file size (blocks, -f) unlimited
    pending signals (-i) 63603
    max locked memory (kbytes, -l) 64
    max memory size (kbytes, -m) unlimited
    open files (-n) 1024
    pipe size (512 bytes, -p) 8
    POSIX message queues (bytes, -q) 819200
    real-time priority (-r) 0
    stack size (kbytes, -s) 8192
    cpu time (seconds, -t) unlimited
    max user processes (-u) 63603
    virtual memory (kbytes, -v) unlimited
    file locks (-x) unlimited

    这是我的电脑 它当客户端的时候 TIME_WAIT 达到三万那样子就不行了 但是当服务端 TIME_WAIT 达到六万多都没啥...
    geew
        15
    geew  
    OP
       2016-10-20 23:11:03 +08:00
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2500 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 15:50 · PVG 23:50 · LAX 07:50 · JFK 10:50
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.