在扩展和扩展基础结构之前,第一步是确保正确使用资源,并且应用程序配置不会成为性能瓶颈。工程团队的主要目标是以最少的资源确保任何已设计和部署的系统连续,不间断地运行。
我们遇到了上述问题,每天有100万用户不时使用我们部署的系统,这些用户会不时地突发连接。这意味着在这种情况下,部署多个服务器或扩展它们不是最佳的解决方案。
本文介绍有关调整Nginx的性能,以提高性能,即提高HTTP API中的RPS(每秒请求数)。我试图告诉您有关我们在已部署系统中应用的优化,以每秒处理数万个请求而又不浪费大量资源。
行动计划:您需要运行以Nginx代理的HTTP API(使用flask用Python编写);需要高带宽。API内容将每隔一天更改一次。
优化
名词
过程以获得最佳结果;最有效地利用情况或资源。
我们使用的主管开始WSGI服务器使用以下配置:
超级用户命令如下所示:
gunicorn api:app --workers=5 --worker-
class=meinheld.gmeinheld.MeinheldWorker --bind=unix:api.sock
我们尝试优化Nginx配置,并检查了最适合我们的方法。
为了评估API的性能,我们将wrk与以下命令结合使用:
wrk -t20 -c200 -d20s http://api.endpoint/resource
默认配置
我们首先对API进行了负载测试,没有进行任何更改,并获得了以下统计信息:
Running 20s test @ http://api.endpoint/resource
20 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 192.48ms 274.78ms 1.97s 87.18%
Req/Sec 85.57 29.20 202.00 72.83%
33329 requests in 20.03s, 29.59MB read
Socket errors: connect 0, read 0, write 0, timeout 85
Requests/sec: 1663.71
Transfer/sec: 1.48MB
更新默认配置
让我们更新默认配置Nginx的即nginx.conf在/etc/nginx/nginx.conf
worker_processes auto;
#or should be equal to the CPU core, you can use `grep processor /proc/cpuinfo | wc -l` to find; auto does it implicitly.
worker_connections 1024;
# default is 768; find optimum value for your server by `ulimit -n`
access_log off;
# to boost I/O on HDD we can disable access logs
# this prevent nginx from logging every action in a log file named `access.log`.
keepalive_timeout 15;
# default is 65;
# server will close connection after this time (in seconds)
gzip_vary on;
gzip_proxied any;
gzip_comp_level 2;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_min_length 256;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
# reduces the data that needs to be sent over the network
nginx.conf(/etc/nginx/nginx.conf)
更改后,我们运行配置检查:
sudo nginx -t
如果检查成功,则可以重新启动Nginx以反映更改:
sudo service nginx restart
使用此配置,我们对API进行了负载测试,并获得了以下结果:
Running 20s test @ http://api.endpoint/resource
20 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 145.80ms 237.97ms 1.95s 89.51%
Req/Sec 107.99 41.34 202.00 66.09%
42898 requests in 20.03s, 39.03MB read
Socket errors: connect 0, read 0, write 0, timeout 46
Non-2xx or 3xx responses: 2
Requests/sec: 2141.48
Transfer/sec: 1.95MB
这些配置减少了超时并增加了RPS(每秒请求数),但数量不多。
添加Nginx缓存
由于在我们的情况下,端点的内容将每隔一天更新一次,因此这为缓存API响应创建了一个合适的环境。
但是添加缓存会使它无效……这是这里的两个困难之一。
在计算机科学中,只有两种复杂性:使缓存无效和命名事物。-菲尔·卡尔顿
我们选择一种简单的解决方案,以在更新下游系统上的内容之后使用cronjob清除缓存目录。
接下来,Nginx将完成所有艰苦的工作,但是现在我们需要确保Nginx已100%准备就绪!
要将缓存添加到Nginx,您需要向Nginx配置文件添加几个指令。
在此之前,我们需要创建一个目录来存储缓存数据:
sudo mkdir -p /data/nginx/cache
Nginx配置更改:
proxy_cache_path /data/nginx/cache keys_zone=my_zone:10m inactive=1d;
server {
...
location /api-endpoint/ {
proxy_cache my_zone;
proxy_cache_key "$host$request_uri$http_authorization";
proxy_cache_valid 404 302 1m;
proxy_cache_valid 200 1d;
add_header X-Cache-Status $upstream_cache_status;
}
...
}
缓存代理请求(Nginx配置)
在此配置更改之后,我们对API进行了负载测试,并得到以下结果:
Running 20s test @ http://api.endpoint/resource
20 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 6.88ms 5.44ms 88.91ms 81.36%
Req/Sec 1.59k 500.04 2.95k 62.50%
634405 requests in 20.06s, 589.86MB read
Requests/sec: 31624.93
Transfer/sec: 29.40MB
因此,通过添加缓存,我们的性能几乎提高了19倍。
Timeweb专家的注意事项:请
务必记住,缓存写入数据库的查询将导致缓存的响应,但不会写入数据库。
RAM(随机存取记忆体)中的Nginx快取
让我们更进一步!目前,我们的缓存数据存储在磁盘上。如果我们将这些数据保存在RAM中怎么办?在我们的情况下,响应数据有限且不大。
因此,首先需要创建一个目录,该目录将安装RAM缓存:
sudo mkdir -p /data/nginx/ramcache
要使用tmpfs将创建的目录挂载到RAM中,请使用以下命令:
sudo mount -t tmpfs -o size=256M tmpfs /data/nginx/ramcache
这会将/ data / nginx / ramcache挂载到RAM中,分配256MB。
如果您认为要禁用RAM缓存,请运行以下命令:
sudo umount /data/nginx/ramcache
要在重启后自动在RAM中重新创建缓存目录,我们需要更新/ etc / fstab文件。向其添加以下行:
tmpfs /data/nginx/ramcache tmpfs defaults,size=256M 0 0
注意:我们还必须将proxy_cache_path值注册到ramcache的路径( / data / nginx / ramcache)。
更新配置后,我们再次执行API负载测试并获得以下结果:
Running 20s test @ http://api.endpoint/resource
20 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 5.57ms 5.69ms 277.76ms 92.94%
Req/Sec 1.98k 403.94 4.55k 71.77%
789306 requests in 20.04s, 733.89MB read
Requests/sec: 39387.13
Transfer/sec: 36.62MB
将缓存存储在RAM中导致显着提高了近23倍。
缓冲访问日志
我们保留对代理应用程序访问的日志,但是您可以先将日志保存在缓冲区中,然后再将其写入磁盘:
- 如果日志的下一行不适合缓冲区
- 如果缓冲区中的数据早于flush参数中指定的数据。
此过程将减少每个请求执行的记录频率。为此,我们只需要在access_log指令中添加具有适当值的buffer和flush参数:
location / {
...
access_log /var/log/nginx/fast_api.log combined buffer=256k flush=10s;
error_log /var/log/nginx/fast_api.err.log;
}
写入磁盘之前的缓冲区日志因此,根据上述配置,最初,只有在缓冲区达到256KB或缓冲的数据早于10秒时,访问日志才会被缓冲并保存到磁盘。
注意:名称是log_format组合在这里。
经过反复的负载测试,我们得到以下结果:
Running 20s test @ http://api.endpoint/resource
20 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 4.21ms 3.19ms 84.83ms 83.84%
Req/Sec 2.53k 379.87 6.02k 77.05%
1009771 requests in 20.03s, 849.31MB read
Requests/sec: 50413.44
Transfer/sec: 42.40MB
与初始阶段相比, 此配置显着增加了每秒的请求数量,约为30倍。
输出量
在本文中,我们讨论了优化Nginx配置以提高RPS性能的过程。RPS已从1663年增加到〜50413(增加了约30倍),从而提供了高吞吐量。通过调整默认设置,可以提高系统性能。
让我们以引号结尾文章:
首先使它工作。然后正确地做。然后优化。-肯特·贝克