Perl Hackers Hub

第24回 PSGI/Plack実践入門―Starman,Starlet,Twiggy,Plack::Middleware,Server::Starter(2)

この記事を読むのに必要な時間:およそ 4 分

前回の(1)こちらから。

PSGIサーバ

ここまで主にPSGIのアプリケーション側について見てきましたが,(2)ではアプリケーションを実行するためのPSGIサーバについて紹介します。

PSGIサーバの役割

PSGIサーバはPerlによるプログラムで,PSGIアプリケーションとアプリケーションが実行される環境を結び付ける役割をします。

図2がPSGIサーバの役割を図に表したものです。ApachenginxなどのWeb サーバからCGI,FastCGI,HTTPプロトコルを経由してクライアントからのリクエストがPSGIサーバに届きます。PSGIサーバはそれぞれの環境からPSGIのリクエスト情報を集めて$envを作り,PSGIアプリケーションに引き渡して実行します。実行後アプリケーションからレスポンスを受け取り,それぞれの環境に応じてレスポンスを整形して出力します。

図2 PSGIサーバの役割

図2 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サーバを兼ねることがあります。

注1)
Plackサーバとも呼ばれます。
注2)
初期のPlackではPlack::Serverが使われていました。

PSGIサーバの起動方法

Plackハンドラに対応したPSGIサーバはplackupコマンドを使うと簡単に起動できます。リスト2のようにアプリケーションをpsgiファイルに記述して,

$ plackup -a hello_world.psgi

として起動します。デフォルトではHTTP::Server::PSGIが使われ,TCPポート5000番をListenします。ブラウザで http://localhost:5000/にアクセスすると,「Hello WEB+DB PRESS」と表示されます。

リスト2 hello_world.psgi

#!/usr/bin/env perl
use strict;
use warnings;

my $app = sub {
  my $env = shift;
  # アプリケーションの処理
  return [
    200,
    ['Content-Type'=>'text/plain'],
    ["Hello WEB+DB PRESS\n"]
  ];
};

$app;

別のPSGIサーバを起動する場合は,plackup-sオプションを付けます。Starmanを使用する場合は次のようになります。

$ plack -s Starman --port 8080 -a hello_world.psgi

ここでは--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と指定しても動作します。

$ plackup -s Standalone -a helloworld.psgi

HTTP::Server::PSGIは単独でプロセスが1つしかないシングルプロセスのWebサーバとして起動し,使うリソースが少ないことから,アプリケーションの開発時に使われます。プロダクション環境での使用は,シングルプロセスのため同時に複数のリクエストを処理できず,性能も上がらないのでお勧めしません。

Starman──多機能PSGIサーバ

StarmanはNet::Serverモジュールをベースとした多機能なPrefork型のWebサーバです。作者はPSGI/Plackの開発や仕様策定を行っている宮川氏です。

Prefork型とは,図3のようにサーバ起動時にワーカと呼ばれる子プロセスを指定した数だけ起動fork(2)し,複数あるワーカでクライアントからのリクエストに応える方式です。最近では複数のCPUコアを搭載するサーバを利用することが多くなりますが,Prefork型は複数のコアを活かせる構造になっています。

図3 Prefork型サーバの動作

図3 Prefork型サーバの動作

Starman の特徴として,HTTP/1.1,SSLSecure Socket Layerへの対応,HTTPヘッダの処理をXS注3で行うことでの高速動作,UNIXドメインソケットのサポート,Server::Starterを使った無停止デプロイなどが挙げられます。

Starmanはplackupでも起動できますが,付属のstarmanコマンドも使えます。

$ starman --workers 32 \
  --max-requests 500 \
  --preload-app \
  --disable-keepalive \
  -a helloworld.psgi

ここでは32個のワーカを起動し,それぞれ500リクエスト処理したらプロセスが終了して新しいプロセスに入れ替わるように--max-requestsを指定しています。アプリケーションにメモリリークがあっても一定の時間でプロセスを終了させることで,OSのメモリを食い潰すことを防ぎます。

--preload-appを指定すると,親プロセスでアプリケーションをメモリに読み込んでからワーカを起動します。親プロセスとワーカでメモリの一部が共有されるので使用メモリを減らせます。またアプリケーションで使用するモジュールのロードをワーカごとに行わずに済むので負荷の削減にもつながります。

Starmanはクライアントとサーバ間のTCP接続を使い回すHTTP KeepAliveがデフォルトで有効になりますが,Prefork型では接続の維持のためにワーカプロセスを占有するので,TCP接続が多くなると,すべてのワーカが接続の維持に使われ,新たなクライアントからのリクエストを受け付けることができなくなります。プロセスの枯渇を防ぐためPrefork型のサーバを使用する場合にはHTTP KeepAliveを無効にして運用するのが一般的です。Starmanでは--disable-keepaliveを指定します。

注3)
C言語で作られた関数をPerlから呼び出すしくみです。機能の追加や処理の高速化に使われます。

著者プロフィール

長野雅広(ながの まさひろ)

株式会社ミクシィ 開発部システム運用グループ アプリケーション運用チーム所属。mixiのアプリケーション運用に携わっています。Perlのカンファレンス,YAPC::Asia 2008でもmemcachedに関する発表を行いました。

URLhttp://blog.nomadscafe.jp/

コメント

コメントの記入