【Nginx x ECS】Nginxの適正設定値の導き方

たきぐち

2023.02.24

1272

たきぐちです。

最近はもっぱらインフラ周り触っております。


今回はみなさん大好きNginxの設定を僕なりにまとめたので、共有しようということで記事にしました。

経緯

Nginxの設定って何を基準にすればええねん!!!

(...なんかみんな当たり前にNginxの設定してるけど何考えてるの??.....僕もとりあえずやってみよ.....あ、なんか動いたからこれでいっか.....)

これやっちゃってる人いるでしょ!!!ダメですよ!!!

ということでnginxの設定値を導き出したので今回触っていきましょう。

Nginx

そもそもNginxってなんぞや?

Nginx(エンジンエックス)は、高性能かつ軽量なWebサーバーであり、リバースプロキシや負荷分散の機能を持つプロキシサーバーとしても使用されます。また、Nginxは、静的コンテンツの配信、FastCGI、WebSocket、SSL/TLSなどの機能をサポートしています。
Nginxは、シングルプロセス・イベント駆動型アーキテクチャを採用しており、高い同時接続数を処理することができます。また、モジュール機構を持ち、ユーザーが自由に拡張することができます。
Nginxは、オープンソースソフトウェアであり、高いパフォーマンスと安定性セキュリティに優れているため、世界中で多くのWebサイトやアプリケーションで使用されています。


ほうほう。つまり簡単にいうと高性能なwebサーバーっちゅうことか。

別の有名どこでいうと"Apache"っちゅうもんがあるな。(今回はNginxメインだから今度触れることにしよう。)


Nginxの設定ファイル

前にwebアプリケーションの構築してるときに下記の設定パラメータがあったんだよね。

worker_rlimit_nofile
worker_processes
worker_connections


.....なんだよこれ!!!!!適正値なににすればいいの?!!


ということで一緒に適正値を設定していきましょう。

の前に上記設定パラメータの説明載せときますねい。

Nginx Webサーバーのパフォーマンスとリソース使用量を制御するための重要な設定
  • worker_rlimit_nofileは、各Nginxプロセスが開くことができるファイルディスクリプタの最大数を制限するための設定です。ファイルディスクリプタは、オープンされたファイル、ソケット、パイプなどのリソースへの参照を表します。Webサーバーが多くのクライアント接続を処理する場合、プロセスが使用するファイルディスクリプタの数が急増する可能性があります。この設定を適切に調整することで、プロセスが必要なリソースを適切に管理し、システム全体のパフォーマンスを向上させることができます。
  • worker_processesは、Nginxサーバーが起動するときに生成されるワーカープロセスの数を設定するための設定です。Nginxは、クライアントリクエストを処理するために複数のプロセスを使用します。ワーカープロセスは、クライアントの接続を受け取り、リクエストを処理してレスポンスを返します。この設定は、Webサーバーの処理能力とリソース使用量を制御するために非常に重要です。
  • worker_connectionsは、各ワーカープロセスが同時に処理できるクライアント接続の最大数を制御するための設定です。この設定を上げることで、Webサーバーが同時に多数のクライアント接続を処理できるようになります。ただし、この設定が高すぎる場合、プロセスのリソース使用量が増加し、サーバー全体のパフォーマンスが低下する可能性があります。したがって、この設定を適切に調整することが重要です。


うん。とりあえず手動かそっか💕

設定値を求める

こいつは簡単にいうとNginxのプロセスが開けるファイルディスクリプタの最大数。

ファイルディスクリプタとは、オープンされたファイル、ソケット、パイプなどのリソースへの参照を表す整数値です。プログラムがファイルを開いたり、ソケットを作成したりすると、それぞれのファイルディスクリプタが返されます。このファイルディスクリプタを使用して、プログラムはファイルやリソースにアクセスし、読み書きや通信を行います。

まずはこいつの適正値を求めていこう↓


1, nginxのサーバーのOSの扱えるファイルの最大値を確認

cat /proc/sys/fs/file-max
392069


※なんで確認するの?

ファイルディスクリプタを設定する際OSで扱える以上を設定すると、NginxでOSで扱えない量のファイル数を参照しエラーになってNginx落ちちゃうお。

参考) https://please-sleep.cou929.nu/nginx-too-many-open-files-error.html


2, wokerプロセス数を設定する。

worker_processの設定値は下記がベスト。CPUのスペックに合わせてよしなにprocess数を設定してくれる。

worker_processes auto;


3, wokerプロセス数を確認する。

# ps -ef | grep nginx
root         1     0  0 08:08 ?        00:00:00 nginx: master process nginx -g daemon off;
nginx       35     1  0 08:08 ?        00:00:00 nginx: worker process
nginx       36     1  0 08:08 ?        00:00:00 nginx: worker process
nginx       37     1  0 08:08 ?        00:00:00 nginx: worker process
nginx       38     1  0 08:08 ?        00:00:00 nginx: worker process
nginx       39     1  0 08:08 ?        00:00:00 nginx: worker process
root        98    88  0 08:40 pts/0    00:00:00 grep nginx


今回でいうと5つ動いてることになりますね。


4, worker_rlimit_nofileを設定する

workerrlimitnofileは workerプロセスの最大オープンファイル数の上限値で、workerプロセス毎の値です。OSの上限は先ほど確認しましたね。

少し余裕を持たせて90パーセントにしましょうか。

上限値 ÷ worker_process(2) * 0.9
392069 ÷ 5 * 0.9 = 70571...
# 端数を切る
worker_rlimit_nofile 70000;


5, worker_connectionsを設定する

この設定は、Nginxが扱える同時接続数を制限するためのもので、worker_connectionsの値はNginxワーカープロセスが同時に接続できるクライアントの最大数を定義します。一方、worker_rlimit_nofileは、Nginxワーカープロセスが同時に開けるファイルディスクリプタの最大数を定義します。

さて最後の設定値ですが下記は守っていれば特に問題はないです。

worker_connections * 2 < worker_rlimit_nofile


※2ってなんの数字?

ファイルディスクリプタを使用するための最小限の値を表します。Nginxワーカープロセスは、各接続に対して少なくとも1つのファイルディスクリプタを使用します。また、一部のモジュールは、追加のファイルディスクリプタを使用する場合があります。


バッファを持って3~4倍でも超えない値を設定するのが良いでしょう。

worker_rlimit_nofile 70000; # worker_connections の3~4倍以上の値を設定

events {
  worker_connections 8192; # 1つのworkerプロセスが開ける最大コネクション数
  ...
}


8192の4倍は32768なので余裕です。


最終的なファイルは下記になります。

user  nginx;
worker_processes auto;
worker_rlimit_nofile 70000;

events {
  worker_connections 8192;
}


Doneです!!

Tips

Q, ECSでNginxコンテナを立てると以下エラーが出る、、、



A, コンテナのタスク定義で下記を設定する

"ulimits": [
      {
        "name": "nofile",
        "softLimit": 100000,
        "hardLimit": 100000
      }
    ]


Q, 上記やってもまだ同じエラーが出る、、、、

1, 一旦サーバーに入って確認

ulimit -n
100000


ん?適用されてね?

ということで調べてみた。

workerrlimitnofileとECSタスク定義のulimitの設定が競合していない場合、setrlimit(RLIMIT_NOFILE, 100000) failed (1: Operation not permitted)というエラーが発生することはなくなります。そのため、ECSタスク定義の方に適切なulimitの設定を行うことで、問題を解決することができます。ただし、ECSタスク定義のulimitの設定によって、Nginxプロセスが必要とするファイルディスクリプタ数を満たせているかどうかを確認する必要があります。必要なファイルディスクリプタ数がulimitの設定を超える場合は、設定値を調整する必要があります。


つまりタスク定義で設定している値とnginx.confで設定している値が競合してエラーが出ていたらしい。

どちらか片方を消せばエラーは解消されるが、タスク定義で設定している場合Nginxのプロセスの基準値を考慮する必要があるらしい。

両方に設定を行う場合は、workerrlimitnofileとECSタスク定義のulimitで同じ値を設定するようにします。ただし、上記でも述べたように、両方の設定が競合する場合があるため、可能な限りどちらか一方の設定に統一することをお勧めします。

nginx.confとタスク定義で同じ値を入れれば特に問題はなし。

nginx.confの方にタスク定義と同じ値を記述して対応した。


最後にサーバー上にて確認

# cat /proc/35/limits
Limit                     Soft Limit           Hard Limit           Units
Max cpu time              unlimited            unlimited            seconds
Max file size             unlimited            unlimited            bytes
Max data size             unlimited            unlimited            bytes
Max stack size            10485760             10485760             bytes
Max core file size        unlimited            unlimited            bytes
Max resident set          unlimited            unlimited            bytes
Max processes             unlimited            unlimited            processes
Max open files            100000                100000                files
Max locked memory         unlimited            unlimited            bytes
Max address space         unlimited            unlimited            bytes
Max file locks            unlimited            unlimited            locks
Max pending signals       30446                30446                signals
Max msgqueue size         819200               819200               bytes
Max nice priority         0                    0
Max realtime priority     0                    0
Max realtime timeout      unlimited            unlimited            us


CloudWatchのエラーも消えてulimitsも適用されてるので一旦よし。

この記事をシェアする