Webアプリケーション内で処理を直列に実行せずにJob Queueに回して非同期に実行することが多くなって来て久しいと思いますが、そのおすすめ構成と気をつけることについてつらつらと。

1) 既存のデータベースをキューとして使う構成例

jobqueue1.png

1つ目はMySQLなどのデータベースをキューとして用いる例。既にアプリケーションで利用しているデータベースにキュー用のテーブルを作成して利用します。データベースを利用したキュー管理の仕組みとしてJonkQudoTheSchwartzなどがPerlでは有名どころです。 依存するミドルウェアが増えないので最もシンプルな構成になると思います。

上記の図ではWorkerはアプリケーション内で実行することで冗長性を確保しますが、キューを格納するデータベースはSPOFになります。しかし、、データベースに障害があった場合キューだけでなくすべてのサービスが停止すると思われますので、取り上げて問題となることはないでしょう。

性能についてですが、Workerがキューを取得する間隔がどうしても1秒やそれ以上になるので、キューを登録してから実行されるまでのレイテンシが大きく、負荷が大きくなるとキューが滞留してしまうことがあるかもしれません。新規にサービスを開始する際はまず依存が少ないこの構成をとって、キューの数を監視しつつ次のアクションを考えるのがおすすめです

2) 専用のメッセージキューを導入する構成例

jobqueue2.png

2つ目は専用のメッセージキューのミドルウェア(Message Broker)を導入する例になります。よく使われるソフトウェアはActiveMQRabbitMQQ4Mあたりでしょうか。新たなミドルウェアを導入する分、システムが複雑になります。

冗長性を確保するため、これらのミドルウェアは2カ所以上で起動しキューは分散して登録します。分散にあたっては単にランダムやランドロビンでサーバを選ぶのではなく、特定のキー(例えばuser_id)に因ってサーバが一意に決まる剰余による分散やConsistent-Hashingを使うと、問題が起きたときにどのサーバがキューを処理したのか追いやすくなります。Workerの作り方に因ってはキューの処理する順も制御できるかもしれません。このためWorkerはlocalhostのメッセージキューだけを参照します。

jobqueue3.png

サービスが大きくなり、キューが捌けないようになった際には上の図のようにメッセージキューとWorkerをセットにしてサーバを増やしていきます。キューを登録する側にて追加したサーバを使うよう設定をするだけでサーバを増やして行くことができるので運用もわかりやすくなります。

3) Workerを作る際に気をつけること

キューを処理するWorkerはPreforkモデルで作成することをお勧めします。サーバがマルチコアになっているのにアプリケーションがシングルプロセスではあまり意味がありませんし、1プロセスで動作していて、キューの処理に時間が掛かると残りのすべてのキューが遅延してしまいます。この上でSignalをハンドリングして、Workerのgraceful shutdownができるようにしましょう。安全にアプリケーションのアップデートや設定変更を行うのに必須です。PerlではParallel::Preforkを使うと、PreforkしつつSignalを受けWorkerを再起動するデーモンが書きやすくなります。

また、ApacheのMaxRequestPerChildのような、一定数のキューを処理したら子プロセスが終了する仕組みが入っているとメモリを多く確保した場合でも、しばらくすれば解放されるので安心です。

Workerではデータベースへのコネクションなどのリソース管理も重要です。Workerプロセスが長い時間データベースへの接続を維持してしまうことで、データベースの最大接続数を使いきってしまったりリソースを無駄に使ってしまうこともあるので、注意が必要です。「1つのキューを処理 = Webサーバへの1リクエストに対する処理」のように捉えて制御することが重要です。

あ、あとログはちゃんと吐かないとsfujiwaraさんが○○にきます

このブログ記事について

このページは、Masahiro Naganoが2011年6月 6日 15:02に書いたブログ記事です。

ひとつ前のブログ記事は「私家版省サーバ運用2011またはWebシステムのコンポーネントの配置について」です。

次のブログ記事は「Log::Minimal v0.08 でログの色付けサポートなど」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

ウェブページ

OpenID対応しています OpenIDについて
Powered by Movable Type 4.27-ja