最適化:HTTPAPIのRPSパフォーマンスを向上させるためのNginxWebサーバーの構成



インフラストラクチャをスケーリングおよびスケーリングする前の最初のステップは、リソースが正しく使用されていること、およびアプリケーション構成がパフォーマンスのボトルネックにならないことを確認することです。エンジニアリングチームの主な目標は、最小限のリソースで、設計および展開されたシステムの継続的で中断のない運用を保証することです。



上記の問題が発生し、展開されたシステムが、時々バーストで接続する100万人のユーザーによって毎日使用されていました。つまり、この状況では、複数のサーバーを展開したり、それらをスケーリングしたりすることは最善の解決策ではありません。



この記事では、パフォーマンスを向上させるため、つまりHTTP APIのRPS(Requests Per Second)を増やすためにNginxを調整する方法について説明します。大量のリソースを無駄にすることなく、1秒あたり数万のリクエストを処理するためにデプロイされたシステムに適用した最適化について説明しようとしました。



アクションプラン: NginxでプロキシされたHTTP API(フラスコを使用してPythonで記述)を実行する必要があります。高帯域幅が必要です。APIの内容は1日間隔で変更されます。



最良の結果を達成するための最適化

名詞



プロセス。状況またはリソースの最も効率的な使用。


スーパーバイザー を使用して、次の構成で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(1秒あたりの要求数)が増加しましたが、それほど多くはありませんでした。



Nginxキャッシュの追加



この場合、エンドポイントのコンテンツは1日間隔で更新されるため、API応答をキャッシュするための適切な環境が作成されます。



しかし、キャッシュを追加すると無効になります...これはここでの2つの問題の1です。

コンピュータサイエンスでは、キャッシュの無効化と名前の付け方の2つの問題しかありません。-フィル・カールトン



ダウンストリームシステムのコンテンツを更新した後、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ディレクティブで適切な値を使用してバッファフラッシュパラメータを追加する必要があります



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


この構成により、1秒あたりのリクエスト数が大幅に増加し、初期段階の30倍になりました。



出力



この記事では、RPSのパフォーマンスを向上させるためにNginx構成を最適化するプロセスについて説明しました。RPSは1663から約50413に増加し(約30倍の増加)、高いスループットを提供します。デフォルト設定を調整することにより、システムパフォーマンスを向上させることができます。



引用で記事を終えましょう:

最初に機能させます。次に、それを正しく行います。次に、最適化します。-ケントベック

ソース






All Articles