声明
本文由Donny译自 3scale.com 的 《How to load test & tune performance on your API》
本文基于Mark在APIStrat/APIDays 柏林站的演讲,视频可以在YouTube上看,如果你可以翻墙的话。
这是如何对API进行负载测试与调优的第2部分。在第1部分中,我们聊了配置测试环境,聊了要测量的指标以及测量这些指标的不同方法。我们还了解了使用哪些测试工具,以获得有关我们的API执行情况的真实数据。
我们现在将研究如何将API安全地暴露给公众,同时确保其性能不受影响。
如何为你的API添加访问控制层
我们已经有了高性能的API了,但如果万一有人以超过16000次请求/秒的速度向服务器发送请求怎么办?你如何能防止API用户向你的API发出爆炸性请求?如果没处理好,将会影响其他用户对API的使用。
解决方法有很多,最简单的就是在你的API服务器建立限速系统。我们认为应该尽可能地降低系统之间的耦合度,所以最好在你的系统中有一个单独的层,这个单独的层专门负责处理限速。
这时候API网关就可以派上用场了。API网关是解决管理API访问问题的通用架构解决方案。它除了用来做访问控制,还可以充当协调与开放内部API不同接口的整合层。
在本文案例中,我们将使用我们自己的API网关,它与3scale平台一起使API提供商能够以安全的方式向外界开放他们的API。它可以很方便地对API接口进行身份验证与设置限速。
有几种方法可以将您的API与3scale集成,我们这里选择基于Nginx的高性能代理部署API网关。我们将会在我们的API服务器之前部署3scale API网关。使用代理的原因不仅仅是性能问题:由于它部署在我们的API之前,那些没经身份验证的或高于我们允许限制的流量请求在到达API服务器之前将会被代理拒绝掉。这让我们可以更专注考虑我们的API服务器,这样我们的API服务器就可以按我们预定的流量负载来设计,不用担心超过这个流量会有什么意外发生,其他的事就交给API网关处理。当然,万一我们的API服务器负荷处理量增加或者是用户数量意外增长时,我们也能在3scale的管理平台上调整限制设置。
作为工程师,在架构中增加扩展层要谨慎。所以我们这里的目标是确保这个扩展性不会对我们的API性能造成影响。
我们会在与我们的API服务器使用相同类型配置的AWS实例上部署网关,一个带有2个虚拟核的c4.large。设置网关很简单,我们可以借用AWS服务市场上我们的AMI映像。
在3scale平台上配置好API后,我们会拿到定制的Nginx配置文件,我们用它来启动API网关。第一步将使用默认配置运行我们之前做的相同测试,请求地址要小修改一下,现在多包含了一个带有API 密钥的参数。
GET http://our-api-gateway.com/question?user_key=ABCD123
以10000次请求/秒速度运行和以前相同的测试,我们会命中几个错误。 Loader.io最终由于大量的错误停止测试。
这些都似乎是500状态码内部错误或其他未指定的网络错误。 我们查过API服务器没有返回任何错误,所以问题的源头可能是Nginx,其中日志显示大量的这些:
2015/04/12 23:07:10 [alert] 2573#0: *147508 256 worker_connections are not enough while connecting to upstream, client: ..., server: , request: "GET /question HTTP/1.1", upstream: "http://.../question", host: "..."
Nginx需要为每个请求至少打开两个连接,一个到客户端,另一个到代理服务器。 它还需要打开连接到3scale,但不是每个请求都要连(我们用的是增强版的3scale API网关,它能批量授权和生成报告)。
考虑到这一点,以10000次请求/秒的速率,Nginx将需要保持的同时打开连接的数量将远高于256。
调整API代理网关以达最大性能
配置nginx的worker_connections可配置配置同时打开的连接数。该设置也高度依赖于底层系统:Nginx不能打开比系统可提供的套接字更多的连接。如果我们想提高数字,有几个设置要修改。
修改文件/etc/security/limits.conf:
# 如果你没配过以下参数,请在文件底部增加以下行,生效需要重启系统
* soft nofile 200000
* hard nofile 200000
修改文件/etc/sysctl.conf:
# 增加打开文件的限制数
# 改完后运行这命令以生效: sudo sysctl -p /etc/sysctl.conf
fs.file-max = 5000000
改完以上内容后,你接下来可以修改nginx的配置文件nginx.conf:
...
worker_rlimit_nofile 100000;
events {
worker_connections 100000;
}
...
Nginx和系统级的优化还有其他一些方法,你可以在Nginx的官方文档中查阅。
在本文案例中,下面的配置修改,极大提高了网络资源的利用率:
(1)在upstream中启用Keep alive,这个需要将HTTP协议设为1.1版,这也是Node.js默认使用的版本。
(2)减少tcp_fin_timeout以最小化TIME_WAIT状态中的连接数,这样我们就不需要很多过时的连接,记得也要启用tcp_tw_reuse。
(3)将worker_processes设为auto ,这样Nginx就可为每一个可用CPU内核启动一个worker进程。
还有很多设置可以提高Web服务器的性能,特别是在系统级的设置。你可以在这里对照一下更为完整的优化配置列表。建议你要对你的系统环境有足够的了解,才能应用这些优化配置。
还有其他一些配置对负载测试环境的影响比在生产环境中影响更大,比较容易产生误导性的测试结果。比如,增加Nginx中 keepalive_requests 的值可以让一个keep-alive连接发送更多的请求。在我们的测试标准中,所有的负载生成都是从单一源发出了,如果增大这个值,明显会比负载来自多个源更有效率。
检查一下优化设置是否生效,我们可以在Loader.io上以60秒运行10000请求/秒的测试。测试结果如下:
测试结果现在没问题了,没有500错误或网络错误。我们达到了我们预期的速率。不过有点微小的差别,就是曲线在延迟增加的地方有些波峰突起,这些突起点是当Nginx需要向3scale反馈数据时发生的,这也影响了当时正要处理的几个客户端请求。网关中的报告生成是由每个客户端完成的,这就是为什么这里的影响非常明显,因为我们从单个客户端生成大量流量。此外,在测试期间这些报告成生的批处理也是相当频繁地进行。如果我们将周期设置的比测试持续时间更长,基本上我们一访问完API,结果就马上出来。
最后,我们用wrk重新来做和前面同样的测试。结果发现通过API网关的性能和我们直接访问API的性能基本一致。但还是有一个比较大的区别,我们现在在我们的API前面多了一层,这一层让我们可以控制它,可以设定速率限制,可以身份验证,可以看到API的使用情况统计分析。而这一切都不需要再修改我们的API代码。
运行1分钟测试 @ http://api-gateway/question
4 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 85.27ms 90.29ms 1.27s 92.76%
Req/Sec 3.98k 588.91 4.27k 64.50%
Latency Distribution
50% 85.75ms
75% 96.61ms
90% 127.49ms
99% 230.90ms
955320 requests in 1.00m, 194.17MB read
Requests/sec: 15942.54
Transfer/sec: 3.23MB
总结
通过这两篇文章,我们讲述 如何对API进行一个有效的负载测试。我们先要配置好测试环境,为准备好测试提供了一些建议。然后我们介绍了市面上以及开源社区里的几个负载测试工具。我们测算出API能实现的峰值性能,同时在性能不受损的前提下增加了API的访问控制层。
从本文的测试中,我们总结出以几个关键点:
(1)在运行测试之前,你要先定好目标,这些目标最好是基于你目前流量数据来定的。这有助于你确定你的API要达到的性能目标线。
(2)要花点时间准备好一个可测量的稳定基线环境。如果你一开始就没弄好,你的测试结果就毫无价值。
(3)别让测试工具成为你测试的限制因素,要研究了解每个测试工具的特性(比如单线程、多线程),多个测试工具的测试可以让你更全面的了解你的API性能。
(3)当你微调了你架构中某部分组件的性能时,你需要对架构中所有部分进行观测。如果限制因素在系统级别上,那么在API层做优化调整也没用。
(4)有一个API网关管理层可以让你更安心,因为管理层可以安全保护好你的API,API只会获得可预测的流量,不会受爆炸性的意外流量影响。对于非可预测的流量,API网关会处理好。
希望本文能给你带来帮助!
本文来自马克在 APIStrat / APIDays 柏林站的演讲整理。
本文译自:How to load test & tune performance on your API (Part II)