HAProxy HTTP 状态码统计

为什么要统计状态码

HTTP 状态码是最容易反映一个网站健康状况的指标。正常的情况下,网站的请求速度因该约等于 200 的 QPS; 在后端网络有问题的时候,可能网络不可达,则 502 会变多;网络阻塞,则 504 会变多;后端全挂掉了,直接 503

用户登录故障,有可能是 401 变多了,也许是授权服务有问题;429 变多了,可能是有异常抓站的行为;400 变多了,甚至可能是客户端 HTTP client 有问题。

响应时间是性能指标,状态码是可用性指标。我们可以通过 ELK 全家桶,搭建一套完整的请求日志分析平台。但是 ELK,尤其是 ElasticSearch 是非常耗计算和存储的。如果我们只是要实时的统计状态码,用不了那么大的块头!使用 HAProxy 的 stick table 就可以轻松做到实时统计状态码,以及几乎为零的性能损失。状态码的统计补丁已经 merged 到上游了,但是没有 backport 到当前的稳定版本。所以我额外在 github 上放了一个稳定版本的 backport。有需要的可以直接使用。

A fast DEMO

请使用上面提供的 backport 版本,安装 HAProxy。一个简单的配置如下:

global
    stats socket /tmp/haproxy.sock mode 666 level admin
    stats timeout 1h

defaults
    timeout server 30s
    timeout client 30s
    timeout connect 5s

listen main
    bind *:8000
    mode http
    stick-table type integer size 1k
    http-response track-sc0 status
    server 01 127.0.0.1:9000

请勿在生产环境使用上述不安全的配置!(我已经警告过你了哦)

使用 haproxy -f haproxy.cfg 运行。然后 rlwrap socat /tmp/haproxy.sock stdio,输入 prompt,就可以进入 HAProxy 的管理端了。HAProxy 提供了很多管理命令,你可以参阅其文档。本文要用的命令只有一条:show table main。测试环境的输出如下:

# table: main, type: integer, size:1024, used:1
0x2256200: key=200 use=0 exp=0

什么都没有!就一个 200,并没有相关的计数。为了添加相应的计数器,请将配置文件倒数第三行改为:

    stick-table type integer size 1k expire 30m store http_req_cnt,http_req_rate(1s)

然后重新运行,并进行请求测试,结果如下:

# table: main, type: integer, size:1024, used:1
0x9c8ae0: key=200 use=0 exp=0 http_req_cnt=176314 http_req_rate(1000)=18570

我用了 wrk 对后端进行简单的压测,结果在上面就能看出来,总共发起了 176314 次请求,当前的请求速度大概是 18570 QPS!哦,忘了和大家说下这个监听 9000 端口的是什么东西了,是个直接 return 200 的 NginX。所以性能如此只好就不足为奇了。

好了,状态码有了,能干啥!

你可以使用 unix socket 定时的获取 HAProxy 的状态码个数,然后存储到 InfluxDB 等地方,就可以很方便的查看异常趋势了。

但是!这只是一小步。我们可以做更多。比如根据后端返回的 429 个数,动态地把抓站用户调度到沙盒或者密罐中,进行相应的限速。对造成大量 404 的非法爬虫进行封禁,等等。展开想象吧!

如果有疑问,欢迎在 github 上留 issue。

谢谢阅读。

References