guard 是一个高性能熔断器+代理
RT。上周末发了 https://www.v2ex.com/t/424778#reply14
然后最近几天一直在迭代。从把锁丢掉,到重写 radix tree 和融合统计模块,到把 net/http
换成 fasthttp
,
在我的笔记本上,QPS 从 7k 左右到了 22k,对比 Nginx,性能从 Nginx 的 0.55 到 1.76 倍。改写的过程非常
累,因为写好的测试需要一遍一遍推翻重写。数据结构也需要仔细设计。hot-path 需要非常注意避免性能问题。
但是改写的过程也学到了很多东西,例如怎么去优化 Go 的性能,期间尝试了 prefork 模式,减少锁,缩小临界区,使用 CAS,调整 GOGC
参数 等等等等。
项目链接:
https://github.com/jiajunhuang/guard
核心模块的设计基本上已经稳定了,接下来要做的事情是:
time.Now
,使用自己维护的粗略时间以减少性能损耗欢迎大家关注和 star,以及提出意见,建议和 PR !
1
LuckCode 2018-01-25 16:35:54 +08:00 via iPhone
不懂 bd,star 学习
|
2
xwhxbg 2018-01-25 16:41:56 +08:00
厉害了,不知道有木有跟 traefik 对比一下性能,另外 string 和 byte 不是应该有相同的 underlying value 吗?这俩之间转换有什么特别大的消耗呀?
|
3
herozem OP @LuckCode star 也是贡献~~鼓励开发者哈哈
@xwhxbg 暂时还没有和 trafik 对比,trafik 说 [自己是 Nginx 的 85%]( https://docs.traefik.io/benchmarks/) 左右,起初我也是以这个为目标的。[]byte 是 mutable 的, string 是 immutable 的,如果底层共享的话,会发大乱子的。 参考: https://syslog.ravelin.com/byte-vs-string-in-go-d645b67ca7ff |
4
xwhxbg 2018-01-25 16:54:51 +08:00
@herozem 学习了,厉害厉害,那已经是 traefik 的两倍了,看了下配置方式很新颖啊,是不是应该以后会有一个界面看 access log 和 register app
|
5
herozem OP @xwhxbg 讲真,重写之后原来的配置方式被删掉了 :joy: 之后的话这些功能应该都可以慢慢加上的。不过当务之急是完善核心功能+继续压榨 Go 的性能。
之前是有一个接口返回 app 和对应的统计数据的,不过如上所说,暂时被删掉了 :joy: 欢迎贡献代码 |
6
ryd994 2018-01-25 17:24:50 +08:00 via Android
希望能看到具体的测试场景和 nginx 配置,否则单凭 req/s 说服力不大
|
8
bramblex 2018-01-25 17:28:10 +08:00 2
讲真 go 这种带着 runtime 的语言是怎么超越 nginx 那种 *****ptr 的优化的。nginx 在很多方面都已经是性能压榨的极限了。
|
9
zhs227 2018-01-25 17:31:55 +08:00
初学者,怀着敬畏点评一下
fasthttp 的头部都是在使用的时候才解析,之前都是一堆的 byte 地址传来传去。如果要逐个解析头部字段,速度就会明显慢下来。 另外,fasthttp 前端目前不支持 http2。后面做一些 web 选型就没有再考虑这个。 不过基于 traefik 的 benchmark 来看,大概 80%相当于 nginx 是靠谱的 |
10
herozem OP |
11
herozem OP @zhs227 是的,原本我计划自己实现 proxy 也是这种思路。因为作为 proxy server,并不需要读 body。另外 net/http 实现里申请了太多的内存,相当的影响性能。 另外 guard 暂时也不会支持 http2。http/1.x 比 2 的工具等
都成熟很多。更专业的 benchmark 我会在把功能做成熟做稳定之后再来,目前还只是一个粗略的跑分 |
12
caola 2018-01-25 17:50:49 +08:00
不支持最新的 QUIC 就一切免谈,
之前用 caddy 的 quic,最高只支持到 quic 38 版本,跟不上时代了 果断放弃,改投 trafficserver 大法,可以支持到 quic 41 版本,爽。。 |
13
zhujinliang 2018-01-25 18:22:47 +08:00
time.Now 这块能详细说一下么
如何取当前时间的,精确度有多少? 我想弄一个能精确到 1ms 或 0.5ms 的,但 linux 时间片好像就需要 10ms |
14
gouchaoer 2018-01-25 18:25:10 +08:00 via Android
你能跑个火焰图和 nginx 火焰图说明一下你哪里更厉害么?
|
15
herozem OP |
16
est 2018-01-25 19:54:01 +08:00 via Android
不太可能超过 nginx 贴配置看看? nginx worker 数量要等于 GOMAXPROC 才公平?
|
17
miketeam 2018-01-25 21:26:11 +08:00 via iPhone
楼主,我搭你的车来了,已给 star
|
18
cholerae 2018-01-26 00:28:11 +08:00 via Android
@zhujinliang 带 runtime 和调度器的语言就要求别太高了,1ms 的精度基本不可能的
|
19
cholerae 2018-01-26 00:32:07 +08:00 via Android
@herozem 那位朋友想要高精度时钟,这个 coarseTime 精度应该比 time.Now 还低啊
|
20
herozem OP @cholerae 应该还是可以的,有写一个 benchmark,发现 time.Now 损耗大概在 40ns 左右,用 coarse 实现应该是可以控制到这位朋友要的精度的。毕竟 CPU 非常的快
|
21
sagaxu 2018-01-26 01:56:55 +08:00
|
22
assad 2018-01-26 07:38:45 +08:00 via Android
要是能取代 nginx 就牛逼了
|
23
herozem OP |
24
herozem OP @assad 没准备取代,设计的时候就没想过要取代。理想的方式是躲在 Nginx 之后作为一个中间件。因为 Nginx 非常的成熟非常的专业,第二 fasthttp 没有完全遵循 HTTP RFC,第三 guard 并不准备增加 Nginx 那么多可更改的配置和“脚本支持”。
理想的方式是 Nginx 处理完规则,然后打到 guard,然后后面是应用 |
26
herozem OP @sagaxu :joy: 那可能是命数。。。要替代 Nginx,有太多太多的功能要开发和完善。其实这个项目起初也是为内网的一个需求设计的,不过目前还不够成熟所以还没有上生产。所以设计之初就是躲在 Nginx 后面工作的 (地下工作者
|
27
KgM4gLtF0shViDH3 2018-01-26 10:20:11 +08:00 via Android
跟 caddy 一样吗
|
29
VYSE 2018-01-26 11:40:28 +08:00
@zhujinliang #13 如果只是对 cpu 运转时间做比较操作,利用 time.Now()的 monotonic clock reading 精度是最高, 读的来源实际就是 cpu 开机至今的 cycle 数, 某些打印操作会导致读自然时间,这就依赖系统时间 api 误差(内核其实只是周期性 update 时间戳)
|
30
zhicheng 2018-01-26 15:37:03 +08:00 8
一般用非 C/C++ 写的基础软的生命周期:
1, 写了个 demo 发现性能能接近 nginx,觉得有戏。 2, 经过一番优化,性能已经完全超过 nginx,觉得非常有戏。 3, 随着功能的完善,性能逐渐下降,完全无法匹敌 nginx。 4, 继续经过一翻优化,性能勉强达到 nginx 水平,但代码已经不像高级语言,后悔没有直接用 C。 5, 用 C 重写了一个 lib,给上层语言调用,性能很好,但 Bug 很多,很容易 Crash。 6, 发现有人写了个 nginx 插件,很好用,项目被抛弃。 |
31
feverzsj 2018-01-26 15:39:36 +08:00
这是再测 fasthttp 吧
|
32
herozem OP |
33
zhicheng 2018-01-26 16:17:21 +08:00
@herozem
并不是说要取代 nginx,而是不要把重点放在性能优化上,把重点放到需求上,性能只是一个功能。如果 “非性能” 部分的需求巨大,到时候哪怕再用 C 写一个,也不是问题。 |
34
m939594960 2018-01-26 16:25:58 +08:00
benchmark nginx 的配置没关 log 啊
|
35
0ZXYDDu796nVCFxq 2018-01-26 19:32:30 +08:00 1
我优化一下 nginx 对比一下
nginx 单进程,CPU 是虚拟机的 i5-4590 CPU @ 3.30GHz 测试结果: 1. 请求 nginx 默认首页 wrk --latency -c 2048 -d 30 -t 2 http://127.0.0.1:32645/index.html Running 30s test @ http://127.0.0.1:32645/index.html 2 threads and 2048 connections Thread Stats Avg Stdev Max +/- Stdev Latency 16.54ms 91.31ms 1.97s 96.19% Req/Sec 35.86k 14.09k 81.79k 66.50% Latency Distribution 50% 1.55ms 75% 2.86ms 90% 4.47ms 99% 406.41ms 2140722 requests in 30.08s, 1.69GB read Socket errors: connect 1029, read 98, write 0, timeout 564 Requests/sec: 71172.27 Transfer/sec: 57.69MB 2. 请求 nginx 直接 return 的 hello world wrk --latency -c 1000 -d 30 -t 2 http://127.0.0.1:32645/hello Running 30s test @ http://127.0.0.1:32645/hello 2 threads and 1000 connections Thread Stats Avg Stdev Max +/- Stdev Latency 43.54ms 182.36ms 1.83s 94.93% Req/Sec 83.45k 12.45k 128.69k 74.58% Latency Distribution 50% 0.99ms 75% 1.75ms 90% 50.98ms 99% 1.12s 4975705 requests in 30.04s, 749.51MB read Socket errors: connect 0, read 21, write 0, timeout 352 Requests/sec: 165662.55 Transfer/sec: 24.95MB 测试配置和脚本见 github: https://gist.github.com/travislee8964/76e57bf013923eb9efe9f5cc6c5f9ce9 |
36
0ZXYDDu796nVCFxq 2018-01-26 19:35:57 +08:00
网络和内核没经过优化,所以有一些 socket errors
优化后性能应该还能有提升 |
37
0915240 2018-01-26 19:40:08 +08:00
强烈关注。。
|
38
herozem OP @zhicheng 嗯,这也是一种观点。过早优化是万恶之源没错,但是性能也是一个重要的功能。软件开发的过程并非要剑走偏锋,例如追着性能不放,而是在权衡之下取一个比较好的点。目前这边也没有完全追逐性能
|
40
wzy44944 2018-01-26 23:05:03 +08:00
压完看下火焰图更准确些,不然很容易被一些无所谓的配置掩盖掉,比如 nginx 的 accept 锁要去掉,reuseport 打开,而且随机请求压才有意义,只压一个请求会有内存缓存,这点和配置也有关系。既然不是替代 nginx 的,就不要和 nginx 对比了吧,和做同一个业务的软件对比才好
|
41
sammo 2018-01-28 11:22:55 +08:00 via Android
终于在 v 站上看到一个有性能追求的软件了
|
42
xxdd 2018-01-28 21:37:04 +08:00
已 star
从不吝啬 star QAQ |
43
Thiece 2018-01-29 15:53:31 +08:00
|
44
xman99 2018-01-31 14:30:13 +08:00
Mark, 膜拜中
|