V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
goforwardv2
V2EX  ›  程序员

怎么把单机的高并发做到最高,为什么 1 万的并发和 5 万的并发, CPU 占用没有变化?

  •  
  •   goforwardv2 · 160 天前 · 2297 次点击
    这是一个创建于 160 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近基于开源的高性能网络库 muduo/libhv ,分别搭建一个简单的 HTTP 服务器,就一个接口/get ,然后返回 hello world. HTTP 服务器单独部署在 8 核的 ubuntu 机器上,代码中开了 8 个工作线程。

    在另一台 12 核的 ubuntu 机器上用 wrk 对 HTTP 服务器进行压测。两台机器都分别用ulimit -n 65536开启了最大的连接数。

    HTTP 服务器还做了一些内核参数的优化,在/etc/sysctl.conf 里面加入了如下内容:
    net.ipv4.tcp_keepalive_time = 1200
    net.ipv4.ip_local_port_range = 10000 65000
    net.ipv4.tcp_max_syn_backlog = 8192
    net.ipv4.tcp_max_tw_buckets = 5000
    net.ipv4.tcp_max_syn_backlog = 65536
    net.core.netdev_max_backlog = 32768
    net.core.somaxconn = 32768
    net.core.wmem_default = 8388608
    net.core.rmem_default = 8388608
    net.core.rmem_max = 16777216
    net.core.wmem_max = 16777216
    net.ipv4.tcp_synack_retries = 2
    net.ipv4.tcp_syn_retries = 2
    net.ipv4.tcp_tw_reuse = 1
    net.ipv4.tcp_wmem = 8192 436600 873200
    net.ipv4.tcp_rmem = 32768 436600 873200
    net.ipv4.tcp_mem = 94500000 91500000 92700000
    net.ipv4.tcp_max_orphans = 3276800
    net.ipv4.tcp_fin_timeout = 30

    但发现有几个现象不是很理解:

    1. wrk 同时开启的客户端越少,得到的 QPS 数据越好,以下是具体数据

    `alex@alex-System-Product-Name:~/code/wrk$ wrk -t12 -c1000 -d100s
    12 threads and 1000 connections
    Thread Stats Avg Stdev Max +/- Stdev
    Latency 41.01ms 37.09ms 542.37ms 88.01%
    Req/Sec 2.38k 1.11k 8.33k 62.50%
    2838582 requests in 1.67m, 319.44MB read
    Requests/sec: 28358.09
    Transfer/sec: 3.19MB

    alex@alex-System-Product-Name:~/code/wrk$ wrk -t12 -c10000 -d100s
    12 threads and 10000 connections
    Thread Stats Avg Stdev Max +/- Stdev
    Latency 364.67ms 115.01ms 1.49s 81.21%
    Req/Sec 2.04k 0.98k 7.46k 61.89%
    2430692 requests in 1.67m, 273.53MB read
    Socket errors: connect 0, read 0, write 0, timeout 93
    Requests/sec: 24292.02
    Transfer/sec: 2.73MB

    alex@alex-System-Product-Name:~/code/wrk$ wrk -t36 -c50000 -d60s
    36 threads and 50000 connections
    Thread Stats Avg Stdev Max +/- Stdev
    Latency 910.52ms 276.46ms 2.00s 83.81%
    Req/Sec 836.26 0.90k 13.56k 86.67%
    1489770 requests in 1.00m, 167.65MB read
    Socket errors: connect 21740, read 0, write 0, timeout 16523
    Requests/sec: 24790.08
    Transfer/sec: 2.79MB
    `

    2. 不管以上那种压测的方式,HTTP 服务器的 CPU 占用都稳定在 240%左右,一核 30%左右,等于没有系统的 CPU 利用一点都不高,没有完全压榨机器的 CPU 性能,按道理并发数不同,服务器的压力应该也不同。

    3. 当在压测服务器之间和 HTTP 服务器之间,用另一台 8 和的机器搭建 Nginx 做代理,然后 wrk 直接向 Nginx 请求,Nginx 再转发,发现没有直接法相 HTTP 服务器得到的 QPS 高,Nginx 的作用难道不是替后端服务抵挡高并发吗,怎么加了,效果变差了。Nginx 的配置也加入了:

    worker_processes auto; worker_rlimit_nofile 30000; events { worker_connections 10240; }

    第 1 条附言  ·  160 天前
    确实是测试机的个关系,换了一台 24 核(Intel(R) Core(TM) i9),用:
    hey -n 1000000 -c 1000 http://172.16.15.9:8090/get 测试,结果如下:
    Summary:
    Total: 6.2846 secs
    Slowest: 0.0940 secs
    Fastest: 0.0001 secs
    Average: 0.0062 secs
    Requests/sec: 159119.5821

    然后 HTTP 服务器的 CPU 占用率也提高到了 400%,看来压测工具想真正模拟高并发,需要机器的性能比较好。
    13 条回复    2024-05-31 18:03:18 +08:00
    lsk569937453
        1
    lsk569937453  
       160 天前
    1.换压测工具试试,https://github.com/rakyll/hey
    2.或者可以换 echo-server,https://github.com/lsk569937453/echo-server 。我的这个 echo-server ,4core 8g 的机器压测结果如下:
    hey -n 1000000 -c 1000 http://backend:8080

    Summary:
    Total: 4.2522 secs
    Slowest: 0.2671 secs
    Fastest: 0.0000 secs
    Average: 0.0041 secs
    Requests/sec: 235174.6871

    Total data: 1000000 bytes
    Size/request: 1 bytes


    3.让我猜测的话,我更倾向于压测机器(wrk 执行命令的机器)的性能达到了瓶颈。
    goforwardv2
        2
    goforwardv2  
    OP
       160 天前
    @lsk569937453 多谢,我试下
    shakeyo
        3
    shakeyo  
       160 天前
    1 是因为服务端线程太少客户端连接数太多,很多都耗在连接跟响应等待了
    2 应该是跟 muduo/libhv 的模型有关,也跟你 8 个线程数设定有关,加大线程池肯定可以提高
    3nginx 作为代理,等于多了一次连接,这都需要时间

    菜鸡的浅薄理解,蹲一个大佬
    lsk569937453
        4
    lsk569937453  
       160 天前
    @lsk569937453 压测的时候还有一个问题是不可忽视的,就是网络延迟。最好看一下两台机器的网络延迟是多少。高性能的 echo-server 的 TPS 不会很低的。

    你在压测的机器前面加了一层 Nginx 的转发,QPS 变低是必然的,Nginx 至少降低 10%的性能。Nginx 的作用是负载均衡。请求在经过 Nginx 的时候,Nginx 需要解析请求的 header 并且中间多了一层网络转发。
    ppking
        5
    ppking  
       160 天前
    cpu 上不去,说明瓶颈在 IO 呗
    sagaxu
        6
    sagaxu  
       160 天前
    高并发请求和高并发连接数是不同的概念,nginx 能解决高并发连接数,对单服务器的高并发请求没有任何帮助。
    yzongyue
        7
    yzongyue  
       160 天前
    试试 nginx 后面挂 8 个 http server , 每个 server 只起一个工作线程,这样 cpu 能不能上去
    F7TsdQL45E0jmoiG
        8
    F7TsdQL45E0jmoiG  
       160 天前
    I/O 密集型
    goforwardv2
        9
    goforwardv2  
    OP
       160 天前
    @ppking @morenacl 每个链接只传输 1 字节的负载,内核参数该优化的也都优化,难道 8 核 1000M 网卡的机器的极限就是 4~5 万 QPS 吗
    F7TsdQL45E0jmoiG
        10
    F7TsdQL45E0jmoiG  
       160 天前
    @goforwardv2 类似服务器跑 nginx ,极简 http get ,极限 qps 大概 8-10w qps 。有必要自己搭 http 服务吗?另外,增大内存有助于提高 qps
    goforwardv2
        11
    goforwardv2  
    OP
       160 天前
    @morenacl 不是为了搭建 http 服务器用,纯纯是为了
    1. 验证几个网络库的性能(其实主要的使用场景是 TCP 长连接,但压测 TCP 比较麻烦)
    2. 看下在确定网络库的情况下,调整哪些系统的网络参数,可以让机器承载更多的高并发
    3. 看下固定配置的机器到底能抗住多少量级的高并发
    我那个极简的 HTTP Server ,高并发跑起来,内存占用都不到 1%,然后没有任何的磁盘 IO 操作,网卡性能和带宽也可以。
    ppking
        12
    ppking  
       160 天前
    把工作线程数开多点啊,你都说了平均到单核 30%多的 cpu 使用率,说明大部分时间在等 io 呗。
    ppking
        13
    ppking  
       160 天前
    你 cpu 使用率上不去,是用%u+%s 合在一起只有 30%多嘛? cpu 的大部分时间片在等 IO ,那你就多开点线程呗,交给操作系统去调度,8 核的服务器不意味着就开 8 个工作线程。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3004 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 13:30 · PVG 21:30 · LAX 05:30 · JFK 08:30
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.