Rails開発におけるwebサーバーとアプリケーションサーバーの違い(翻訳)

More than 1 year has passed since last update.

はじめに

先日スタック・オーバーフローでこんな質問に回答しました。

webサーバー、アプリケーションサーバー、Rackといった仕様や概念と、WEBrick、Unicorn、Pumaといった実装の関係が頭の中で結びつきません

質問者の方はwebサーバー、アプリケーションサーバー、Rack、Unicorn、Pumaと言った用語や概念の理解がこんがらかっているように見えたので、このあたりをきれいに説明している記事を探していたところ、以下の記事を見つけました。

A web server vs. an app server - Justin Weiss

スタック・オーバーフローでは記事の一部を抜粋して「ざっくり翻訳」したのですが、それだけで終わらせるのはもったいない気がしたので、Qiitaには全文を翻訳して載せておこうと思います。

これを読むと、あなたもwebサーバーとアプリケーションサーバーの違いや、UnicornやPuma、Rackが何なのかがはっきり理解できるかもしれません。
僕も理解があやふやなところがあったので、翻訳してみてスッキリしました。

翻訳の方針について

翻訳は日本語としての読みやすさを重視してところどころ意訳しています。
もし完全に間違った訳になっていたり、意訳しすぎて原文のニュアンスが変わってしまったりしているところがあれば、コメントや編集リクエスト等でやさしく指摘してやってください。

webサーバーとアプリケーションサーバーの違い(翻訳)

A web server vs. an app server - Justin Weiss(元記事)

Railsアプリケーションのデプロイ方法を調べていると、いろんな名前を目にすると思います。たとえば、ApacheやUnicorn、Puma、Phusion Passenger、Nginx、Rainbowsなどなどです。こうした名前はどれも「Railsのデプロイ」というカテゴリに関連してそうですが、重要な違いが一つだけあります。一方は「webサーバー」で、もう一方は「アプリケーションサーバー」です。

どれがどのカテゴリに関連し、そのカテゴリがシステムにどう関連するかを理解できれば、自分がデプロイで何をしているのか、ちゃんとわかるようになります。 とはいえ、この二つのカテゴリの違いはちょっとわかりづらいです。

webサーバーとは何で、アプリケーションサーバーとはどう違うのでしょうか?一方だけを使い、もう一方を使わない、ということはできるのでしょうか?そしてRackはどう関連しているのでしょうか?

webサーバーとは?

webサーバーはユーザーから送られてきた自サイトへのリクエストを受け取り、なんらかの処理を加えるプログラムです。そして、場合によってはあなたのRailsアプリケーションにリクエストを投げます。 NginxとApacheは最も有名なwebサーバーです。

CSSやJavaScript、画像など、頻繁に変化しないファイルへのリクエストであれば、Railsアプリケーションはそのリクエストを処理する必要がないかもしれません。webサーバーはRailsアプリケーションに処理を移譲することなく、そのリクエストを自分で処理できます。また、そうした方が通常は速く完了します。

webサーバーはSSLリクエストや静的なファイルやアセット、圧縮されたリクエスト等を処理したり、その他大半のwebサイトが必要としそうな数多くの処理をこなしたりすることができます。そしてもし、あなたのRailsアプリケーションがリクエストを処理しなければならない場合は、webサーバーはリクエストをアプリケーションサーバーにパスします。

アプリケーションサーバーとは?

アプリケーションサーバーはあなたのRailsアプリケーションを動かしているものです。 アプリケーションサーバーはあなたのコードを読み込み、アプリケーションをメモリに保持します。アプリケーションサーバーはwebサーバーからリクエストを受け取ると、Railsアプリケーションにそのことを知らせます。アプリケーションがリクエストを処理すると、アプリケーションサーバーはそのレスポンスをwebサーバーに返します。(そのレスポンスは最終的にユーザーへ届きます。)

大半のアプリケーションサーバーはwebサーバーを使わずに単体で実行できます。これはあなたがdevelopmentモードでやっていることです! しかしproduction環境ではwebサーバーを手前に置くことが多いはずです。 webサーバーは複数のアプリケーションを一度に処理したり、アセットを素早くレンダリングしたり、リクエストごとに発生する多くの処理をさばいたりしてくれます。

Rails用のアプリケーションサーバーは山ほどあります。たとえば、Mongrel(ただし最近はほとんど使われていない)、Unicorn、Thin、Rainbows、Pumaなどです。それぞれに異なる長所があり、異なる設計思想を持っています。とはいえ、みんなやっていることは一緒です。つまり、どのアプリケーションサーバーもあなたのRailsアプリケーションを動かし、リクエストを処理し続けています。

Passengerの場合は?

Phusion Passengerはちょっと変わっています。「スタンドアローンモード」ではアプリケーションサーバーのように動作します。 しかし、webサーバーに組み込むこともできます。その場合、Railsアプリケーションを動作させるためにアプリケーションサーバーを別に用意する必要はありません。

この機能はとても便利な場合があります。特に、大量のアプリケーションを実行し、ひとつずつアプリケーションサーバーをセットアップするのが面倒な場合に便利です。Passengerをインストールしたら、webサーバーを(アプリケーションサーバーでなく)直接Railsアプリケーションに接続しましょう。これでRailsアプリケーションはリクエストを処理できるようになります!

このように、Passengerはとても便利な選択肢です。とはいえ、アプリケーションサーバーは独立して用意する方が良いでしょう。 アプリケーションサーバーを独立して用意しておくと、要件に最も適したアプリケーションサーバーを自由に選択できますし、アプリケーションサーバーだけを個別に実行したりスケールしたりすることもできます。ですが、私は小規模な新しいアプリケーションを今度デプロイするときに、もう一度Passengerを使ってみようと思います。Passengerを使うことで、この先も同じサーバーに新しいアプリケーションをデプロイしやすくなることを期待しています。

Rackとは?

Rackは魔法です。Rackを使えばどのアプリケーションサーバーであってもあなたのRailsアプリケーションを動かすことができます。(Railsに限らず、SinatraやPadrinoであっても同じです)

RackはRailsのようなRuby製のwebフレームワークとアプリケーションサーバーの両方が話せる共通言語のようなものだと考えてください。両者が共通言語を理解できるので、RailsはUnicornと話せますし、UnicronはRailsと話せます。しかも、RailsもUnicornも相手のことを知っておく必要は全くありません。

webサーバーとアプリケーションサーバーはどういう関係なのか?

それでは、この話を全部まとめるとどうなるでしょうか?

まず、webリクエストはwebサーバーが受け取ります。そのリクエストがRailsで処理できるものであれば、webサーバーはリクエストに簡単な処理を加えてアプリケーションサーバーに渡します。アプリケーションサーバーはRackを使ってRailsアプリケーションに話しかけます。Railsアプリケーションがリクエストの処理を終えると、Railsはレスポンスをアプリケーションサーバーに返します。そして、webサーバーはあなたのアプリケーションを使っているユーザーにレスポンスを返します。

もっと具体的に言えば、NginxはリクエストをUnicornに渡します。UnicornはリクエストをRackに渡します。RackはリクエストをRailsのrouterに渡します。routerはリクエストを適切なcontrollerに渡します。そしてレスポンスが逆の順番で返されます。


以上のような説明はちょっと単純化しすぎているかもしれません。 しかし、このような二つのカテゴリを知っておくだけで、自分が使おうとしているソフトウェアのことを正しく理解しやすくなるはずです。

アプリケーションサーバーとwebサーバーがどのように関連するかを理解できれば、サーバーに問題が起きてもずっと簡単にデバッグすることができます。調べ物をするときも、役割の違いやそれぞれの要素がお互いにどうやって協調するのかがわかるはずです。さらに、新しくて面白そうなアプリケーションサーバーが登場したときも、きっとすぐに試してみることができるでしょう!

(翻訳おわり)

あわせて読みたい

元記事を書かれたJustinさんはいつも良質なRails関係のノウハウを提供してくれています。
説明もわかりやすく丁寧ですし、Rails開発者なら知っておいて損はない情報ばかりをピックアップしてくれます。
みなさんも(英語の勉強をかねて)ぜひチェックしてみてください。

http://www.justinweiss.com/

ちなみに、以前書いたこちらの記事でもJustinさんのブログを紹介しています。

Rubyの最新情報をキャッチ!僕が購読しているメルマガとRSSフィード5選 - Qiita