みなさん、こんにちは。エンジニアのpiyohikoです。 今回はフルマネージドサービスの「Message Service」についてご紹介したいと思います。Alibaba Cloudに限らずですが、クラウド上でのシステム構築にキューイングサービスはとても重要ですので、その魅力についてご紹介いたします。
クラウド上で様々なサービスを展開していくと、サービス同士の連携方法に頭を悩ませることが多々あると思います。アプリ上で複雑な連携や同期を構成してしまうと、相互の依存性が高くなり、場合によってはクラウドの良さである柔軟性や拡張性を損ねてしまうこともあります(これを密結合といいます)。
今回は密結合と逆の結合方法、疎結合(マイクロサービス化)を実現する、キューイングサービスをご紹介したいと思います。 疎結合ではシンプルな非同期構成や分散構成を、スケールを気にすることなく構築することができ、また、システムが追加になっても構成変更を容易に実施できます。
Alibaba Cloudのキューイングサービスはフルマネージドサービスで提供されており、「Message Service」といいます。
キューイングシステムとは
もう少し詳しくキューイングシステムについて説明します。 キューイングシステムとは、キューに入れたメッセージをやり取りすることで、システム間を連携させる仕組みです。メッセージの送り手と受け手は非同期で処理するため、一方のシステムがダウンしても直接影響を受けないのが特徴です。
効果的な活用例
Message Serviceをより深く理解するために、この特性を生かした活用例を2つ紹介します。
1.画像処理などの逐次作業を並列処理させる
例えば、Webサイトから画像処理などの時間のかかる処理を要求するシステムがあったとします。このようなシステムの場合に、メッセージキューを活用できます。メッセージキューを使わない同期的なシステムでは、画像処理が終わるまでブラウザを開いたままにする必要があります。ブラウザのタブを閉じてしまったり、通信環境が悪くなったりした場合には処理が中断してしまいます。
一方、メッセージキューを利用して非同期的なシステムにした場合、Webサイト側では、「画像処理の要求を受け付けました」とレスポンスを返し、裏で画像処理を行うことができます。
また、画像処理の動作中にサーバに障害が発生したとしても、未処理のキューが残っているので、サーバが復旧次第処理を再開できます。
(画像処理例:画像のアップロード、保存、エンコーディング、サムネイル作成、等)
2.アプリケーションの追加や運用ルール変更時のシステム変更を楽にする
例えば以下のようなECサイトがあったとします。
1.顧客管理サービスを呼び出し、会員として登録する。 2.ポイントサービスを呼び出し、新規会員登録時のポイントを付与する。 3.メール送信サービスを呼び出し、会員登録サンキューメールを送信する。
後からECサイトの追加と、メールアドレスを持たない人用にDM発送の運用ルールを追加したとします。
このシステムをアプリケーション同士で連携していた場合、ECサイトを追加したり、DMメールを送るような運用ルールを追加したりすると、各アプリケーションごとに変更が必要です。キューイングシステムを利用して連携すれば、ECサイトが追加になっても運用ルールが追加になっても、変更はキューイングシステムだけで済みます。
では、実際にMessage Serviceを使ってシステムを構築してみます。
Webページの「登録」ボタンが押されたらメールを送信するシステムを構築する
今回はこの構成を実装してみます。Webサイトの「登録」ボタンが押されたら、メッセージキューを利用して登録処理の実行とメールを送信します。
1.「登録」ボタンが押されるとWebページが更新されます。
2.メッセージキューを送るコマンドが実行されます。
3.一定間隔でメッセージキューを受信するコマンドが実行されています。
4.メッセージを受けたら登録処理とメール送信を要求するコマンドを実行し、メッセージキューを削除します。
※メールはSendGridという外部サービスを使って送信されます。
基本的な操作と環境設定
SDKをインストールします。 インストールにはGitを使用します。Gitをインストール後、PythonのSDKをインストールします。 コマンド例
$ sudo yum -y install git $ git clone https://github.com/bowenpay/mns-python-sdk.git $ cd mns-python-sdk/ $ sudo python setup.py install
「mnscmd」コマンドがインストールができたか確認します。 mnscmdでオプションの一覧が表示されたらインストール完了です。
$ mnscmd =============================================== mnscmd: createqueue createqueue --queuename=xxx [--vistimeout=xxx] [--maxmsgsize=xxx] [--retentionperiod=xxx] [--delaysec=xxx] [--waitsec=xxx] listqueue listqueue [--prefix=xxx] [--retnum=xxx] [--marker=xxx] getqueueattr getqueueattr --queuename=xxx sendmessage sendmessage --queuename=xxx --body=xxx [--delaysec=xxx --priority=xxx] receivemessage receivemessage --queuename=xxx [--waitsec=xxx] peekmessage peekmessage --queuename=xxx setqueueattr setqueueattr --queuename=xxx [--vistimeout=xxx] [--maxmsgsize=xxx] [--retentionperiod=xxx] [--delaysec=xxx] [--waitsec=xxx] changevisibility changevisibility --queuename=xxx --handle=xxx --vistimeout=xxx deletequeue deletequeue --queuename=xxx deletemessage deletemessage --queuename=xxx --handle=xxx config config --endpoint=http://$accountid.mns.cn-hangzhou.aliyuncs.com --accesskeyid=YOUR_ACCESSKEYID --accesskeysecret=YOUR_ACCESSKEYSECRET ===============================================
ライセンス・エンドポイントの登録 MNS管理コンソールからエンドポイントをコピーし、サーバーにコマンドで登録します。(MNSコンソール⇒サーバー)
MNS管理コンソールの「エンドポイントの取得」から、エンドポイント をコピーすることができます。
<Endpoint> パブリックエンドポイント : http(s)://<アカウントID>.<リージョンID>.aliyuncs.com/
configコマンドで設定します。 「mnscmd config --endpoint=」の後に、エンドポイント、アクセスキー、シークレットキーを追記します。
# mnscmd config --endpoint=http://<アカウントID>.<リージョンID>.aliyuncs.com/ --accesskeyid=<アクセスキー>--accesskeysecret=<シークレットキー> Your configuration is saved into /root/.mnscredentials .
httpdとphpをインストールし、httpの再起動後indexページを編集します。 コマンド例
# yum -y install httpd # systemctl start httpd # systemctl status httpd # yum -y install php # systemctl restart httpd # vi /var/www/html/index.html
ブラウザーからみたWebページ
登録ボタンを押すと、ページが更新され、メッセージを送るコマンドが実行されます。 phpコマンド例
//処理要求の実行 $scmd='sudo /root/mns-python-sdk/bin/mnscmd sendmessage --queuename=test06 --body="サービス処理側へ引き渡すパラメータを指定"
ブラウザからみたWebページ
メッセージを監視するコマンドを実行しておきます。 メッセージが受信されると、DB登録処理やメール送信処理が実行されます。 phpコマンド例
//処理要求待ち監視(無限loop) $i = 0; while ($i <= 1){ $rcmd='sudo /root/mns-python-sdk/bin/mnscmd receivemessage --queuename=test06'; $output1=array(); exec($rcmd,$output1,$res); error_check($res); $count=count($output1); //メッセージ受信確認 if ($count === 14) { $receipthandle=$output1[6]; $receipthandle=explode(":",$receipthandle); $receipthandle=$receipthandle[1]; $messagebody=$output1[12]; $messagebody=explode(":",$messagebody); $messagebody=$messagebody[1]; //ここでDB登録処理を実行(今回は省略) //ここでメール送信処理を実行 $output2=array(); $sg2cmd='sudo python /usr/lib/python2.7/site-packages/sendgrid/helpers/mail/test-send.py'; exec($sg2cmd,$output2,$res); $output3=array(); sleep(1); //ここで処理済キューを削除 $dcmd='sudo /root/mns-python-sdk/bin/mnscmd deletemessage --queuename=test06 --handle=$receipthandle'; exec($dcmd,$output3,$res); error_check($res); echo "メールを送信しました!"; sleep(5); } else { echo "\n"; echo "まだ要求は来ていません!"; sleep(5); } }
「test-send.py」はメールを送信するようなプログラムです。 メールを送信する手順は以下のテックブログを参考に実施しました。
「Alibaba Cloud上でSendGridのWeb APIを使ったメール送信方法」 http://techblog.sbcloud.co.jp/2017/06/28/sendgrid_with_alibaba_2/
設定は以上です。
動作確認
Web画面の「登録」ボタンを押すと、Web画面が更新され、メール送信コマンンドの「test-send.py」で指定した宛先にメールが送信されました。
まとめ
今回は1つのメッセージ送信に対して1つのメッセージ受信を実装しましたが、一度に16以下のメッセージを受け取ることもできます。ある程度まとめて受信をしたい場合に活用できます。
このようにアプリと実際の処理を分けることで、スケールや障害を気にすることなくすぐにレスポンスを返すことができます。 また、キューイングサービスを実機で実装しようとすると、サーバの手配からミドルウェアの選定、テスト等、非常に手間とコストがかかります(もちろん運用も)。MessageServiceを利用すれば、必要になるのはエンドポイントの取得と利用した分の料金くらいです。
今回は単純な構成でご紹介しましたが、他にも色々なケースで活躍できる機能です。低コストで、非同期処理や分散処理を実現する手段として、活用していただきたいと思います。