きっかけ
研修資料を作成していて、今までの慣例に則ってnginx + アプリケーションサーバーの構成を組んでいるときに
「ALBもCloudFrontもある環境で、なぜnginxが必要なのか?」
という何回かは抱いたことがある疑問にちゃんと向き合ってみようと思って深掘りしてみました。
私のエンジニアとしての初めてのフレームワークはRuby on Rails (7系)でした。
その際に、nginx + pumaの構成がデファクトスタンダードであると学習し、その際にnginxの役割として、SSL終端や、静的ファイルの配信、ロードバランシングを行なっているというふうに学びました。AWSを学習した際には、ALBがSSL終端もロードバランシングもやってくれるし、CloudFrontを前段に追加すれば静的ファイルも配信できることを知りました。「じゃあnginxって何のためにいるんだ」という疑問についてはなんとなく深掘りする余裕もなかったので、今日やっと向き合ってみました。
そもそもサーバーとは何か考えた
Webサーバーもアプリケーションサーバーも、ソフトウェアとしての「サーバー」です。
整理してみると、「サーバー」は特別なものではないことを再認識しました。
- 結局はOS上で動くただのプログラム(プロセス)
- 何かしらの言語によってOSのシステムコールを呼んで、ポートを開いて接続を待ち続け(listenさせ)、リクエストが来たら何か返すアプリケーションを総称してサーバーと呼んでいるにすぎない
内部的にはOSのソケットAPI(socket → bind → listen → accept)を呼んでいるだけです。ブラウザやSlackと同じ「ただのアプリケーション」にすぎないな〜と再認識しました。
Webサーバーとアプリケーションサーバーの違い
この記事のように、どこにあるからどっちのサーバーにカテゴライズできるみたいな話は考慮せず、浅い観点でまとめています。
nginx(Webサーバー):
- やることを極端に絞っている(ファイル配信と転送だけ)
- プログラミング言語(Ruby等)を実行する機能を持たない
- C言語で書かれたイベント駆動。1スレッドで数千接続を管理できる
- 1リクエストあたりマイクロ秒で処理が終わる
- 要するに、簡単な仕事を一瞬で済ますことに特化している
puma(アプリケーションサーバー):
- リクエストごとにアプリケーションコードを実行
- Railsならルーティング → コントローラ → DB → ビュー生成を毎回走らせる
- 1リクエストあたり数十〜数百ミリ秒かかる
- ワーカー数に限りがあり、全部埋まると詰まる
つまり「どちらかが優れている」のではなく、汎用性を捨てて特化しているから速いというトレードオフのようです。
Rubyを動かすことはできないが、HTTPを捌くことだけは圧倒的に得意、みたいな立ち位置であるだけだと再認識しました。
pumaのワーカーは「貴重なリソース」です。1つのリクエストを処理している間、そのワーカーは占有され続けるので、
- CSSや画像を返すだけの処理にpumaを使うのは無駄
- スロークライアント(遅い回線)がいると、レスポンス送信待ちでワーカーが占有されるのでプログラムを動かせないので勿体無い
- nginxがバッファリングすれば、pumaは即座に次のリクエストに移れる
「簡単な作業を速く軽くできる専門サーバー」に単純作業を任せて、アプリケーションサーバーはビジネスロジックに集中させる。これが分業の本質なのだなと理解しました。
クラウド時代での位置づけ
ALB + CloudFrontがある場合、nginxの役割の多くは代替されます:
- SSL終端 → ALB / CloudFront
- ロードバランシング → ALB
- 静的ファイル配信 → CloudFront + S3
- 同時接続管理 → ALB
AIに聞いてみたところ、ECS + Fargate + Node.jsやGoの構成ではnginxを挟まないケースが増えているらしいです(確証は低いけど、、、)
想定していた通り、ALBがスロークライアントのバッファリングもやってくれるので、アプリケーションサーバーが直接ALBからリクエストを受けても問題なさそうです。
ただ、色々調べていくうちにnginxで自分でconfigを書いて制御できる感じはやはりいいものだなと思ったり、静的アセットの提供のために前段にCDN(Cloudfront)を置くことの抵抗感があるなと感じたりしました。個人的な経験から、キャッシュの層が増えると嫌な気持ちになります。
結局はどこに「層」を増やすのか、どこまでマネージドにしたいかみたいな話に帰着するなと感じました。
※ただしRails + pumaの構成では、歴史的経緯とpumaの設計思想から、今でもnginxを前に置くのが主流のようです。
結論
- Webサーバーは「HTTPを捌くことに特化した軽量プログラム」
- 存在意義は「アプリケーションサーバーの貴重なリソースを守る門番的な役割」
- クラウドネイティブ環境ではALBやCloudFrontがその役割を担えるので、nginxは必須ではなくなりつつあるのかもしれない
- ただし構成や言語によっては今でも有用
参考にした記事