Edited at

Nginxのアーキテクチャを理解する

Nginxのアーキテクチャについて調べてたことをまとめた。


用語のおさらい


プロセス(Process)



  • プログラムの実行単位であり、CPU時間単位で割り振られる。

  • 状態(ステート)があり、現在処理中であるRunning状態だったり、実行可能状態であるReady等が存在する。

  • CPUがプロセスを実行する場合、そのプロセスが持つメモリデータに対して演算をを行う。

  • プロセスはテキストセグメントとデータセグメントからなる構造データをメモリ上に持っている。



    • テキストセグメント


      • プログラムの命令列




    • データセグメント


      • PDA (Processor Data Area)と呼ばれる、プロセッサの情報やプロセス管理用のデータ領域

      • データ領域と呼ばれる、定数等が置かれる静的領域と、通常の変数等が置かれるヒープ領域からなる領域

      • スタック領域と呼ばれる、一時的なデータ保管領域





実行中のプロセスを確認

~ ❯❯❯ ps

PID TTY TIME CMD
6966 ttys000 0:00.03 /Applications/iTerm.app/Contents/MacOS/iTerm2 --server login -fp kenta
6968 ttys000 0:00.35 -zsh
7116 ttys001 0:00.01 -zsh


スレッド(Thread)



  • CPUを利用するための実行単位で、最小処理単位の概念


  • 子プロセスは独自の仮想メモリを割り当てられるため、より軽量な実行単位が求められLinux2.4からつくられた。


平行と並列の違い

定義


システムが複数の動作(処理の流れ)を同時に実行状態(in progress)に保てる機能を備えている場合を 並行(concurrent)と言い、複数の動作を同時に実行できる場合を並列(parallel)と言います。 重要な概念、違いは「実行状態」という点です。



並行(concurrent)


  • ある任意時間時で一つの仕事しか行わないが、複数の仕事を切り替えることにより同時に実行すること。

  • 複数の仕事(スレッド)を実行状態として保てている状態。


並列(pararell)


  • ある任意時間時で複数の仕事を同時に実行すること。


  • 並列は平行を包含していることに注意。


JavaScripで例えてみる

非同期処理はメインのスレッドと別スレッドで動いているから並列処理では?と思いがちだが、実際は平行処理を行なっている。


  • 具体的に、基本的にJSはシングルスレッドのプログラムなので一見並列で動いていそうなsetTimeout等の非同期処理も実は同じスレッドで動いている

  • キューに登録された関数が順番に一つづつ実行されるが、非同期処理の実装では実行待ちのキューにコールバック関数が割り込まれるようになっている。



引用 : https://qiita.com/klme_u6/items/ea155f82cbe44d6f5d88


シングルプロセスとマルチプロセス(マルチタスク)


マルチプロセス


  • 複数のプロセスを並列処理すること。


  • クライアントからの接続毎にプロセスをフォークして処理する。

  • プロセスをフォーク(fork)し、子プロセスを複数立ち上げることで同じプログラムを並列実行することができる。

  • プロセス ∋ スレッドの概念であることに注意。

  • メリット



    • メモリ空間が子プロセス毎に独立しているため、スクリプト言語等を組み込みやすい。



  • デメリット


    • メモリ空間が共有できないため、プロセス間のメモリを直接参照できない。





引用 : https://moro-archive.hatenablog.com/entry/2014/09/11/013520


シングルプロセス


  • そのまま、1つのプロセスでのプログラム実行を示す。

  • プロセスは一つなので、平行処理となる


シングルスレッドとマルチスレッド


マルチスレッド


  • 複数のスレッドを並列処理すること

  • つまり、1プロセスの中で各スレッドの並列処理を行うことができるということ。


  • クライアントからの接続毎にスレッドを生成して処理する。

  • メリット



    • メモリ空間が各スレッドの間で共有できる

    • マルチプロセスモデルに比べ、メモリ空間の切り替えがない分、メモリ消費量やコンテキストスイッチのオーバーヘッドが小さくなる。



  • デメリット


    • メモリ空間を共有しているため、他のスレッドに依存する場合がありスクリプト言語等が組み込めない場合もある。





引用 : https://moro-archive.hatenablog.com/entry/2014/09/11/013520


シングルスレッド


  • 並行して複数のプログラム流れが実行されるマルチスレッドと対比して、プログラムの処理の流れが一本のみの状態のこと。

  • 並列処理ではなく、単一の命令の流れを逐次的に実行していく平行処理を指す

  • 1つのプロセスが1つのスレッドしか持っていない場合、この時はスレッド=プロセスとも言える。

  • 例えば、Node.jsではシングルスレッドが適応されており、「ファイルI/Oの非同期」と「イベントループ」によって効率よく処理を行うことを可能にしている。


コンテキストスイッチ

同時接続数分のプロセスやスレッドが必要になり、その数が多くなるとコンテキストスイッチが発生し処理が遅くなる場合がある。


コンテキストスイッチとは、コンピュータの処理装置(CPU)が現在実行している処理の流れ(プロセス、スレッド)を一時停止し、別のものに切り替えて実行を再開すること。



C10K問題


「C」は「Client(クライアント)」、「10K」は「1万台」を表し、(ハードウェアやネットワーク性能に問題がなくても)同時クライアント接続数がある一定数を超えるとサーバがパンクしてしまう問題のこと。



アーキテクチャの種類


preforkとworker


  • MPM(Multi Processing Module)の種類。

  • Webブラウザからのリクエストの処理部分をモジュール化したもののこと。


preforkモデル


  • Apacheのデフォルトアーキテクチャで利用されている。


  • マルチプロセスモデル

  • スレッドを使わず、先行してforkを行なうwebサーバを指す(なので、pre + fork)。


  • リクエストとプロセスが1対1対応で処理する。

  • メリット


    • 子プロセスが何らかの原因で停止しても、他の子プロセスには影響を及ぼすことが無く通信を継続できるため、安定した通信を行える。



  • デメリット


    • 同時接続数(クライアント数)に比例して子プロセスの数も増えるので、使用メモリ量やCPU負荷が比例的に増大していくことになり、C10K問題に繋がる。




workerモデル


  • Apacheのアーキテクチャとして利用可能。


  • マルチプロセスとマルチスレッドのハイブリッド型モデル

  • Apacheの子プロセス1つ1つがマルチスレッドで動作し、スレッド1つが1つのクライアントの処理を担う。


  • リクエストとスレッドが1対1対応で処理する。

  • メリット


    • 多くの子プロセスを起動せずに、メモリの使用量を減らすことができる。



  • デメリット


    • 同時接続数(クライアント数)に比例してスレッドの数も増えるので、使用メモリ量やCPU負荷が比例的に増大していくことになり、C10K問題に繋がる。




イベント駆動モデル


  • Nginxのアーキテクチャで利用されている。

  • イベント駆動型モデルとは、クライアントのアクセスをイベントとして扱い、それをトリガーにプロセス内で処理を行うこと。

  • 1プロセスは1スレッドしか利用しないので、CPUの数だけプロセスを用意するワーカーモデルが利用されている。


    • Node.jsと同様、イベントループ方式(シングルスレッドでループ処理をまわし、キューに溜まったイベントを処理していく処理方式)が利用されている。



  • メリット


    • シングルスレッドのプロセスのためメモリ空間の共有が可能。

    • 同時接続数(クライアント数)が増えても、プロセス数やスレッド数は増えないため、C10K問題を解決できる。


      • そのため、メモリ消費量やコンテキススイッチのオーバーヘッドが小さい。





  • デメリット


    • メモリ空間を共有しているため、他のスレッドに依存する場合がありスクリプト言語等が組み込めない場合もある。




Nginxで用いられるアーキテクチャ


イベント駆動による非同期的なI/Oによるアーキテクチャ

接続ごとにプロセスやスレッドを立ち上げてコンテキストスイッチが起こらないように、Nginxはシングルスレッドで処理を行う。


プロセスの仕組み


マスタープロセス


  • workerプロセスの立ち上げや管理を担い、nginx全体のプロセスを制御する


ワーカープロセス


  • workerと呼ばれるシングルスレッドのプロセスが、それぞれ複数のリクエストを処理する。

  • つまり、1つのworkerプロセスが、複数のリクエストを処理する。

  • ただしワーカプロセス自体はマルチプロセスとして扱うことも可能。各ワーカプロセスはマスタプロセスが受信したシグナルの種類に応じて各ワーカプロセスにもシグナルを送る。

では、シングルスレッドにおける1プロセスでどうやって、多数のクライアントからのアクセスをさばいているのか?

1プロセスで多数のクライアントの接続を処理するためにはマルチプロセス, マルチスレッド, 非同期I/O, I/Oの多重化という方法がある。


I/Oの種類と概要


ブロッキングI/OとノンブロッキングI/O

ブロッキングI/O・・・データ処理が完了するまで待つこと/操作する前に待ちが発生するという性質。

ノンブロッキングI/O・・・データ処理の完了を待たずに他の処理を行うこと/操作する前に待ちが発生しそうなら即座に関数から返るという性質。


同期I/Oと非同期I/O

同期I/O・・・データ処理の入出力が可能になった時点で通知する/操作が終わるまでブロックするという性質。

非同期I/O・・・データ処理の入出力が完了した時点で通知/IO操作を発効したスレッド自体がブロックせずに別のCPU処理を行えるという性質。


I/Oの多重化

2つ以上のI/Oに対して、どれかが入出力可能になった場合の通知をカーネルに依頼する機能。

I/Oの多重化を実現するためのシステムコール「select, poll, epoll, kqueue」と呼ばれるものがあり、これらはそれぞれ以下の処理を行う


  • 一つもしくは複数のディスクリプタを監視

  • ディスクリプタの準備状態(例 : ready(読み書き可能))になるまで待つ

  • 準備が整ったディスクリプタの通知

ファイルディスクリプタ


ファイルディスクリプタとは、プログラムからファイルを操作する際、操作対象のファイルを識別・同定するために割り当てられる番号。OSにアクセスを依頼する際にファイルを指定するのに用いられる整数値である


NginxでのI/O処理では、

(イベントループによる)非同期なイベント駆動と、IOの多重化によって、workerプロセスにてリクエストが完全に処理されることを待たずに処理を捌くことができている。


Nginxはリバースプロキシとしても利用できる


一般的なプロキシ


  • クライアントからプロキシサーバに、任意のWebサーバへのリクエストを行う。


リバースプロキシ


  • Webサーバーの代理の役割を行う。

  • Webサーバーへのリクエストの代理受信や、クライアントへのレスポンスの代理送信ができる。


リバースプロキシのメリット


キャッシュや圧縮による高速化


  • リバースプロキシにてデータのキャッシングや圧縮をすることが可能。

  • 同じページへアクセスがあった時は外部のサーバへアクセスを行わずに済むため、応答性能の向上や通信量の削減になる。


セキュリティの向上


  • IPアドレスでのフィルタリングにより、悪意のあるホストからのリクエストの遮断や特定のIPのみ許可することができる。

  • webサーバは直接インターネットに接する必要がないためリスクが低減する。

  • リバースプロキシ上でファイアウォールなどのセキュリティ対策をすることで、Webサーバに直接手を加えることなく安全性を高めることができる。


SSLの集中管理


  • クライアントとリバースプロキシ間の通信路がSSLで暗号化される場合、リバースプロキシが通信内容を復号することで

  • 通信するWebサーバー自体をそれぞれHTTPSに対応させることなく、通信路を暗号化することが可能。


負荷分散


  • webサーバは複数台で構成され、1台のリバースプロキシサーバから複数のWebサーバにリクエストを振り分け負荷分散が可能。

  • また、リバースプロキシでURLを分解してからURLを変換しWEBサーバーに転送ができ、URLの短縮も行うことができる。


メモリ効率の向上


  • URLから静的コンテンツ/動的コンテンツを各サーバーに振り分けて処理を行うことができ、全体としてメモリ使用効率が上がる。


Apacheとの比較

ApacheとNginxについて比較を参照。


参考文献

Linuxプロセスとカーネル読解のとっかかり

プロセスとスレッド - Linux Kernel

並行処理、並列処理のあれこれ

プロセスとスレッドの違いとは?

イケてるエンジニアになろうシリーズ 〜メモリとプロセスとスレッド編〜

Nginxの仕組みについて入門

preforkとworker

Apache MPMとはなんぞやという話

リバースプロキシって何?触りだけ学んだサーバー/インフラ入門

リバースプロキシ (reverse proxy)とは

プロキシサーバ・リバースプロキシサーバとは?

90秒の動画で学ぶITキーワード:リバースプロキシ

Nginxが早い理由について調べた(基礎)

コンビニでわかるノンブロッキングIO

ノンブロッキングI/Oと非同期I/Oの違いを理解する

非同期I/OやノンブロッキングI/O及びI/Oの多重化について

ファイルディスクリプタ

Apacheコミッターが見た、Apache vs nginx

【Nginx】Nginxについて(概要)

非同期 IO について

非同期とノンブロッキングとあと何か

JavaScriptの非同期処理を並列処理と勘違いしていませんか?