Reverse Proxy がなぜ必要か

フロントエンジニアに知ってもらいたいリバースプロキシの重要性 | RickyNews この記事が目に入って読んでみた。なるほど、昨今は Reverse Proxy は便利な L7 ルーター的なものとして認識されているのだな、と思った。URL の Rewrite や、VirtualHost 云々。確かに Reverse Proxy の便利な側面ではある一方、それらは Nginx などの Reverse Proxy でなければ実装が不可能かと言えばそんなことはないものでもある。

自分は Reverse Proxy はもうすこしサーバー/インフラ的な側面でその役割を捉えている。今更何をというものでもあるが、昼休みがてら時間があるので簡単に書いてみよう。

Reverse Proxy はWebシステム全体のリソース最適化のためのパーツ

Reverse Proxy のインフラ的な視点での役割は「Webシステム全体の系におけるリソース全体最適のための部品」である。なんのこっちゃ・・・ごめん、石投げないで。

改めて Reverse Proxy は

としたときに

  • フロントエンドで裁けるものはフロントエンドで
  • バックエンドでなければ処理できないものだけバックエンドで処理する

ようにし「全体のリソース効率を上げましょう」というためのものである。

マルチプロセスモデルと並行処理性能

最近はいろいろな実装があるので一概には言えないのだが、Webアプリケーションによるバックエンドのアプリケーションサーバーでは、特にスクリプト言語においては、それはマルチプロセスモデルを採用していることがほとんどだ。マルチプロセスモデルでは、1リクエストを1プロセスが担当することになる。従って、1システムで20プロセスが起動していたとすると同時に処理できる並行処理数は最大で20リクエストということになる。

ご存知のようにアプリケーションサーバーはメモリを大量に消費する。メモリ使用量という文脈で「重い」と言える。そのため、32GB とかどんなに潤沢にメモリが確保できる状況でも、せいぜい最大プロセス数は、すなわち並行処理性能は 50 とか 100 とかそのぐらいである。

Web システムが応答しなければいけないのは、例えば /login に来た1リクエストに対してその画面が含む画像、JavaScript、CSS その他大量のアセットを含む。Reverse Proxy を導入していないシステムではこれらのすべてにアプリケーションサーバーが応答しなければならない。ここが問題。本来アプリケーションサーバーは、動的なリクエストを処理するために用意されているものであるにも関わらず、動的でないコンテンツにまで応答しなければならない・・・というので、先にみたように貴重なアプリケーションサーバープロセスが、どうでもいい静的ファイルのリクエストなどにも消費されてしまう、のである。

Reverse Proxy で得意なものは得意な人が応答するようにする

そこで Reverse Proxy を入れて、(ネットワーク的に) アプリケーションサーバーの手前に配置する。そして静的ファイルなど、アプリケーションサーバーを介さずに応答できるものは Reverse Proxy が直接クライアントに応答し、アプリケーションサーバーでなければ応答できないリクエストのみアプリケーションサーバーに転送する。

Reverse Proxy は、(アプリケーションサーバーがマルチプロセスモデルであるのと対照的に) 昨今の場合 Nginx のようにシングルプロセス・イベントドリブンなアーキテクチャの実装のものを用いる。このアーキテクチャは、どんなに大量のリクエストが来てもプロセス数は増やさずにコンテキストスイッチングのみ (CPU 的な意味のコンテキストスイッチングではなく、イベントの意味での。具体的には select や epoll に類するシステムコール) で並行処理性能を稼ぐところが利点。そのためメモリ使用量の文脈では「軽い」。

この「重い」アプリケーションサーバーと「軽い」Reverse Proxy を組み合わせてそれぞれ自分が得意なものだけ担当することで、システム全体の系でみたときにリソース効率を全体最適させましょう・・・というのがインフラ視点で Reverse Proxy を導入したい一番の理由である。

Reverse Proxy はネットワーク的に遅いクライアントや、KeepAlive リクエスト、あるいは大きなファイルをアップロードしてくるクライアントなど「あまり仕事はしないけどネットワーク接続の維持は要求される」されるような側面でも役に立つ。それらは Reverse Proxy 側で処理しておき、アプリケーションサーバーには本当に必要なときだけにしかリクエストを転送しない・・・ たとえば遅いクライアントのHTTPリクエストがすべて着信してから転送、KeepAlive はフロントだけ有効にしておきバックエンドは応答が終わったらそく切断、アップロードファイルは終わるまでフロント側でバッファリング・・・などである。

この役割分担が、更に得意なものは得意なところで、というリソース全体最適化に寄与する。

四方山

この辺が Reverse Proxy に求められる役割の主軸で、L7 的な便利機能・・・ URL の Rewrite とかフロントエンド側でのアクセス制御というのはあくまで副次的な要素に過ぎない・・・というのがインフラ視点での認識ではある。まあ、フロントエンドエンジニアリングからしたらその視点が逆転する、というのはわからなくもない。

ちなみに最近は Amazon の CloudFront など CDN を比較的カジュアルに使えるようになったので、静的ファイルの配信に関しては CDN だけで賄ってしまうという力業を使う例も増えてる気もする。個人的には、その副次的な用途の魅力も大きいので、CDN に使うにしても Rerverse Proxy あったほうがいいよとは思うけど。

・・・書いてるうちにだんだんドヤ顔になってきてしまった。すみません。自分の知識がある程度正しいという思い込みを前提に、きちんとこの辺の背景事情を続く世代に継承していけたらとも思うところです。

ちなみに、この辺は『サーバー/インフラを支える技術』という(とっても)素晴らしい本に詳しく書かれているのでこちらを読むと良いと思う。