Skip to content
iwhurtafly edited this page Nov 21, 2012 · 7 revisions

Unixのプロセスモデルとは、サーバーサイドのプログラムを実行するためのシンプルでパワフルな抽象化と言えます。プロセスモデルをwebアプリケーションに当てはめてみると、ワークロードを分散し、時間が掛かる処理のスケールアップを考える際に、ユニークな方法を提供してくれます。HerokuのCedar stackにおいても、webやworker、またはその他全種類のプロセスへプロセスモデルを使用しています。

基礎

プロセスモデルの基礎を学ぶのに、シンプルな実例を使って始めてみましょう。Unix界隈で良く知られたmemcachedというデーモンを使ってみます。

ダウンロードし、コンパイルして下さい。:

:::term
$ wget http://memcached.googlecode.com/files/memcached-1.4.5.tar.gz
$ tar xzf memcached-1.4.5.tar.gz 
$ cd memcached-1.4.5
$ ./configure
$ make

プログラムを実行して下さい。:

:::term
$ ./memcached -vv
...
<17 server listening (auto-negotiate)
<18 send buffer was 9216, now 3728270

この実行されたプログラムが プロセスと呼ばれます。

ローカルの開発環境では、ターミナル上での手動実行で問題無しですが、Heroku上では、本番環境のデプロイ時、memcachedが **managed(管理された)**プロセスとなっていることを期待しています。managedプロセスは、OSの起動時、自動的に実行されるべきです。また、いかなる理由にせよ、プロセスがクラッシュしたり、強制終了した場合は、再起動されるべきです。

一般的なサーバーベースのデプロイでは、OSが プロセスマネージャーを提供します。OS Xでは、launchdがビルトインされています。Ubuntuでは、Upstartがビルトインされています。Herokuでは、dyno manifoldが各サービス毎に分散されたプロセスマネージャを提供します。

ここまでで、プロセスモデルのベースラインを構築することが出来ました。この仕組みをより新しいやり方へ動作するよう組み入れてみましょう。:webアプリケーションへの実装です。

Unixのプロセスモデルをwebアプリケーションへマッピングする

memcachedのようなサーバーのデーモンは、単一のエントリーポイントを管理しています。要するに、デーモンを呼び出すのに1つだけのコマンドが存在することとなります。一方で、webアプリケーションでは、2つ以上のエントリーポイントが存在することが常です。これらのエントリーポイントを プロセスタイプと呼んでいます。

基本的なRailsのアプリケーションでは、2つのプロセスタイプを管理することとなるでしょう。:1つは、Rack互換のwebプロセス(Webrick、 Mongrel、 Thinと言った)、そして2つ目は、キューイングライブラリ(Delayed JobやResqueと言った)を使用するworkerプロセスです。例を挙げます。:

プロセスタイプ コマンド
web bundle exec rails server
worker bundle exec rake jobs:work

基本的なDjangoのアプリケーションもRailsと驚くほど似ています。: webプロセスは、manage.pyの管理ツールで実行されます。そしてバックグラウンドジョブは、Celeryを経由して実行されます。

プロセスタイプ コマンド
web python manage.py runserver
worker celeryd --loglevel=INFO

プロセスタイプは、それぞれのアプリケーション毎に異なります。例えば、Delayed Jobの替わりにResqueを使用するアプリケーションもあるでしょうし、複数のworkerを管理するアプリケーションもあるでしょう。それぞれのアプリケーション毎に使用しているプロセスタイプを宣言する必要があるのです。

Procfileは、プロセスタイプを宣言するためのフォーマットを提供します。そして、Foremanは、これらのプロセスを開発環境で実行することを簡単にしてくれるツールです。詳細は、Procfileのドキュメントを読んで下さい。

プロセスタイプ 対 プロセス

スケールアップするためには、プロセスタイプとプロセスの関連性について、しっかりと把握しておきたいでしょう。

プロセスタイプとは、1つ以上の プロセスがインスタンスを生成する際、元となるプロトタイプのことです。このことは、オブジェクト指向のプログラミング言語において、1つ以上の オブジェクトのインスタンスを生成する際、 クラスがプロトタイプとなることと似ています。

プロセス(縦軸)とプロセスタイプ(横軸)の関係が視覚的に分かるものを提示します。:

縦軸上にあるプロセスは、 スケールとなります。プロセスタイプによりハンドルされるworkへ並列処理数をスケールアップする必要がある場合、この値を増やします。Herokuで、これを行うには、scaleコマンドを実行します。:

:::term
$ heroku ps:scale web=2 worker=4 clock=1
Scaling web processes... done, now running 2
Scaling worker processes... done, now running 4
Scaling clock processes... done, now running 1

横軸上にあるプロセスタイプは、 ワークロードの種類となります。それぞれのプロセスタイプが、ある特定のworkにおいて専従することとなります。

例えば、あるアプリケーションが2つのworkerを管理していた場合、1つは緊急を要するジョブで、もう1つは長時間の実行を要するジョブだったとします。ジョブを専門のworkerへ細分化することにより、緊急を要するジョブには、より早いレスポンスを得ることが出来ますし、計算で使用するリソースをどのように使うかをより細かくコントロールすることが可能となります。キューイングシステムは、workerプロセスへジョブを分配するのに使われます。

プロセスのスケジュール化

cronと非常に似ていますが、ある特定の日付または時間間隔でworkをスケジュール化することは、Heroku Schedulerのようなアドオン、または特別なジョブスケジューリングのプロセスタイプを使うことで実現可能です。

1度限りのアドミンプロセス

heroku ps:scaleコマンドを経由してdyno manifold上で実行されるプロセス群は、プロセスの編成として知られています。- 例:web=2 worker=4 clock=1 継続的に実行されるこれらのプロセスに加えて、プロセスモデルは、データベースのマイグレーションやコンソールのセッションと言った管理者権限のタスクをハンドルする1度限りのプロセスを実行することも許可しています。

1度限りのアドミンプロセスに関しては、こちらをお読み下さい。

ストリームをログとしてアウトプットする

プロセスモデル配下で実行される全てのプロセスは、ログをSTDOUTへ送るべきです。ローカル上では、プロセスのアウトプットストリームは、Foremanによりターミナルの画面に表示されます。Heroku上では、heroku logsコマンドで簡単にログの参照が可能なLogplexを使い、dyno manifoldを経由して実行されるプロセスからのアウトプットストリームを収集します。

Clone this wiki locally