shaoyie
V2EX  ›  程序员

c++多线程实现反向代理 QPS 达到 Haproxy/Nginx 的 3 倍

By shaoyie at 2023 年 9 月 12 日 · 10054 次点击

NiubiX.

项目地址

实验性项目,NiubiX 只提供反向代理功能,大家轻拍有不好的地方可以留言或提 issue/pr. 觉得好就点个 star ,我会持续完善它

与 Nginx/Haproxy 对比测试

Linux 5.19.0-1030-gcp #32~22.04.1-Ubuntu
Instacne 1 GCP cloud VM, 2 cores, 4GB RAM 10.146.0.2 (nginx,haproxy, niubix run at here)
Instacne 2 GCP cloud VM, 2 cores, 4GB RAM 10.146.0.3 (backend, wrk run at here)

nginx version config

nginx version: nginx/1.18.0 (Ubuntu)

server {
    listen       8082 reuseport;
    server_name  localhost;

    access_log  off;
    error_log off;

    location / {
        proxy_pass http://10.146.0.3:8080;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

root         516       1  0 Aug24 ?        00:00:00 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
www-data  417322     516  0 12:13 ?        00:00:06 nginx: worker process
www-data  417323     516  0 12:13 ?        00:00:08 nginx: worker process

haproxy version config

HAProxy version 2.4.22-0ubuntu0.22.04.2 2023/08/14

listen niubix
    bind 0.0.0.0:8083
    mode http
    option forwardfor
    server s1 10.146.0.3:8080

ps -eLf | grep haproxy
root      449421       1  449421  0    1 15:11 ?        00:00:00 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -S /run/haproxy-master.sock
haproxy   449423  449421  449423  0    2 15:11 ?        00:00:05 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -S /run/haproxy-master.sock
haproxy   449423  449421  449429  0    2 15:11 ?        00:00:05 /usr/sbin/haproxy -Ws -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -S /run/haproxy-master.sock

单独测试后端程序处理能力, 确保不存在吞吐量瓶颈

run at 10.146.0.2

wrk -t 2 -c 100 -d 10s  http://10.146.0.3:8080/xxx
Running 10s test @ http://10.146.0.3:8080/xxx
  2 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   520.95us  203.98us   4.09ms   68.03%
    Req/Sec    59.25k     2.68k   63.62k    52.50%
  1179133 requests in 10.00s, 173.17MB read
Requests/sec: 117888.45
Transfer/sec:     17.31MB

为了数据真实性,我只取了 1 次测试结果,连续对 3 个服务测试截图

对于 nginx 的数据声明一下:只有偶尔能跑到 1.7w 的 qps ,如果 proxy_pass http://10.146.0.3:8080; 换到 127.0.0.1:8080 ,qps 能到 9000 qps ,至于局域网内为什么这么低通过 strace 也没看到异常,而且 cpu 也通跑满,不知道它在干嘛

tcpdump tcp port 8080 抓包查看 niubix 实际数据,包含 X-Real-IP, XFF ,并且响应在微秒级

目前具备功能:

  • master/worker 模式,worker 采用多线程,支持配置优雅的 Reload(像 nginx 一样),master 还是守护进程,当 worker 进程异常会马上 fork 一个新的
  • 只支持 Linux (将来也不准备跨平台)
  • 主体逻辑无锁,简单高效,可靠
  • 优雅的 acceptor/connector ,高效实现异步监听+连接

测试声明

  • niubix 仅提供反向代理功能
  • niubix 支持 X-Real-IP, X-Forwarded-For, 其他 Header 并没有解析
  • http parser 只是简单的解析, 并没有完全实现
  • 只是初步测试, 并没有做冒烟测试和稳定性测试以及多条件下复杂测试
  • niubix 均衡策略使用的是 roundrobin(别的也还没实现呢), nginx/haproxy 也是一样的策略
  • backend 测试程序 code
  • niubix 不解析 response 内容
  • 功能逐步完善中, 基本框架是过硬的, 我相信这是一个好的开始

接下来开发计划

  • Better HTTP parser
  • TCP protocol + Proxy Protocol
  • Https
第 1 条附言  ·  2023 年 9 月 13 日

nginx的问题搞定了,wrk 加上 -H 'Connection: keep-alive'了,wrk默认不带,nginx按照 Connection: close处理了。

重新更正一下连续测试结果

wrk -t 2 -c 100 -d 10s -H 'Connection: keep-alive' http://10.146.0.2:8081/xxx
Running 10s test @ http://10.146.0.2:8081/xxx
  2 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.22ms  800.49us  19.71ms   94.57%
    Req/Sec    26.67k     1.92k   29.53k    76.00%
  530996 requests in 10.01s, 77.99MB read
Requests/sec:  53032.21
Transfer/sec:      7.79MB
(base) root@instance-1:~# wrk -t 2 -c 100 -d 10s -H 'Connection: keep-alive' http://10.146.0.2:8082/xxx
Running 10s test @ http://10.146.0.2:8082/xxx
  2 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    10.16ms   13.47ms  93.49ms   85.88%
    Req/Sec     8.64k     7.59k   23.31k    68.50%
  172028 requests in 10.01s, 26.41MB read
Requests/sec:  17188.44
Transfer/sec:      2.64MB
(base) root@instance-1:~# wrk -t 2 -c 100 -d 10s -H 'Connection: keep-alive' http://10.146.0.2:8083/xxx
Running 10s test @ http://10.146.0.2:8083/xxx
  2 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     6.49ms    8.64ms 141.16ms   97.99%
    Req/Sec     8.89k     1.25k   13.48k    85.86%
  176005 requests in 10.00s, 21.82MB read
Requests/sec:  17598.35
Transfer/sec:      2.18MB
第 2 条附言  ·  2023 年 9 月 13 日
总结一下啊,很开心有这么多人关注,大家怼的也很开心,正所谓淫者见淫,智者见智。

我写这个东西的肝了好几晚,初衷就是想看一下 nginx 功能拆分后(包括扔掉历史包袱)对性能的提升能有多少,我有信心在网络架构上不会输给 nginx ,细节和专业度就不好意思提了,肯定赶不上

庆幸,昨晚程序能跑起来后我就第一时间做了对比测试,数据很惊讶,后来我又拉 haproxy 一起测了下,确认了结论

我没贬低 nginx haproxy ,也没吹牛逼,只是尽量尽量把数据搞得经得起推敲(开始 nginx 的问题确实没搞定),我定位的只是方向代理功能,在我的测试条件下 nginx 大部分功能都是不会触发的,只是在解析协议上有些差距(当然这只是我的浅薄之见),包括只做代理的 haproxy

我在实现过程也做了一些优化,比如 epoll ptr 的使用,在链接成功后就尝试匹配后端,多线程下互斥的避免,这些其实在我的测试中都遇到过问题,包括 coredump ,不过都解决了

每一种结果都能给我们提供一种可行性,都有它存在的价值

大家多一些思考,不要盲目判断
第 3 条附言  ·  2023 年 9 月 20 日
2023-09-20 更新
1. 基于状态机的 http parser ,解析效率超过 nginx 模式 1 倍
2. 灵敏的健康检查机制
3. 增加 POST/DELETE/PUT/HEAD 的支持(主要是 Content-Length 的支持)
4. Frontend Active Check
5. 增加 Admin api web server (简易版),可以通过 http 请求动态更新配置(部分配置)
6. 通过 Host 匹配 app (还不支持模糊匹配)
以上,性能未减

计划
1. Transfer-Encoding: chunked
2. 支持 https (有经验的兄弟可以联系我,这块我没碰过)
3. ip hash 均衡策略
4. 支持 Proxy protocol
完成以上就可以发 v0.1 了
125 条回复  •  2023-09-21 13:49:45 +08:00
第 1 页
共 2 页
12
slowman
   1
slowman  
   2023 年 9 月 12 日   ❤️ 9
Nginx 1K tps?
我是秦始皇,信我
xiaooloong
   2
xiaooloong  
   2023 年 9 月 12 日   ❤️ 1
nginx 上 upstream ,开 http 1.1 和 keepalive 试下
lovelylain
   3
lovelylain  
   2023 年 9 月 12 日 via Android
nginx 进程数?
sadfQED2
   4
sadfQED2  
   2023 年 9 月 12 日   ❤️ 4
我宁愿信#1 是秦始皇,我都不信你这玩意能吊打 ha 和 nginx
nmap
   5
nmap  
   2023 年 9 月 12 日   ❤️ 1
测出这种荒唐的结果,首先应该是怀疑自己的问题,而不是感觉发现了新大陆
ugpu
   6
ugpu  
   2023 年 9 月 12 日   ❤️ 1
不知道为什么要写这么个标题.
如果不是为了喧哗惑众 那么请看看 nginx 的配置. 以及测试姿势是否正确.
shaoyie
   7
shaoyie  
OP
   2023 年 9 月 12 日
@ugpu 标题有什么问题?测试结果确实是这样,nginx 我也不知道为什么在我这边特别不稳定,只是偶尔能跑出过万的 qps ,但是 haproxy 比较稳定,haproxy 在性能上略高 nginx 这是事实,我测出来的比 haproxy 高出很多,我不可以这样写吗?
shaoyie
   8
shaoyie  
OP
   2023 年 9 月 12 日
@nmap 是不是新大陆,那也是我一行一行码出来的代码跑出来的。
shaoyie
   9
shaoyie  
OP
   2023 年 9 月 12 日
@sadfQED2 认真看,我说的是仅限反向代理功能
shaoyie
   10
shaoyie  
OP
   2023 年 9 月 12 日
@lovelylain 上边不是展示 nginx 的进程数了吗,也是 2 个,开了 reuseport
shaoyie
   11
shaoyie  
OP
   2023 年 9 月 12 日
@xiaooloong wrk 就是长链接的,如果用 ab 短链接测试,数据更差
shaoyie
   12
shaoyie  
OP
   2023 年 9 月 12 日
@ugpu 配置我贴出来了,你觉得哪里有问题可以指出来我再去测
shaoyie
   13
shaoyie  
OP
   2023 年 9 月 12 日   ❤️ 4
刚注册不久,不知道 V2EX 上边戾气这么重,我开头就说了,是实验性项目,我一没收你们钱,二没吃你们家大米,遇到新鲜事物,上来就是批评,不应该是先确定是不是,再问为什么,最后研究怎么做到的
deorth
   14
deorth  
   2023 年 9 月 12 日 via Android
因为没空
u20237
   15
u20237  
   2023 年 9 月 12 日
nginx 有那么弱吗?
shaoyie
   16
shaoyie  
OP
   2023 年 9 月 12 日
@u20237 确实没搞懂在 gcp 上为啥这么不稳定
shaoyie
   17
shaoyie  
OP
   2023 年 9 月 12 日
@deorth 烂鸟蛋
kkk9
   18
kkk9  
   2023 年 9 月 12 日
首先 nginx 肯定没那么弱,其次 ha 也不是这样测的,最后其实我啥也不懂
dasf53adf
   19
dasf53adf  
   2023 年 9 月 12 日
不明觉历,希望有大佬出来做个二次测试验证一下。
ugpu
   20
ugpu  
   2023 年 9 月 12 日
@shaoyie 不会 我啥也不懂.
shaoyie
   21
shaoyie  
OP
   2023 年 9 月 12 日
@kkk9 请教,haproxy 怎么测?
ShuWei
   22
ShuWei  
   2023 年 9 月 12 日
用了什么黑科技吗? nginx/haproxy 什么时候这么弱鸡了
stinkytofu
   23
stinkytofu  
   2023 年 9 月 12 日
看标题, 民科既视感
shaoyie
   24
shaoyie  
OP
   2023 年 9 月 12 日
@ShuWei 算不上黑科技吧,这不像比武,没有明显的绝招,反正一行一行写完,测试结果就是会好一些,nginx 可能历史包袱比较重吧,如果单纯实现某一个功能就会轻巧一些,但是这个相差距我也是挺意外的。即使我没有完整解析 http 协议,但是性能差距也不应该这么大,我只是没有过滤某些 header 而已,也是完全循环到 header 结尾了。
我没有仔细研究 haproxy nginx 全部代码,但是总体架构都差不多,系统 api 就那些
ugpu
   25
ugpu  
   2023 年 9 月 12 日
@shaoyie 首先你可以试试 真实物理机 + 真实路由效果. 然后做一些转发逻辑 . 其次 nginx 本真支持很多插件挂载, 支持多平台. 极度稳定.
最后 点个赞 觉得你动手能力很强. 起码你敢去做.
shaoyie
   26
shaoyie  
OP
   2023 年 9 月 12 日
slowman
   27
slowman  
   2023 年 9 月 12 日   ❤️ 2
一上来就吊打 nginx 的,不是装傻就是真蠢
nginx 都多少年了,当网友都没测过 nginx 是吧
shaoyie
   28
shaoyie  
OP
   2023 年 9 月 12 日
@ugpu 1. 无奈测试环境有限,等成熟一些再花大精力对细致化测试,目前至少已经证明 nignx,haproxy 是有提升空间的,2. 不追求功能大而全,只专注一个功能。重剑无锋,大巧不工!
shaoyie
   29
shaoyie  
OP
   2023 年 9 月 12 日
@1423 读都读不明白,你还能干啥?我说了,仅限反向代理功能!烂番茄,臭鸟蛋一类,就喜欢嘴炮,
lsk569937453
   30
lsk569937453  
   2023 年 9 月 12 日 via Android
https://v2ex.com/t/929786#reply26 自己用 rust 开发的反向代理,也有和 nginx,envoy 的性能对比
devopsdogdog
   31
devopsdogdog  
   2023 年 9 月 12 日 via Android
nginx haproxy 全部配置贴一下,你是不是用默认参数对比的? 建议先调优。
ccsexyz
   32
ccsexyz  
   2023 年 9 月 12 日
你这测试结果太离谱了,没有采信的价值。
我盲猜是 nginx 回源没开长链接,不如直接读下本地文件对比下。
shaoyie
   33
shaoyie  
OP
   2023 年 9 月 12 日
@devopsdogdog 确实,除了我贴出来的,其他的都是默认的,
deorth
   34
deorth  
   2023 年 9 月 12 日 via Android
@Livid 人身攻击
shaoyie
   35
shaoyie  
OP
   2023 年 9 月 12 日
@ccsexyz 那 haproxy 的测试数据也算一个参考,读文件那是 webserver 的活,我实现的只是反向代理的功能
slowman
   36
slowman  
   2023 年 9 月 12 日
@Livid @shaoyie 在 29 楼搞人身攻击
slowman
   37
slowman  
   2023 年 9 月 12 日


随便跑了下 nginx 就 8w 多, 这类 C 程序基本性能都到头了,新的方向都是更安全(rust),更快速开发(go)
年轻人别浪费时间在这上面了,经济价值极低
lhbc
   38
lhbc  
   2023 年 9 月 12 日
啊,我手上 100K+ QPS 的 nginx 是哪里来的?
ccsexyz
   39
ccsexyz  
   2023 年 9 月 12 日
@shaoyie 我觉得你还是多研究下被测的软件吧,随便测一下就下结论很容易误导人。
zebedy
   40
zebedy  
   2023 年 9 月 12 日   ❤️ 2
op 原话:“nginx 我也不知道为什么在我这边特别不稳定,只是偶尔能跑出过万的 qps”
所以你不去研究一下为什么你的 nginx 才能跑到 2k 的 qps ,而是去吹牛逼:我的代码实现了超过 Nginx 三倍的性能。这个脑回路也是很不一般

你说巧不巧,我也有个 2c 的小鸡上面跑着本地的反代,随手跑一下

wrk -t2 -c100 -d10s xxxxxxxx
Running 10s test @ xxxxxxxx
2 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 6.71ms 3.04ms 45.66ms 82.73%
Req/Sec 7.62k 1.81k 12.55k 65.50%
151984 requests in 10.05s, 55.95MB read
Requests/sec: 15118.79
Transfer/sec: 5.57MB
shaoyie
   42
shaoyie  
OP
   2023 年 9 月 12 日
@lhbc 要看服务器配置啊,我的是 2c 4g gcp 主机
shaoyie
   43
shaoyie  
OP
   2023 年 9 月 12 日
@zebedy 我确实研究了,没研究出来,后来我布署了 haproxy ,测了一下,haproxy 没问题,比较稳定,能跑到 1.8w
shaoyie
   44
shaoyie  
OP
   2023 年 9 月 12 日
@zebedy haproxy 的也具有参考价值
shaoyie
   45
shaoyie  
OP
   2023 年 9 月 12 日
@Inn0Vat10n 感谢,不过在初始化过程的代码都没有做内存释放,因为 return -1 了 就直接 exit 了
Betsy
   46
Betsy  
   2023 年 9 月 12 日 via iPhone
op 最大的败笔在于没有深入研究 nginx 的性能就贸然碰瓷如此有名气的组件(搜搜网上已经公开的测试结果也好),这就跟写论文没把别人的论文复现(甚至都没有仔细做这个实验)就说没人不行一样的道理。体感上来说无异于闭门造车显得不专业。不过换个标题(比如去掉 nginx 的比较)大概就是个不错的分享了。
shaoyie
   47
shaoyie  
OP
   2023 年 9 月 12 日
@Betsy 感谢认真回复。你们为什么总扒着 nignx 不放,haproxy 呢,它的功能更相似一些。
Betsy
   48
Betsy  
   2023 年 9 月 12 日 via iPhone
@shaoyie 你写的每个字大家都会看,而对 nginx 熟悉的人居多,所以你懂的。更何况你也没对 haproxy 标重点呀,故大家抓着 nginx 不放也没毛病。
toomlo
   49
toomlo  
   2023 年 9 月 12 日
@shaoyie #13 很多人评论的内容完全是为了宣泄情绪或者在别的什么地方看到个名言就瞎乱用也不知道这样的评论有啥意义。
shaoyie
   50
shaoyie  
OP
   2023 年 9 月 13 日
@toomlo en, 国内这个社区氛围不好
wangbin526
   51
wangbin526  
   2023 年 9 月 13 日 via Android
@shaoyie Nginx 以性能著称,特别是做前端反代几乎是建站标配,此类互联网基础组件 c 代码早被优化到接近极限,同等条件下性能提升个 3%都算巨大进步,结果你宣称用性能更差的 c++,在 Nginx 最主要的反代功能上跑出来 3 倍性能,确实很离谱,至于 haproxy 是什么鬼?至少偶没用过,你吹超过 10 倍偶也没感觉
这就像如今百米短跑成绩已经濒临人体极限,每提升 0.1 秒都极其艰难,结果你直接宣称短跑速度翻三倍直接直接从 9 秒多提升到 3 秒,外星科技都没这么离谱
shaoyie
   52
shaoyie  
OP
   2023 年 9 月 13 日
@wangbin526 你顺便去把 mojo 也喷一下吧,他吹的牛可不小
shakeyo
   53
shakeyo  
   2023 年 9 月 13 日   ❤️ 1
你想获得认可的话,还不如把这怼人的功夫如何实现这么高性能的讲清楚,然后 nginx 为什么表现那么差去分析分析对比
而不是先起个耸人听闻的标题,然后别人有质疑就一副就我牛逼的姿态
shaoyie
   54
shaoyie  
OP
   2023 年 9 月 13 日
@shakeyo 你哪只眼睛看到我怼人了,哪句话看到我显摆牛逼了
shaoyie
   55
shaoyie  
OP
   2023 年 9 月 13 日
我贴一下 nginx 的全部配置,刚刚升级了 1.24 ,吞吐量还是上不去

```
user nginx;
worker_processes auto;

error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;


events {
worker_connections 1024;
}


http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

sendfile on;
#tcp_nopush on;

keepalive_timeout 65;

#gzip on;

include /etc/nginx/conf.d/*.conf;
}
```
```
cat /etc/nginx/conf.d/test.conf
server {
listen 8082 reuseport;
server_name localhost;

access_log off;
error_log off;

location / {
#proxy_pass http://127.0.0.1:8080;
proxy_pass http://10.146.0.3:8080;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

```

```
reuseport 也生效了
netstat -anp --inet | grep 8082
tcp 0 0 0.0.0.0:8082 0.0.0.0:* LISTEN 468035/nginx: maste
tcp 0 0 0.0.0.0:8082 0.0.0.0:* LISTEN 468035/nginx: maste

```
Dukec
   56
Dukec  
   2023 年 9 月 13 日
要在别人最佳状态的时候超越他才有成就感。
xiaooloong
   57
xiaooloong  
   2023 年 9 月 13 日
@shaoyie 不是 wrk 到 nginx ,是 nginx 到 upstream
xiaooloong
   58
xiaooloong  
   2023 年 9 月 13 日
```nginx
upstream http_backend {
server 127.0.0.1:8080;

keepalive 16;
}

server {
...

location /http/ {
proxy_pass http://http_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
...
}
}
```
picone
   59
picone  
   2023 年 9 月 13 日
@shaoyie #11 说的是 nginx 到 upstream ,不是 client 到 nginx
mengjue
   60
mengjue  
   2023 年 9 月 13 日
遥遥领先!
learningman
   61
learningman  
   2023 年 9 月 13 日
反代没开 proxy_http_version 1.1 ,keep alive 没打开
proxy_set_header Connection "";
proxy_http_version 1.1;

upstream 里可以单独配,你也没设
zengzizhao
   62
zengzizhao  
   2023 年 9 月 13 日
@shaoyie #52 你这是怼了人不自知啊......
kkk9
   63
kkk9  
   2023 年 9 月 13 日
@shaoyie #21 我也不会测,但是我知道美团把 haproxy 作为数据库集群的负载均衡支撑,每天的流量应该比你测试高。实战也比我们整个小机器测试的真实。

还是建议换个 8c16g 的真实主机测试,应该会有新的发现,同时,随便拿一台 GCP 测试的数据挨喷很正常,不要太玻璃心。
ShuA1
   64
ShuA1  
   2023 年 9 月 13 日
upstream
shaoyie
   65
shaoyie  
OP
   2023 年 9 月 13 日
@xiaooloong 感谢,
我试了一下,还是不行,qps 还是 2000+
```
upstream backend {
server 10.146.0.3:8080;
keepalive 16;
}
server {
listen 8082 reuseport;
server_name localhost;

access_log off;
error_log off;

location / {
#proxy_pass http://127.0.0.1:8080;
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
```
shaoyie
   66
shaoyie  
OP
   2023 年 9 月 13 日
@learningman 开了啊,我只有一个 backend ,用 proxy_pass 就可以了,不用 upstream 也没事,这不影响性能
shaoyie
   67
shaoyie  
OP
   2023 年 9 月 13 日
感谢提出意见的各位,不用怼了,haproxy 的数据已经可以做为参考了,至少证明了我的猜想是可行的,我会持续去完善 niubix ,争取能给 LBS 带来一个新的选项。
encro
   68
encro  
   2023 年 9 月 13 日
@shaoyie

“国内这个社区氛围不好”



少一些标题党估计能更好?!
shaoyie
   69
shaoyie  
OP
   2023 年 9 月 13 日
@encro 测试数据就是个结果啊,我也声明了,程序还不完善,但要懂其底层原理的人应该明白,补上缺少的那些功能并不会带来 2 倍的性能差异,数据只是参考,不是定性,每个人通过数据分析到的结果是不一样的。
yunyuyuan
   70
yunyuyuan  
   2023 年 9 月 13 日   ❤️ 3
你自己看看的回复,就你戾气最重,谁 tm 惯着你了?还骂起人来
我替他们骂你:臭煞笔,已 b
hankai17
   71
hankai17  
   2023 年 9 月 13 日
nginx 开启 upstream 的 keepalive 后 如果 qps 上不去 看一下是不是 upstream 端的压测工具是不是有问题

测代理别用 wrk 测 可以试试 ats 的 jtest 同时充当客户端与服务端
hankai17
   72
hankai17  
   2023 年 9 月 13 日
@shaoyie
worker_connections 1024; 改大点
还有文件描述符限制 也改大点
shaoyie
   73
shaoyie  
OP
   2023 年 9 月 13 日
@hankai17 嗯 感谢,我研究研究 backend
shaoyie
   74
shaoyie  
OP
   2023 年 9 月 13 日
@hankai17 这个 fd 数量不影响,默认 ulimit -n 就是 1024 ,实际并发链接数 wrk 也才 100 ,
hikarugo
   75
hikarugo  
   2023 年 9 月 13 日   ❤️ 3
在相对专业的论坛发一个 uc 类标题(难听点就是一眼假),被嘲讽就反嘲讽回去,然后怪论坛人戾气重,一眼假的结论还不允许别人批评,如果你不是显摆也不是来寻求建议,那你发帖的标题出发点是?你完全标题可以加上“是我测试方法不对吗”。这种圈内常识性的结论性标题被喷难道不应该吗?多少人厌恶这种标题党。

楼上的 v 友说得很好“测出这种荒唐的结果,首先应该是怀疑自己的问题,而不是感觉发现了新大陆”
看你的回复骂人的话是真的难听,你的戾气应该是他们的 3 倍吧
chaorenguilai198
   76
chaorenguilai198  
   2023 年 9 月 13 日
我擦,我竟然看完了所有回复。确实喷的精彩。
ragnaroks
   77
ragnaroks  
   2023 年 9 月 13 日
1 virtual thread E5-2689 + 512 MiB RAM

root@cn1427:~# wrk -t2 -c100 -d10s http://localhost
Running 10s test @ http://localhost
2 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 2.61ms 2.49ms 13.74ms 80.17%
Req/Sec 18.19k 3.59k 21.09k 81.00%
362030 requests in 10.01s, 39.22GB read
Requests/sec: 36181.29
Transfer/sec: 3.92GB

root@cn1427:~# podman exec openresty nginx -V
nginx version: openresty/1.21.4.2
built with OpenSSL 1.1.1s 1 Nov 2022
TLS SNI support enabled
configure arguments: --prefix=/usr/local/openresty/nginx --with-cc-opt='-O2 -DNGX_LUA_ABORT_AT_PANIC -I/usr/local/openresty/zlib/include -I/usr/local/openresty/pcre/include -I/usr/local/openresty/openssl111/include' --add-module=../ngx_devel_kit-0.3.2 --add-module=../echo-nginx-module-0.63 --add-module=../xss-nginx-module-0.06 --add-module=../ngx_coolkit-0.2 --add-module=../set-misc-nginx-module-0.33 --add-module=../form-input-nginx-module-0.12 --add-module=../encrypted-session-nginx-module-0.09 --add-module=../srcache-nginx-module-0.33 --add-module=../ngx_lua-0.10.25 --add-module=../ngx_lua_upstream-0.07 --add-module=../headers-more-nginx-module-0.34 --add-module=../array-var-nginx-module-0.06 --add-module=../memc-nginx-module-0.19 --add-module=../redis2-nginx-module-0.15 --add-module=../redis-nginx-module-0.3.9 --add-module=../ngx_stream_lua-0.0.13 --with-ld-opt='-Wl,-rpath,/usr/local/openresty/luajit/lib -L/usr/local/openresty/zlib/lib -L/usr/local/openresty/pcre/lib -L/usr/local/openresty/openssl111/lib -Wl,-rpath,/usr/local/openresty/zlib/lib:/usr/local/openresty/pcre/lib:/usr/local/openresty/openssl111/lib' --with-pcre-jit --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-http_v2_module --without-mail_pop3_module --without-mail_imap_module --without-mail_smtp_module --with-http_stub_status_module --with-http_realip_module --with-http_addition_module --with-http_auth_request_module --with-http_secure_link_module --with-http_random_index_module --with-http_gzip_static_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-threads --with-stream --with-http_ssl_module
ragnaroks
   78
ragnaroks  
   2023 年 9 月 13 日
root@cn1427:~# cat /var/lib/containers/storage/volumes/openresty-config/_data/nginx.conf
# nginx.conf -- docker-openresty
#
# This file is installed to:
# `/usr/local/openresty/nginx/conf/nginx.conf`
# and is the file loaded by nginx at startup,
# unless the user specifies otherwise.
#
# It tracks the upstream OpenResty's `nginx.conf`, but removes the `server`
# section and adds this directive:
# `include /etc/nginx/conf.d/*.conf;`
#
# The `docker-openresty` file `nginx.vh.default.conf` is copied to
# `/etc/nginx/conf.d/default.conf`. It contains the `server section
# of the upstream `nginx.conf`.
#
# See https://github.com/openresty/docker-openresty/blob/master/README.md#nginx-config-files
#

user root;
worker_processes 2;
worker_rlimit_nofile 65535;
pcre_jit on;
error_log /logs/error.log;

events {
use epoll;
worker_connections 16384;
accept_mutex off;
multi_accept on;
}

http {
include mime.types;
default_type application/octet-stream;
log_format main '$time_local # $remote_addr => $http_x_real_ip[$http_x_forwarded_for] | $status | $http_referer | $http_user_agent | $request';
access_log /logs/access.log main;
client_body_temp_path /var/run/openresty/nginx-client-body;
proxy_temp_path /var/run/openresty/nginx-proxy;
fastcgi_temp_path /var/run/openresty/nginx-fastcgi;
uwsgi_temp_path /var/run/openresty/nginx-uwsgi;
scgi_temp_path /var/run/openresty/nginx-scgi;
sendfile on;
keepalive_timeout 65;
server_tokens off;
more_clear_headers Server;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 256k;
resolver 223.5.5.5;
include /etc/nginx/conf.d/*.conf;
}
shaoyie
   79
shaoyie  
OP
   2023 年 9 月 13 日
@fyxtc 感谢回复,就是要打破所谓的“圈内常识”,我从来都没说我吹 NB ,我只是写了一个 3 倍(也是有数据支撑的,而且我也声明了,我实现的功能不完全)数据只供参考,我相信等功能完善了也不会降低 2 倍的性能差。至于 nginx 的问题,完全可以忽略,参考 haproxy 的就够了。nginx 的配置我确实没搞定,也研究过,也试了上边热心网友提供的配置,都不行。
shaoyie
   80
shaoyie  
OP
   2023 年 9 月 13 日
铁子们,搞定了 @xiaooloong @learningman @picone

wrk -t 2 -c 100 -d 10s -H 'Connection: keep-alive' http://10.146.0.2:8082/xxx
Running 10s test @ http://10.146.0.2:8082/xxx
2 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 3.99ms 1.16ms 28.64ms 81.99%
Req/Sec 12.61k 526.49 13.93k 78.50%
250914 requests in 10.00s, 38.52MB read
Requests/sec: 25083.91
Transfer/sec: 3.85MB


wrk 是不带 connection header 的,nginx 默认就按 close 处理了。
shaoyie
   81
shaoyie  
OP
   2023 年 9 月 13 日
抱歉,搞错了, #80 是在 nignx 主机上测试的
在 wrk 的主机上测试,数据没那么好,
wrk -t 2 -c 100 -d 20s http://10.146.0.2:8082/xxx
Running 20s test @ http://10.146.0.2:8082/xxx
2 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 12.87ms 18.90ms 172.84ms 88.01%
Req/Sec 7.64k 6.23k 25.84k 74.00%
304115 requests in 20.01s, 46.69MB read
Requests/sec: 15195.51
Transfer/sec: 2.33MB
shaoyie
   82
shaoyie  
OP
   2023 年 9 月 13 日
#81 又鸡巴贴错了,抱歉
```
wrk -t 2 -c 100 -d 10s -H 'Connection: keep-alive' http://10.146.0.2:8082/xxx
Running 10s test @ http://10.146.0.2:8082/xxx
2 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 8.30ms 12.55ms 116.67ms 86.81%
Req/Sec 12.44k 8.43k 23.21k 55.50%
247471 requests in 10.00s, 38.00MB read
Requests/sec: 24736.85
Transfer/sec: 3.80MB
```
lesismal
   83
lesismal  
   2023 年 9 月 13 日   ❤️ 6
简单扫了几眼代码,没全看,大概明白为啥 niubix 性能这么高了,只扫了几分钟、不保证我说的是准确的,如果有误,OP 和各位多多指正。

1. 对 client 端请求的处理
https://github.com/shaovie/niubix/blob/main/src/http_conn.cpp#L168
这里的 http request 处理,目测似乎并没有做完整的 http 协议解析所以也没有请求合法性校验之类的,也没有 nginx 那些完善的对请求进行中间处理的功能,主要是添加 realip/x-forward-for

2. 对 backend 端的处理
https://github.com/shaovie/niubix/blob/main/src/backend_conn.cpp#L74
看这里是对 backend 读取到的数据直接转发给 client 、没有进行 http 协议的中间处理。但 nginx 是有处理功能的、比如开了 gzip ,backend 没开 gzip ,nginx 是会自己加上 gzip 逻辑的,也包括其他通用功能的处理。
另外啊,如果只是需要盲转发数据,其实用 splice 这种 zero copy 的 syscall 性能更好。

所以综合下来看,相比于 nginx 完善的功能,niubix 目前版本对 client 、backend 的处理都是功能不完善的、还属于 demo 级代码,或许适用于自家特定业务的优化,不适合作为通用功能的反代。

这种 demo 级的测试,跟商业级稳定大项目来对比性能本身就是不合理的,就像我之前给 OP 说的那样:拿不完整功能的 http server 去参加 TechEmpower Plaintext 没意义。
hankai17
   84
hankai17  
   2023 年 9 月 13 日   ❤️ 1
@lesismal + 1
曾经也写过一个类似的 server 也是不解析 http 协议 在实际压测时性能略高于 nginx
shaoyie
   85
shaoyie  
OP
   2023 年 9 月 13 日
@lesismal 又看到你,
1. 虽然解析过滤不完整,但是我也走了完整的循环,只是没有过滤所有 header 而已,但这正常单一功能的优势(仅提供反向代理功能)
2. splice 是限于 pipe 。ZEROCOPY 是异步的增加复杂度了,buf 机制也要改,整体提升非常有限
3. 其他选项,根本不会触发啊,比如 gzip:我发的内容很短"hello world"。
4. 我声明了啊,本来就是个实验性项目,功能不完整

只是证明一种可行性,数据要辩证的分析
shaoyie
   86
shaoyie  
OP
   2023 年 9 月 13 日
@hankai17 我的 backend server 就不解析协议,qps 直接就是 11w ,我上边贴了
starinmars
   87
starinmars  
   2023 年 9 月 13 日
@1423 一楼,我信你。
ruanimal
   88
ruanimal  
   2023 年 9 月 13 日   ❤️ 3
@lesismal 你就说快不快吧[doge]
rrfeng
   89
rrfeng  
   2023 年 9 月 13 日
我用 shell 写了个 proxy ,可以支持 10w qps 。

目前只支持 echo "hello,world"
lesismal
   90
lesismal  
   2023 年 9 月 13 日   ❤️ 1
@shaoyie #85

1/3/4: 既然是这样,就不要用 qps x3 nginx 、haproxy 这种标题了,完全没有可比性,至少标题指明用于特定场景优化会好些。
nginx 的行业地位比自定制的玩具 demo 稳多了,这样标题、大家看了第一感觉就是你在碰瓷 nginx 、吹牛+踩 nginx 弱鸡,就像突然蹦出个民科一顿言论吊打数学家科学家一样。
goev 的帖子也是如此。

> 2. splice 是限于 pipe 。ZEROCOPY 是异步的增加复杂度了,buf 机制也要改,整体提升非常有限

按现在的功能,如果只是转发 backend 给 client ,应该不需要改太多
shaoyie
   91
shaoyie  
OP
   2023 年 9 月 13 日
@rrfeng 来呀,我接受你的挑战,搞不定你就吃粑粑
shaoyie
   92
shaoyie  
OP
   2023 年 9 月 13 日
@lesismal 我标题做了定语啊:反向代理。

而且我项目首页就写了 “Just a reverse proxy service”
nginx 是功能很多,但是做为反向代理,大部分功能不需要,非要比功能多不多干吗?不是还有 haproxy 做对比吗

“应该不需要改太多”,想当然了吧,部分的栈内存要换成堆内存,还要增加一次系统调用查询结果综合提升非常有限。再有,程序还没有到过滤优化的阶段。
tool2d
   93
tool2d  
   2023 年 9 月 13 日
帖子刷了差不多 3200 个点击,也只有 4 个人 star ,足够证明了这项目没前途。

真不是 QPS 的问题。
shaoyie
   94
shaoyie  
OP
   2023 年 9 月 13 日
@tool2d 哈哈,开心就好
e7
   95
e7  
   2023 年 9 月 13 日
grep -Rn EPOLLET src
src/event/ngx_event.h:353:#define NGX_CLEAR_EVENT EPOLLET
src/event/modules/ngx_epoll_module.c:32:#define EPOLLET 0x80000000
src/event/modules/ngx_epoll_module.c:292: ee.events = EPOLLIN|EPOLLET;
src/event/modules/ngx_epoll_module.c:412: ee.events = EPOLLIN|EPOLLET;
src/event/modules/ngx_epoll_module.c:476: ee.events = EPOLLET|EPOLLIN|EPOLLRDHUP;
src/event/modules/ngx_epoll_module.c:705: ee.events = EPOLLIN|EPOLLOUT|EPOLLET|EPOLLRDHUP;

其实 37L 说得挺好
jeesk
   96
jeesk  
   2023 年 9 月 13 日
哈哈,路过看看。 周末有时间我自己测试一下。
shaoyie
   97
shaoyie  
OP
   2023 年 9 月 13 日
@e7
ET 模式不是性能的标配,读的话不管哪种模式都是尽量一次性读完,减少 syscall 次数,而且有了这个前提 大部分情况 ET 模式反而会浪费一次 syscall ,因为必须判断 ret=-1 && errno = EAGAIN ,而在水平模式下,读出来的数量小于你的 buf 长度 就可以了,不需要再尝试一次

个人感觉它适合在 write 方面,减少 epoll_ctl 的调用

欢迎讨论
shaoyie
   98
shaoyie  
OP
   2023 年 9 月 13 日
@jeesk 欢迎哦,有问题随时找我
shaoyie
   99
shaoyie  
OP
   2023 年 9 月 13 日
@e7 咱想复杂了,就讨论反向代理这块,语言和技术发展方向暂避不谈
u20237
   100
u20237  
   2023 年 9 月 13 日
问个不该问的,这个问题的后端 比代理端更厉害
我猜测这个后端能上 100W 并发 这样才会实现代理端和后端各 40W+
如果后端有底层限制跑不到 30W 20W 并发,代理端很难突破限制

直接测试后端的 QPS 值是什么呢?总数据量?状态码?
如果同意,后端的软件名和版本号?

如果是两机测试,有可能带宽跑满,但结果对第三机无意义。第三计算机会有各种因素被限速甚至丢包/屏蔽
第 1 页
共 2 页
12
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
© 2026 V2EX · 121ms · 3.9.8.5