ニフクラ ブログ

ニフクラ/FJcloud-Vやクラウドの技術について、エンジニアが語るブログです。

ニフティクラウドMessageQueueを使ってみました

はじめに

昨年12月になりますが、ニフティクラウドエンジニアリングパーツというサービスがリリースされました。
今回リリースされたエンジニアリングパーツは全部で4つあります。

それぞれアプリ開発に必要なパーツ・機能を提供しています。

今回はその中の1つ、キューイングサービスであるニフティクラウドMessageQueueを使って簡単な分散処理を実装する方法をレポートしてみたいと思います。

ニフティクラウドMessageQueueとは

Amazon Simple Queue Service に互換したキューイングサービスです。
おもな登場人物は「キュー」と「メッセージ」だけで非常にシンプルなサービスとなっています。
シンプルなサービスですがニフティクラウドMessageQueueを使うことで非同期処理や分散処理、ジョブパイプラインといった複雑な処理を簡単に実現することができるようになります。

主な機能

  • メッセージの送受信
    • ニフティクラウドMessageQueueの基本機能です。
    • メッセージの最大サイズは1メッセージあたり256KBまでとなっています。
  • FIFO(First In First Out)
    • 先に送信されたメッセージから順番に受信されるという概念です。
    • パイプライン処理のように順序を制御しなければならない場合に役に立ちます。
  • ロングポーリング
    • メッセージの受信を指定した時間待つことができます。
    • メッセージが存在するかを複数回リクエストよりも、1回のリクエストでメッセージの受信待たせることにより、リクエスト回数を抑えることができます。

他にもVisibilityTimeout(不可視時間)やDelaySeconds(遅延キュー)といった機能がございます。
詳細は公式ドキュメントをご覧ください。

ニフティクラウドMessageQueueを使うメリット

世の中にはたくさんのキューイングサービスがあります。
リレーショナルデータベースであるMySQLを使ったキューイングの仕組みQ4Mや有名なミドルウェアでRabbitMQといったキューイングツールもあります。
ここでは、これらのキューイングツールと比較してニフティクラウドMessageQueueを使った場合のメリットをご紹介します。

構築コストの削減ができる

キューイングする仕組みを独自で実装するときに、ほぼ必須になるのがキューサーバの構築です。
キューサーバを0から構築する場合の流れは、ざっと以下のような手順になるかと思います。

  1. サーバの調達(クラウドサービス or オンプレでのサーバ調達 etc)
  2. サーバの設定(ACL、ネッワーク、ディスク追加 etc)
  3. ミドルウェアの選定
  4. ミドルウェアのインストールおよび設定
  5. テストの実施(キューの作成やメッセージの送受信等最低限のテスト)

クラウドサービスを利用し、普段こういった作業に慣れていらっしゃるエンジニアであれば、それほど大変ではないかもしれませんが、それでも2, 3日は構築に時間を費やすかと思います。
ニフティクラウドMessageQueueを利用すれば上記のような構築作業が不要なのはもちろんのこと、必要なミドルウェアのインストールや設定、チューニングもすべて不要となります。
代わりに必要となるのはニフティクラウドを利用するためのアカウント取得程度です。

運用コストの削減ができる

サーバ構築したあとはそのサーバを運用するコストも、もちろん発生いたします。
キューサーバが障害となった場合は障害復旧作業をする他、キャパシティプランニングや監視作業等、日々の運用作業も発生することになります。
ニフティクラウドMessageQueueを利用すればこれらの運用コストもすべて0とすることができます。
キューサーバの監視、運用はニフティ側で実施してくれるため、ニフティクラウドMessageQueueを利用しているお客様はキューを利用するアプリの実装だけを考えればよくなります。

簡単に利用できる

ニフティクラウドMessageQueueを利用する方法は大きく以下の2つあります。

  1. コントロールパネル
  2. API

ニフティクラウドを利用できるアカウントさえあればキューの作成はコントロールパネルから簡単に行えます。
作成したキューの利用状況の確認もモニタリング機能を提供しているためコントロールパネルから確認することができます。
コントロールパネルの操作方法に関しては公式ドキュメントのコントロールパネルヘルプをご覧ください。
また、キュー内のメッセージの送受信に関しては基本的にプラグラム上から操作されることになるかと思いますので開発用のSDKを2種類(for Java, for PHP)用意しております。

キューイングに特化した様々な機能を使うことができる

ニフティクラウドMessageQueueではデフォルトで以下の機能も提供しています。

  • 遅延キュー
    • 送信したメッセージを指定した時間遅らせてキューイングすることが出来る機能
  • バッチ処理
    • 複数のメッセージを1度のリクエストで処理する機能
  • 不可視時間
    • メッセージ受信後、指定した時間同じメッセージを受信不可な状態にする機能
  • ロングポーリング
    • メッセージが空である場合、メッセージの受信を指定した時間待つことができる機能

基本的なメッセージの送受信の他にもキューイングに特化した便利な機能を提供しております。
これらの機能は一般的なキューイングツールに標準で備わっていることは少なく独自で実装または機能追加する必要があります。
ニフティクラウドMessageQueueでは上記の機能をデフォルトで提供しているため、利用者はキューを作成した直後から上記の機能を使って複雑なキューイング処理を行うことが可能です。

ニフティクラウドMessageQueueを使って分散処理を実装してみる

ここまで紹介させていただいた上で、実際にニフティクラウドMessageQueueを利用した簡単なシステムを構築してみたのでご紹介いたします。
今回は1つのキューに対して複数のクライアント(worker)からアクセス可能な状況を想定した分散システム環境を構築しました。
workerを増やしていくだけで処理を分散させることができる簡単なシステムとなっています。

適用できるケース

例えば、以下のようなケースに今回の実装は有効であると考えられます。

  • 処理をすべて同期処理にしているせいで処理が完了するまでクライアントにレスポンスを返すことができない
  • 同時アクセス数を超えた場合に、実行中のタスクが完了するまで次のタスクが待ち状態になってしまう
    • 上記の場合に簡単にスケールアウトできる仕組みになっていない

同期処理によるレスポンス効率の低下に関してはニフティクラウドMessageQueueを利用することで非同期処理を実現してあげます。
アプリはすぐにレスポンスを返却し処理の命令(メッセージ)をキューに格納します。
アプリ自体で処理を実施することがなくなるのでレスポンスを劇的に改善することができます。

同時アクセスによる負荷増大のときには実際に処理をするworkerのプロセスを増やすことで待ち状態を解消します。
worker用のサーバ1台で処理できる性能に限界が来た場合は新たにworkder用のサーバを立てることでサーバレベルでも分散できるようにします。

それでは上記を想定した簡単なサンプルシステムをご紹介いたします。

システム概要

簡単なWebアプリケーションを想定しています。
アプリにリクエストされた情報はニフティクラウドMessageQueueにキューイングされ、クライアントへはすぐにレスポンスを返却します。
実際の処理はスケールアウトを想定してworkerによって処理されるようになっております。
workerは常にキューを監視しており、メッセージがキューイングされたらそのメッセージを受信し処理を開始します。

構成

今回作成したサンプルの構成は以下の通りです。

php-mq-sample

  1. appサーバ内のアプリはリクエストを受け取るとレスポンスをすぐに返却します
  2. レスポンス返却と同時にニフティクラウドMessageQueueにメッセージを送信します
  3. workerサーバ内で動作するworkerプロセスは常にキューを監視しており、先にメッセージを受信したworkerが処理を開始します
  4. 非同期処理のため処理が完了した場合にオプションでメール通知することができます

サンプル

ソースコードはこちらで公開しております。
インストール方法や設定方法はこちらをご覧ください。
ニフティクラウドのCentOS6.3で動作を確認しております。
動作に必要なパッケージインストールとソースの設定箇所を変更すれば完了です。

キューを作成する

サンプルを動作させるにはニフティクラウドMessageQueue上にキューを作成する必要があります。
キューの作成はパッケージのインストール等は必要なくニフティクラウドMessageQueueのコントロールパネル上で作成します。

  1. ニフティクラウドMessageQueueのコントロールパネルにログインします
  2. ダッシュボードの右上にリージョンを選択するセレクトボックスがありますので「west-1」を選択します
  3. キューの一覧画面にある「キュー新規作成」ボタンをクリックします
    01_create_new_queue
  4. キュー作成のダイアログでキュー名に「jobQueue」と入力し、次へ進むをクリックします 02_input_queue_info
  5. 確認画面が表示されたら「作成する」ボタンをクリックすればキューの作成は完了です 03_create_queue

作成後、キューの一覧画面に「jobQueue」が表示されます。
これでキューの作成は完了です。UIを操作するだけで簡単にキューを作成することができます。
キューを作成しサンプルコードのインストールと設定が完了すれば、あとはブラウザでアプリにアクセスするだけです。

サンプルアプリのイメージ画像

サンプル説明

  • index.php
    アプリそのものとなります。
    44行目
    sendMessage(json_encode($message));
    でニフティクラウドMessageQueueにメッセージを送信しております。 あとはただレスポンスを表示するだけのシンプルなものとなっています。

  • worker.php
    実際に処理をするデーモンプロセスとなります。
    このworkerプロセスが起動している数だけ同時実行することが可能です。
    workerは単純なphpプロセスなので
    php worker.php
    とするだけで簡単にworkerプロセスを増やしていくことができます。
    31行目
    $messageInfo = receiveMessage();
    でニフティクラウドMessageQueueからメッセージを受け取りその後処理を開始します。
    実際にどんな処理をしているかですが、今回は指定した数内に存在する素数の数をカウントする処理を実装しています。

ポイント

  • index.phpの即時レスポンス
    index.phpはユーザからリクエストしたform情報を受け取りその情報をメッセージとしてニフティクラウドMessageQueueに送信する処理だけを行っています。
    キューにメッセージを送信するだけなので、ユーザにストレスなくレスポンスを返すことができるようになっております。
    アプリは受け取った情報を次々にキューに送信していきます。

  • worker.phpのスケールアウトによる分散処理
    workerプロセスはコマンド1つで簡単に追加することができます。
    例えば、アプリがニフティクラウドMessageQueueに大量にメッセージを送信し、現在起動しているworkerプロセスの数ではキュー内のメッセージを捌けなくなってしまった場合に
    別のworkerプロセスを起動するだけでどんどんメッセージを捌くことができるようになります。
    また、今回のサンプルはサーバ側の設定に依存することなくニフティクラウドMessageQueueにアクセスできるので、1台のworkerサーバ内で起動できるプロセス数に限界が来た場合は
    サーバ自体をスケールアウトすることで更に効率的にメッセージを捌くことができるようになります。

今回はサンプルとして処理をアプリとworkerに分けることでボトルネックを解消する方法を紹介しました。
このようなケースは多くのシステムやサービスで適用できるケースではないかと思います。

おわりに

ニフティクラウドMessageQueueは使い方がシンプルでありながら、複雑な分散処理や非同期処理を簡単に実現することができる橋渡し的な存在だなと実感しました。
利用者はプログラマブルにキューを利用できるため、プログラムに集中することができるなと感じました。
今回、サンプルで紹介したケースは非同期+分散処理のケースでニフティクラウドMessageQueueを利用しましたが他にもいろいろなケースで活躍してくれるかと思います。
他のエンジニアリングパーツに比べ、キューイング処理のみを行うニフティクラウドMessageQueueは多少地味なイメージもありますが、その効果と利便性は他にも劣らぬ輝きがあると思います。
クラウドデザインパターンのように型にはまってしまえば、ニフティクラウドMessageQueueの存在があなたのシステムで欠かせない存在になる日がくるかもしれません。