普段Nginxを使ってはいるものの、その仕組やなぜNignxを使うべきなのかというところがあまりわかっていなかったので、
改めてNginxを入門しその仕組などについて調べてみた。
勉強不足もあって、間違ってることもあるかもしれないがその際は教えて下さい。
1. C10K問題
まず、Nginxを理解する上でC10K問題について知る必要がある。
C10K問題とは下記の問題のことだ。
ハードウェアの性能上は問題がなくても、クライアント数があまりにも多くなるとサーバがパンクする問題のこと。 C は「Client(クライアント)」の頭文字、10K は「1 万台」を意味する。「クライアント 1 万台問題」ともいわれる。
(C10K 問題とは - はてなキーワード より引用)
2. 従来のWebサーバのアーキテクチャ
prefork
Apacheのデフォルトのアーキテクチャなどで採用されている。
特徴としては、1リクエストに対して1プロセスが処理する。
すなわち同時接続が 1000であれば 1000個のプロセスが必要となる。
worker
リクエストはスレッドが処理する。
スレッドは1プロセスのなかで複数立ち上げることができる。
プロセス数は少なくて済むが、同時接続が1000であれば1000個のスレッドが必要となる。
Apacheで指定可能なアーキテクチャの1つ。
いずれにしても、1000の同時接続があれば、1000のプロセスやスレッドが必要ということだ。
プロセス/スレッド数が多くなってくると「コンテキストスイッチ」が多く発生し、処理が遅くなってしまう。
コンテキストスイッチとは
コンテキストスイッチとは、コンピュータの処理装置(CPU)が現在実行している処理の流れ(プロセス、スレッド)を一時停止し、別のものに切り替えて実行を再開すること。
(コンテキストスイッチとは|コンテキストスイッチング|context switch - 意味/定義 : IT用語辞典 より引用)
3. Nginxのアーキテクチャ
NginxがC10K 問題を解決するために開発されたともいわれている。
上記のような課題を解決するようなアーキテクチャを採用している。
ワーカプロセスがリクエストを処理する。
前述のpreforkやworkerと決定的に違うところは、1つのワーカプロセスが複数のリクエストを処理するということだ。
また、マスタープロセスはワーカプロセスの立ち上げや、制御、管理などが主な仕事。
Nginxを終了あるいは再起動、設定ファイルを再読み込みして変更を反映するなど。
下記のような仕組みがNginxの高速化(C10K問題対応)を可能としている。
シングルスレッド
接続ごとにプロセスやスレッドを立ち上げていては、C10K問題に対応できない。
そこで、Nginxは1つのスレッドで処理を行うようにしている。
それにより、コンテキストスイッチと呼ばれるCPUの切り替え処理が発生しない。
正確に言うと、完全に1スレッドで処理するわけではなく図にあるようにワーカプロセス自体はマルチプロセス化できる。
イベント駆動
通常のプログラムは上から書かれた順に実行されますよね。
イベ ント駆動で動作するプログラムは何かしらのイベントが発生するまで待機し、発生したイベントの種類に応じて実行される。
ブラウザ上のJavaScriptの動きをイメージするとわかりやすいと思う。
非同期処理
一般的なwebサーバでは同期処理を行う。
つまり、複数のリクエストがあったときに順番に処理していく。
そのため、1つのリクエストが遅いとそれに引きづられてあとのリクエストも遅くなる。
非同期処理では、リクエストがきたら他のリクエストの状況に関わらず処理を行う。
同期処理
非同期処理
向いていること / 向いていないこと
Nginxではイベント駆動で非同期的なIO処理によって、リクエストを完全に処理することを待たずに次から次へと処理を受け付けていきます。
そのため、1処理に時間のかかるものをNginx自身で行おうとするとキューがどんどん溜まってしまいます。
そのため、一般にアプリケーションの実行やデータベース処理などは向いていません。
一方で、軽量な静的データの配信やリバースプロキシなどに向いています。
Nginxは、静的データの配信や、プロキシなどに特化させ、アプリケーションの実行などは別途アプリケーションサーバ等で行わせることで有効活用できます。
向いていること
- 軽量データの大量配信
- ディスクI/Oの発生しないキャッシュ
- リバースプロキシ
- ロードバランサ
向いていないこと
- アプリケーション実行
- データベース処理
- 動画などの重たいデータの配信
4. 最後に
NginxやWebサーバについてより理解を深めるためには、
UNIXのプロセスやネットワークAPIについての知識が足りないことに気づきます。
というわけで、もう販売はされておらず中古でしか手に入らないのですが、UNIXネットワークプログラミングのバイブルを購入し、C言語を少し学びました。978ページもあるため、本当にこれを学ぼうと思ったのは、購入してから数年後にモチベーションが再熱したタイミングでしたが、非常に良書であることは間違いないです。
上を買うのに自信がない人は、Rubyになってしまいますがこのような書籍から入るのがいいと思います。