AP4R,Rubyで非同期メッセージング

第3回 SAF機能とテストサポートによる安心非同期

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

前回のおさらい

前回は,ウェブ上のお店のアプリケーションを作成しました。店を訪れたお客さんはウェブブラウザから品物の名前を入力して,注文を行います。その後,サーバ側では注文情報の保存と決済の2つの処理を順次行います。処理が完了すると,ブラウザに注文完了の情報が表示されます。この同期アプリケーションをAP4Rを利用して非同期拡張しました。

すなわち async_to メソッドを使って「重い」決済処理を注文処理から分離し,ユーザーの待ち時間を解消しました。リバースプロキシを利用した,バックエンドに複数の Railsプロセスが存在する構成では,「重い」非同期処理とユーザーにすぐ応答したい処理をうまく両立させながら実行できます。記事のサンプルではリバースプロキシ構成にはせず,URL変換フィルタの機能を利用して,非同期メッセージ処理のリクエスト先を別のRailsプロセスに変える例をご紹介しました。

今回は,AP4Rの「堅牢さ」を支える SAF機能の使い方やテストサポートについて解説し,安心して非同期処理を導入できるようにします。

アプリケーションの拡張の方向性

2つの拡張を行います。

異常系に対する備え

メッセージングを利用してアプリケーションを非同期化する際には,異常系に対する備えが重要となります。通常の同期処理であれば,ユーザーは何か問題が起きたことに気づき再度処理を実行してくれるでしょう。しかし,非同期処理の場合,ユーザーの気づかないところで異常が発生していることになります。また,異常によりメッセージのやりとりに問題がでるかもしれません。

データベースやネットワークの障害,サーバの突然のダウンなど,異常は予期せず発生します。連載第1回目でも触れましたが異常の発生タイミングによってメッセージングにどんな影響があるかを復習してみましょう。

下図は,業務DBへのコミットとメッセージ生成の間で障害が発生した場合です。業務DBにCRUD(Create, Refer, Update, Delete)が反映されているものの,メッセージの生成が行われていないので,AP4Rを介して実行するはずの非同期処理が行われません。サンプルアプリケーションでは決済処理が実行されないことになります。

図1 データはあるのに,メッセージがない場合

図1 データはあるのに,メッセージがない場合

また次の図は,業務DBへのコミットとメッセージ生成の順番を変えたものです。このようにすると,メッセージは生成されますが,業務DBへのコミット前に異常が発生するとCRUDの結果はロールバックされます。この結果,注文処理に失敗したにもかかわらず,決済処理だけ実行されてしまうという状況になります。

図2 データがないのに,メッセージがある場合

図2 データがないのに,メッセージがある場合

業務DBへのCRUDの反映とメッセージの生成をアトミックに行い,たとえなにがあろうとも,メッセージを死守する。それが信頼性のあるメッセージングに求められる必須要件となります。AP4Rでは,そのためにSAF機能を提供しています。

非同期処理もテストする

テスト駆動開発(Test-driven Development,以下TDD)や振舞駆動開発(Behaivior-driven Development, 以下BDD)という開発手法は,既に広く知られており,開発現場で適用されている方も多いのではないかと思います。

筆者はあるプロジェクトでTDDを実践し,自分の書いたコードに対するテストスイートを作成しました。その際,コードの保守,拡張に対する安心感,そしてリリースに対する自信に繋がるたいへん有効な方法だと感じました。

この連載では,TDD/BDDの説明には踏み込みませんが,BDDでは開発側だけに留まらず,「仕様」に着目し,それを記述することで開発自体を牽引していくという面も強調されます。

Rubyには,Test::Unit ラリブラリが付属しており,簡単にTDDが実践できます。また,Ruby on Railsでは,ウェブアプリケーションにTDDを適用するため,unit,functional,integrationという3種類のテスト方法をサポートしています。

非同期処理を含むアプリケーションでも,網羅的なテストが(比較的)簡単に実行できることは同じように重要です。メッセージング処理では,ネットワーク通信をともなうため,複数のプロセスが関係することと,通信により時間がかかることの2点を考慮する必要があります。そこで,AP4Rでは,2つのテスト方法を用いて,テストしやすさと,網羅性を補完的に実現します。

(Rails付属の)functionalテスト
アクション単体のテストとして,メッセージングでの通信無しにテストを行います。
asyncテスト
ネットワーク通信やメッセージDBへのアクセスを含め,実動作となるべく近いやり方でテストを行います。

次ページから,SAF機能を適用し,前回に続いて非同期アプリケーションを拡張します。その後,AP4Rでのテストサポートとして,それぞれの動作概要,テストの書き方と実行方法を説明します。

著者プロフィール

加藤究(かとうきわむ)

フューチャーアーキテクト株式会社,シニアコンサルタント。土木専攻だった大学時代には,道路や橋の建設について学んできたが,社会に出てからは Javaのメッセージングミドルウェアの開発/保守などに従事。昨年,Rubyで書いたメッセージングライブラリ,AP4Rでオーンソースの世界に仲間入り。現在は,AP4Rの開発/導入サポート中。

URLhttp://d.hatena.ne.jp/kiwamu/


篠原俊一(しのはらしゅんいち)

フューチャーアーキテクト株式会社,シニアコンサルタント。大学時代は物理学を専攻,素粒子論を研究,10次元の世界に住んでいた。入社後まもなく,Martin FowlerのblikiでRubyを知り,"The Ruby Way"に学ぶ。 Rubyとオープンソースが大好きなプログラマとして,AP4Rを開発中。

URLhttp://d.hatena.ne.jp/ita-wasa/

コメント

  • 疑問点

    ページ2で、003_create_table_for_saf.rb を作成してから rails を実行するまでに rake db:migrate が抜けているようです。

    また、ページ3で raise "for SAF test" を挿入した箇所は ap4r.async_toより後ろですから、メッセージはStoreされるのではないでしょうか。

    Commented : #1  だて (2007/09/28, 18:41)

コメントの記入