ApacheとNginxの違いに関する見解

## はじめに
見にきていただき、ありがとうございます。
とある企業所属のn0taです。

今回はWebサーバとして大幅なシェア率を誇る「Apache」と「Nginx」についての見解を書かせていただければと思います。
興味ある方は最後まで見ていただけると幸いです。

**本記事を読むにあたって、1点注意していただきたいことがございます。**
- 本記事は2次情報に該当するため、オフィシャルな情報を知りたい場合は公式リファレンスを参照してください。

また、本記事はn0taのナレッジベースで記載しているので誤った情報があるかと思います。その時はQAなどから指摘いただけますと幸いです。(感想や質問なども歓迎です！)

## 想定読者
初学者の方も分かりやすいように記載する想定ですが、用語だけ使って説明することも多くあります。
そのため、分からない用語が出てきた場合は各自で調べていただけますと幸いです。
※ITのエンジニアは分からない用語が無限に出てくるので、調べる力も養っていけると後々楽にお仕事できるようになると思います。

## 経緯
なぜ本記事を作ることになったかというと、n0taが企業に所属してお仕事をしていくなかで、「Webサーバの技術選定ってどのように行われるのだろう」という疑問が始まりでした。

したがって、本記事では「このアプリケーションにはApache(Nginx)」という技術選定時に活用できる記事を意識して記載しています。(実際活用できるかは不明)

## Webサーバとは
Webサーバに関する定義としては下記となります。[1]
>ソフトウェアの観点では、ウェブサーバーとは、ホストにあるファイルに対する、ウェブユーザーのアクセスを制御する、いくつかの部品の集まりです。最小限の部品は HTTP サーバーです。HTTP サーバーは URL （ウェブアドレス）および HTTP （ブラウザーがウェブページを閲覧するためのプロトコル）を理解するソフトウェアのことです。格納しているウェブサイトのドメイン名（mozilla.org など）を通してアクセスすることができ、コンテンツをエンドユーザーの端末に配信します。

上記を噛み砕くと、「クライアントからリクエストを受け取るもの」ぐらいの認識で良いと思います。(凄く適当で申し訳ない...)

続いてはWebサーバとして業界で広くシェアされている「Apache」と「Nginx」について簡潔に紹介していきます。

## Apacheとは
Apache HTTP Serverの特徴は下記が挙げられます。
- 業界で長く利用されているWebサーバの1つ(レガシーなシステムはApacheであることが多い)
- プログラミング言語である「PHP」と相性がよい
    - 下記の構成が広く利用されている(OS, Webサーバ, DBMS, プログラミング言語の並び)
    - LAMP(Linux, Apache, MySQL, PHP)
    - LAPP(Linux, Apache, PostgreSQL, PHP)
- ディレクトリごとに設定が容易に変えられる

## Nginxとは
Nginxの特徴は下記が挙げられます。
- 高速・軽量・非同期のWebサーバ
    - シングルスレッドで処理
- 機能性が高い
    - ロードバランシングやキャッシュなども完備

ここからは技術的に深い内容に入っていきます。
※分からない用語が出てきた場合は各自で調べていただけますと幸いです。

## ApacheとNginxのリクエストの処理方法
ApacheとNginxではリクエストの処理方法が異なります。
各処理方法を理解することで、技術選定時の判断材料となるはずです。

### Apacheのリクエスト処理方法
Apacheの処理方法について名称があり、それが**MCP(Multi-Processing Module)** と呼ばれるものとなります。
MCPの種類としては下記の3つとなります。
1. Prefork
1. Worker
1. Event
順々に説明していきます。

#### Preforkについて
Preforkの特徴としては下記となります。
- 1リクエスト1プロセスで処理を行う
- プロセスはシングルスレッドで動作する
    - そのためスレッドセーフではないものと相性がよい

```Preforkのイメージ
[親プロセス] <- 子プロセスの管理などを行う
     |
     |--- 子プロセス(Process 1) -> 1つのリクエストを処理(Request 1)
     |--- 子プロセス(Process 2) -> 1つのリクエストを処理(Request 2)
     |--- 子プロセス(Process 3) -> 1つのリクエストを処理(Request 3)
```

上記の仕組みとなっているため、**リクエストが増えていくとプロセス数が増加し、メモリ消費量が大きくなってしまう** というデメリットがあります。
しかし、**各子プロセスは独立(シングルスレッド)なため安全性が高い** というメリットもあります。

#### Workerについて
Workerの特徴としては下記となります。
- 1リクエストをプロセス内の1スレッドで処理を行う
- プロセスとスレッドの関係は1対多の関係
- Preforkと比べてメモリ消費量が低くなっている

```Workerのイメージ
[親プロセス] <- 子プロセスの管理などを行う
     |
     |--- 子プロセス(Process 1) 
     |           |--- スレッド(Thread 1) -> 1つのリクエストを処理(Request 1)
     |           |--- スレッド(Thread 2) -> 1つのリクエストを処理(Request 2)
     |           |--- スレッド(Thread 3) -> 1つのリクエストを処理(Request 3)
     |--- 子プロセス(Process 2)
     |           |・・・
     |・・・
```

上記の仕組みとなっているため、**スレッドセーフなプログラムを意識しなければいけない** というデメリットがあります。
しかし、**Preforkと比べて同時接続数に強いことやメモリ消費量が抑えられる** というメリットもあります。

#### Eventについて
Eventの特徴としては下記となります。
- keep-alive接続のためにスレッドを専有しない（スレッドの効率的な再利用）
- 1リクエストをスレッドで処理する点はWorkerと同様
- イベント駆動で接続の監視や処理を効率化
- 高負荷環境に強く、近年のApacheのデフォルト設定

```Eventのイメージ
[親プロセス] <- 子プロセスの管理などを行う
     |
     |--- 子プロセス(Process 1)
     |           |--- スレッド(Thread 1) -> リクエストを処理(Request 1)
     |           |--- スレッド(Thread 2) -> リクエストを処理(Request 2)
     |           |--- イベントループスレッド -> keep-alive接続の監視・管理
     |--- 子プロセス(Process 2)
     |           |・・・
     |・・・
```

keep-alive状態の接続を別スレッド（イベントループ）で監視する仕組みになっているため、**リクエスト処理専用のスレッドを効率的に利用できる** というメリットがあります。
また、**Workerよりもさらに多くの同時接続に対応可能で、長時間接続を伴うHTTP通信に適しています。**
しかし、**Workerと同様にスレッドセーフなプログラムを意識しなければならない** ことは変わりないです。

### Nginxのリクエスト処理方法
Nginxの特徴としては下記となります。
- 多数のリクエストを1プロセスで非同期に処理を行う(スレッドは未使用)
    - スレッドに関する考慮が不要
    - シングルスレッドで動作
- CPUのコア数に応じて子プロセス(Workerプロセス)を作成する
    - 1プロセス10000コネクションほど行える想定(正確な数値は調査不足です...)
- イベント駆動かつノンブロッキングI/Oで処理を行う

```Nginxのイメージ
[親プロセス(Master Process)] <- 子プロセス(Workerプロセス)の起動・監視を行う
     |
     |--- 子プロセス(Worker Process 1) 
     |         |--- イベントループ -> 多数のリクエストを非同期に処理
     |--- 子プロセス(Worker Process 2)
     |         |・・・
     |・・・
```

各子プロセスはシングルスレッドで動作し、ノンブロッキングI/Oにより複数のリクエストを効率的に処理します。
そのため、**1プロセス1スレッドで大量同時接続に対応できるという特長があり、
メモリ消費量が低く高いスケーラビリティが実現できる** というメリットがあります。
また、**シングルスレッドのためスレッドセーフを考慮する必要がない** というメリットもあります。

## 各処理方法のユースケース(著者の独断と偏見)
ApacheとNginxのリクエスト処理方法が分かったところで、各処理方法のユースケースを述べていこうと思います。

### Apache Preforkのユースケース
- リクエストが極端に少ない(クライアントが限定的なシステム)
- スレッドセーフが考慮されていないモジュールを使うとき

### Apache Worker, Apache Eventのユースケース
- 比較的リクエストが多いシステム(一般的に公開されるシステム)
- ディレクトリごとに詳細な設定を行いたい場合
- スレッドセーフが考慮されている場合

### Nginxのユースケース
- リクエストが多いシステム
- スループットを意識しなければならない場合
- スレッドが考慮されていない場合でも利用可能

## おわりに
今回はWebサーバとして認知度の高い「Apache」と「Nginx」に重きを置いて、記事を書かせていただきました。
記事を書いてみて思ったことは、「文章を書く能力が低すぎる」と痛感しました...
よい経験になったと思うので、これを機にqiitaなどのブログサイトでアウトプットを出すことによって鍛えていければと思います。

今回の記事に関して **「認識の違い(筆者の認識ミス)」や「疑問点」などがございましたら遠慮なくコメントしてください！** 
私自身も色々な方の意見を聞くことができるよい機会だと思いますので、相互に勉強できればと思います。(Apacheのプロフェッショナルの方からミスを指摘されたい...)
また、よければハートください。(モチベーションに繋がります...)

これからも幅広い分野で勉強したことをシェアさせていただければと思います。
困ったらNginxを使おう！！！
読んでいただき、ありがとうございました！

## 追伸
最初に初学者にも分かるように記載すると言ってましたが、難しかったです...
申し訳ございません...

## 参考文献
[1] https://developer.mozilla.org/ja/docs/Learn_web_development/Howto/Web_mechanics/What_is_a_web_server
・https://httpd.apache.org
・https://httpd.apache.org/docs/current/mod/prefork.html
・https://httpd.apache.org/docs/current/mod/worker.html
・https://httpd.apache.org/docs/current/mod/event.html
・https://nginx.org