ホームページ >運用・保守 >Nginx >nginx シグナルセットの分析例

nginx シグナルセットの分析例

WBOY
WBOY転載
2023-05-13 10:37:161095ブラウズ

シナリオの再現

以下では、ネイティブ nginx を使用して、fedora26 がインストールされた仮想マシン上でこのプロセスを再現します。使用する nginx バージョンは最新の 1.13.4

最初に nginx を起動します

nginx シグナルセットの分析例

マスターとワーカーの両方がすでに実行されていることがわかります。

次に、マスターに sigusr2 シグナルを送信し、nginx コアがこのシグナルを受信すると、ホット アップデートがトリガーされます。

nginx シグナルセットの分析例

新しいマスターと、マスターによってフォークされたワーカーがすでに実行されていることがわかります。この時点で、古いマスターにシグウィンチ信号を送信し、古いマスターはこれを受け取ります。 シグナルの後、sigquit がそのワーカーに送信されるため、古いマスターのワーカー プロセスは終了します:

nginx シグナルセットの分析例

現時点では、古いマスターのみ、新しいマスターと新しいマスターが残り、マスターのワーカーが実行されており、そのときのオンライン操作と同様です。

次に stop コマンドを使用します:

nginx シグナルセットの分析例

新しいマスターとそのワーカーが終了し、古いマスターがまだ実行中であることがわかります。生み出された労働者。当時のネット上の状況はこんな感じでした。

実際、この現象は nginx 自体の設計に関連しています。古いマスターが新しいマスターをフォークする準備ができると、nginx.pid ファイルの名前が nginx.pid.oldbin に変更され、その後、名前が変更されます。フォークからの新しいマスターは新しい nginx.pid を作成し、このファイルには新しいマスターの pid が記録されます。 nginx は、ホット アップデートが完了すると、古いマスターの使命はほぼ終了し、いつでも終了するため、その後のすべての操作は新しいマスターに引き継がれる必要があると考えています。もちろん、古いマスターが終了せずに新しいマスターに sigusr2 を送信して別のホット アップデートを試みることは無効であり、新しいマスターはこの信号を無視して独自の作業を続行します。

問題分析

さらに残念なのは、上で説明した lua テーブル、つまりそれを定義する lua ファイルが、init_by_lua フックが実行される時点ですでに luajit によってメモリにロードされていることです。そしてバイトコードにコンパイルされると、ロードされる lua コードの一部が古いバージョンであるため、古いマスターにはこの lua テーブルが存在してはなりません。

テーブルのインデックスを作成する Lua コードは、init_by_lua では使用されません。これらのコードはワーカー プロセスに読み込まれます。この時点では、プロジェクト ディレクトリ内のコードはすべて最新であるため、ワーカー プロセスは最新のコードをこれらのワーカー プロセスが関連するリクエストを処理すると、Lua ランタイム エラーが発生し、外部マニフェストは対応する http 500 になります。

この教訓を理解した後は、nginx サービスをより合理的にシャットダウンする必要があります。したがって、より合理的な nginx サービスの起動および終了スクリプトが必要になりますが、インターネット上で流通しているスクリプトの中にはこの現象に対応していないものもありますので、nginx が提供する公式スクリプトを参照する必要があります。

nginx シグナルセットの分析例

このコードは nginx 公式 /etc/init.d/nginx から引用しています。

nginx シグナル セット

次に、nginx シグナル セットを包括的に整理しましょう。ここではソース コードの詳細には関与しません。興味のある学生は関連するソース コードを自分で読んでください。

マスター プロセスにシグナルを送信するには 2 つの方法があります。1 つは nginx -s シグナルを使用して操作する方法、もう 1 つは kill コマンドを使用して手動で送信する方法です。

最初の方法の原理は、nginx.pid ファイルを通じてマスター プロセスの pid を取得し、対応するシグナルをマスターに送信して終了する新しいプロセスを生成することです。このプロセスは次のとおりです。シグナラーと呼ばれる。

2 番目の方法では、nginx -s 信号と実際の信号のマッピングを理解する必要があります。次の表は、それらのマッピング関係を示しています。

operation signal
reload sighup
reopen sigusr1
stop sigterm
quit sigquit
hot update sigusr2 & sigwinch & sigquit
stop vs quit

#stop は sigterm シグナルを送信して強制終了を示し、quit は sigquit を送信して正常な終了を示します。具体的な違いは、ワーカー プロセスが sigquit メッセージを受信した後 (シグナルは直接送信されないため、代わりにメッセージが使用されることに注意してください)、リッスンしているソケットを閉じ、現在のアイドル接続 (プリエンプト可能な接続) を閉じることです。 ) を事前に処理し、すべてのタイマー イベントは最後に終了します。特別な事情がない限り、stop ではなく quit を使用する必要があります。

reload

マスター プロセスは、sighup を受信した後、構成ファイルを再解析し、共有メモリを適用し、その他の一連のタスクを実行して、新しいワーカーのバッチを生成します。ワーカープロセスは sigquit に相当するメッセージを送信し、最終的にはシームレスに再起動が実現されます。

再開

マスター プロセスは sigusr1 を受信した後、開いているすべてのファイル (ログなど) を再度開き、sigusr1 情報を各ワーカー プロセスに送信します。ワーカー プロセスはシグナルを受信した後、同じ操作を実行します。 Reopen はログの切断に使用できます。たとえば、nginx は公式にソリューションを提供しています:

nginx シグナルセットの分析例

マスター プロセスがワーカー プロセスに sigusr1 メッセージを送信するため、ここでは sleep 1 が必要です。実際に access.log を再度開くまでには時間がかかりますが、この時点でも、ワーカー プロセスは依然としてファイル access.log.0 にログを書き込みます。 1 秒スリープすることで、access.log.0 ログ情報の整合性が保証されます (スリープせずに直接圧縮を実行すると、ログ損失が発生する可能性があります)。

ホット アップデート

バイナリ ホット アップデートを実行する必要がある場合があります。nginx には設計時にこの機能が含まれていますが、nginx が提供するコマンド ラインでは完了できません。手動で送信する必要があります。 。

上記の問題の繰り返しを通じて、ホット アップデートの実行方法を理解できたはずです。まず sigusr2 を現在のマスター プロセスに送信する必要があります。その後、マスターは nginx.pid の名前を nginx.pid に変更します。 oldbin.その後、新しいプロセスをフォークします。新しいプロセスは、execve システム コールを使用して、現在のプロセス イメージを新しい nginx elf ファイルに置き換え、新しいマスター プロセスになります。新しいマスター プロセスが起動すると、構成ファイルの解析やその他の操作が実行され、新しいワーカー プロセスがフォークアウトされて動作を開始します。

次に、古いマスターに sigwinch シグナルを送信します。その後、古いマスター プロセスは sigquit メッセージをワーカー プロセスに送信し、ワーカー プロセスを終了させます。 sigwinch と sigquit をマスター プロセスに送信するとワーカー プロセスが終了しますが、前者ではマスター プロセスも終了しません。

最後に、古いマスター プロセスがその使命を完了したと感じた場合は、それに sigquit シグナルを送信して終了させることができます。

ワーカー プロセスがマスターからのシグナル メッセージを処理する方法

実際、マスター プロセスは、kill 関数を使用せず、パイプを通じて実装された nginx チャネルを使用してワーカー プロセスと通信します。 、マスター プロセスがパイプの一端に情報 (シグナル情報など) を書き込み、ワーカー プロセスがもう一方の端から情報を受信します。ワーカーが実行されると、nginx チャネル イベントがイベント スケジューラ (epoll、kqueue など) に追加されます。プロセスが開始されたばかりなので、マスターからデータが送信されたときに、イベント スケジューラによって通知できます。

nginx がこのように設計されているのには理由があります。優れたリバース プロキシ サーバーとして、nginx は極めて高いパフォーマンスを追求しており、シグナル ハンドラーがワーカー プロセスの実行を中断し、すべてのイベントが一時停止されます。パフォーマンスに一定の損失が生じます。

マスター プロセスがワーカー プロセスに情報を送信すると、ワーカー プロセスは対応する操作ですぐに応答すると考える人が多いかもしれませんが、ワーカー プロセスは非常にビジーであり、常にネットワーク イベントやタイマー イベントを処理しています。 nginx チャネル イベント ハンドラーを呼び出した後、nginx は一部のフラグのみを処理します。これらのアクションは、一連のイベント スケジュールが完了した後に実際に実行されます。そのため、その間に時間枠があり、特に業務が複雑でトラフィックが多い場合には、この時間枠が拡大する可能性があるため、nginx が公式に提供するログカットプランでは sleep 1 秒が必要となります。

もちろん、マスター プロセスをバイパスして、ワーカー プロセスにシグナルを直接送信することもできます。ワーカーが処理できるシグナルは、

signal effect
sigintforce exit
です。 sigterm 強制終了
sigquit 正常な終了
sigusr1 ファイルを再度開きます

以上がnginx シグナルセットの分析例の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。