前回の(1)はこちらから。
PSGIサーバ
ここまで主にPSGIのアプリケーション側について見てきましたが、(2)ではアプリケーションを実行するためのPSGIサーバについて紹介します。
PSGIサーバの役割
PSGIサーバはPerlによるプログラムで、PSGIアプリケーションとアプリケーションが実行される環境を結び付ける役割をします。
図2がPSGIサーバの役割を図に表したものです。ApacheやnginxなどのWeb サーバからCGI、FastCGI、HTTPプロトコルを経由してクライアントからのリクエストがPSGIサーバに届きます。PSGIサーバはそれぞれの環境からPSGIのリクエスト情報を集めて$env
を作り、PSGIアプリケーションに引き渡して実行します。実行後アプリケーションからレスポンスを受け取り、それぞれの環境に応じてレスポンスを整形して出力します。
PSGIサーバとPlackハンドラ
PSGIサーバはPlackハンドラと呼ばれることがありますが、両者は異なるものを指します。
Plackハンドラ[1]とは、PlackとPSGIサーバとを結び付けるアダプタのインタフェースであり、モジュールの名前空間ではPlack::Handlerを利用します[2]。たとえば、PSGI 対応Web サーバのStarmanでは、Starman::ServerモジュールにPSGIサーバの実装があり、Plack とのアダプタインタフェースはPlack::Handler::Starmanに実装がされています。また、CGI、FastCGI、mod_perlなど既存のWebアプリケーション実行環境があり、独立したPSGIサーバの実装が必要ない場合、Plackハンドラに実行環境との橋渡しを実装してPSGIサーバを兼ねることがあります。
PSGIサーバの起動方法
Plackハンドラに対応したPSGIサーバはplackup
コマンドを使うと簡単に起動できます。リスト2のようにアプリケーションをpsgiファイルに記述して、
として起動します。デフォルトではHTTP::Server::PSGIが使われ、TCPポート5000番をListenします。ブラウザで http://localhost:5000/
にアクセスすると、「Hello WEB+DB PRESS」と表示されます。
別のPSGIサーバを起動する場合は、plackup
に-s
オプションを付けます。Starmanを使用する場合は次のようになります。
ここでは--port
オプションも使い、ListenするTCPポートも変更しています。
よく利用されるPSGIサーバと、その選び方
PSGI/Plackの登場以降、さまざまなWebアプリケーションの実行環境がPSGIに対応したり、新しく作られました。2013年11月現在CPANには40個以上のPlack::Handlerが登録されています。その中から開発やプロダクション環境で利用されるPSGIサーバを紹介します。
HTTP::Server::PSGI
HTTP::Server::PSGIはplackupコマンドのデフォルトで使われるPSGI サーバです。Plack::Hander::StandaloneモジュールがPlack::Hander::HTTP::Server::PSGIのエイリアスとして実装されているので、PlackハンドラをStandaloneと指定しても動作します。
HTTP::Server::PSGIは単独でプロセスが1つしかないシングルプロセスのWebサーバとして起動し、使うリソースが少ないことから、アプリケーションの開発時に使われます。プロダクション環境での使用は、シングルプロセスのため同時に複数のリクエストを処理できず、性能も上がらないのでお勧めしません。
Starman──多機能PSGIサーバ
StarmanはNet::Serverモジュールをベースとした多機能なPrefork型のWebサーバです。作者はPSGI/Plackの開発や仕様策定を行っている宮川氏です。
Prefork型とは、図3のようにサーバ起動時にワーカと呼ばれる子プロセスを指定した数だけ起動(fork(2)
)し、複数あるワーカでクライアントからのリクエストに応える方式です。最近では複数のCPUコアを搭載するサーバを利用することが多くなりますが、Prefork型は複数のコアを活かせる構造になっています。
Starman の特徴として、HTTP/1.1、SSL(Secure Socket Layer)への対応、HTTPヘッダの処理をXS[3]で行うことでの高速動作、UNIXドメインソケットのサポート、Server::Starterを使った無停止デプロイなどが挙げられます。
Starmanはplackup
でも起動できますが、付属のstarman
コマンドも使えます。
ここでは32個のワーカを起動し、それぞれ500リクエスト処理したらプロセスが終了して新しいプロセスに入れ替わるように--max-requests
を指定しています。アプリケーションにメモリリークがあっても一定の時間でプロセスを終了させることで、OSのメモリを食い潰すことを防ぎます。
--preload-app
を指定すると、親プロセスでアプリケーションをメモリに読み込んでからワーカを起動します。親プロセスとワーカでメモリの一部が共有されるので使用メモリを減らせます。またアプリケーションで使用するモジュールのロードをワーカごとに行わずに済むので負荷の削減にもつながります。
Starmanはクライアントとサーバ間のTCP接続を使い回すHTTP KeepAliveがデフォルトで有効になりますが、Prefork型では接続の維持のためにワーカプロセスを占有するので、TCP接続が多くなると、すべてのワーカが接続の維持に使われ、新たなクライアントからのリクエストを受け付けることができなくなります。プロセスの枯渇を防ぐためPrefork型のサーバを使用する場合にはHTTP KeepAliveを無効にして運用するのが一般的です。Starmanでは--disable-keepalive
を指定します。
Starlet──シンプルで高速なPSGIサーバ
Starletは本連載第6回を執筆した奥一穂氏が開発しているPSGI対応のWebサーバです。Prefork型で、Linuxのネットワークプログラミングのテクニックが多数盛り込まれており、高速な動作を実現しています。HTTP::Parser::XS
モジュールを導入するとXSでHTTPヘッダ処理が行われるので、特に理由のない限りインストールしてください。
StarletにはStarmanと異なり専用の起動コマンドが付属しないので、plackup
でサーバを起動します。
Starletの起動オプションで特徴的なのが、--max-reqsper-child
と--min-reqs-per-child
です。Starmanの--max-requests
に相当する機能ですが、ワーカプロセスの入れ替わるタイミングがmaxとminの間のランダムな値に設定されます。Prefork型のWebサーバでは、アクセスが多くなるにつれ、各ワーカが処理したリクエスト数がほぼ同数になり、プロセスの終了と新しいプロセスを起動が同じタイミングに集中します。アクセスの多いサイトではサーバの負荷が上がり、サービスに影響が出ることもあります。そこでStarletではワーカが入れ替わるタイミングにランダム性を持たせるオプションがサポートされています。
Twiggy── AnyEventベースの非同期Webサーバ
Twiggyはイベント駆動ライブラリのAnyEventを利用したWebサーバです。StarmanなどのPrefork型のサーバとは異なり、1個のプロセスで数十~数百の接続を受けることができます。PSGIの遅延レスポンス、ストリーミングレスポンスをサポートしており、サーバプッシュ型アプリケーションに向いているPSGIサーバです。
リスト3はAnyEventを利用して、次のリクエストが来るまでレスポンスを待つPSGIアプリケーションです。
リスト3は次のコマンドで起動します。
curlなどでアクセスすると、レスポンスが途中まで行われたのち次のリクエストを待つ状態に入ります。
別のターミナルから同じcurlコマンドを実行すると「request has come!」と表示され、レスポンスが完了します。このようにTwiggyとPSGIを利用することで、簡単にイベント駆動のアプリケーションも書けます。
Twiggy::Prefork── Prefork対応Twiggy
Twiggy::Preforkは拙作のWebサーバです。その名のとおりTwiggyにPreforkの機能を付加しています。Twiggyはすべての接続を1個のプロセス内で処理するので、クライアント同士の情報のやりとりが行いやすいという特徴があります。しかし、シングルプロセスではCPUコアを複数積んだサーバの処理能力を活かしきれません。
そこで開発をしたのがTwiggy::Preforkです。ワーカプロセスが複数になることで、クライアント同士の情報の交換は難しくなりますが、CPUのパワーを利用してさらに多くの接続を扱えます。
Twiggy::PreforkはStarletと同様に1プロセスが処理するリクエスト数の最大と最小を指定できます。
Feersum──高速非同期サーバ
FeersumはC言語のイベント駆動ライブラリであるlibevをベースに作られているPSGI対応のWebサーバです。C/XSで作られている部分も多く非常に高速に動作します。筆者は残念ながら使ったことはありませんが、Webアプリケーションのチューニングコンテスト「ISUCON」において、このFeersumを使い上位にランキングしたチームがいます。
2013年11月現在、実験的な機能とされていますが、FeersumはPrefork型にも対応しています。
PSGIサーバの選び方
CPANには多くのPSGIサーバがありますが、ほかのミドルウェアに依存せず単独でWebサーバとして動作するPSGI サーバを使うのがお勧めです。HTTP::Server::PSGI、StarmanやStarletなど単独で動作するPSGIサーバは、perlのインタプリタをインストール・管理するソフトウェアであるplenv、本連載Vol.75で紹介されたCartonやcpanmなどを使い、簡単にセットアップできます。またWebサーバとして起動すればブラウザで直接アクセスできるので開発やデバッグも捗ります。
表2にPSGIサーバを選ぶ際の基準をまとめました。非同期処理を必要としないアプリケーションであれば1行目「通常のアプリケーション」を、非同期処理が必要なら2行目「非同期処理が必要なアプリケーション」となります。そして、シングルプロセス内でのデータの共有が必要なら1列目「シングルプロセス」、そうでない場合は2列目「マルチプロセス」を選びます。多くの場合、マルチコアを持つサーバを使いますので、通常のアプリケーションの場合は自動的に右上のサーバになるでしょう。各カラムの中でどのサーバを選ぶべきかですが、実際のアプリケーションにおいてはどれも高速でそれほど差がありません。オプションの指定方法など開発者が慣れたサーバを選ぶのが良いでしょう。筆者の個人的なお勧めは、ホットデプロイ機能やプロセスごとに終了タイミングを変更できる機能を備えたStarletです。
表2 PSGIサーバの選び方
種類 | シングルプロセス | マルチプロセス |
通常のアプリケーション | ─ | Starman Starlet |
非同期処理が必要なアプリケーション | Twiggy Feersum | Twiggy::Prefork Feersum |
<続きの(3)はこちら。>