Azureで非同期処理を実装する必要があり、Queue StorageとService Busを比較しました。
メッセージの順序保証と消失回避をガチで追求するService Busは考慮すべき事項が大量にあり、
そういう要件がないのであればQueue Storageを使うと楽になることが分かりました。
非同期要求-応答パターン
アーキテクチャセンターという場所で、Azure全体で検討すべき設計パターンが公開されています。
その中に、非同期要求-応答パターンという項目があります。Azure Functionのドキュメントの中でも、
タイムアウトしそうな長時間処理を実装するならこのパターンにすると良いよ、と説明されています。
HTTPトリガによってキューイングサービスであるAzure Service Busにキュー登録し、
Azure Service Busトリガによって裏で非同期処理を実行する、というものですね。
シーケンス図がわかりやすいです。
アプリケーションとジョブ実行機能を疎結合にしたい、という意図がチラチラ見えます。
実際、そこまで疎結合しないのであれば、アプリケーションに統合してしまう作りもあるかと思います。
密結合で良ければ、キュー登録もステータス監視もアプリケーションでやれますので大分シンプルです。
キュー登録、状態監視は非同期処理のコアではなく、コアは以下なのだろうと思います。
- キューに積む側が即時応答できること
- 積まれたトリガで開始する重い処理を分離できること
Service BusとQueue Service
Azureにはキューを実現する仕組みが2つあります。
厳密にはキューイングサービスはService Busだけですが、ストレージアカウントの1機能である
Queue Storageが”キューそのもの”であって、よりシンプルにキュー機能を作ることができます。
Service Busは、メッセージを決して消失させないガチのキューイングサービスで、
それを実現するために考慮すべき点が大量にあります。順序や消失の対応に命をかけるのでなければ
単なるストレージであるQueue Storageを使った方が気楽です。
両者の機能比較
Queue StorageとService Busの違いについて、公式ドキュメントから拾い集めて表にしました。
ちょっと理解が難しい部分があったので、だいぶ憶測と妄想で補足しています。
(下の方は読み取れず諦めたところがあります..)
もともと全然違うサービスなのに比較しようとするから、表の対応が取れない、という問題があります。
公式を読んでもいまいち対応が取れないのは、そもそも機能が違うから、なのだろうと思います。
Storageキュー | Service Busキュー | |
---|---|---|
特徴 | シンプル。ストレージ容量で課金。単一の送信先(非Pub/Sub)。トランザクション無し。メッセージ内容の更新可。重複検出無し。 | 多機能。トランザクション有り。1対1に加え多対多(Pub/Sub)が可。メッセージ内容の更新不可。重複検出あり。トピックフィルタあり。 |
順序の保証 | なし 一般にFIFOだが状況によって順序が変わる |
FIFO、セッションIDによるグルーピング(セッション)と同一セッション内の送信順序保持。 |
転送・ロック・解決 | Peek & Lease 受信者から「読み出す(Peek)」要求があった場合に他の受信者に該当のメッセージ読み取らせないようにする。(Lease) |
Peek/Lockモード 送信者がブローカー(Service Bus)に送信し受信者の受信が成功/失敗分かって初めて解決とする。メッセージにロックがかかり競合受信者が触れなくなる。送りっぱなし・非同期にしてはいけない。 Receive/Deleteモード ブローカーが受信者に送信した時点で解決とする。受信者による受信の成功/失敗には関与しない。受信に失敗するとメッセージは失われる。 |
配信不能キュー(DLQ) | 有害キュー。対応する記事がないが、受信に失敗すると特殊なキューが作られてそこに入った。 | 配信不能レタリング |
配信保証 | At-Least-Once 少なくとも1回。つまり1回は確実に配信されるが、重複(2回以上同じメッセージ)がありうる。 |
At-Least-Once(PeekLockの場合) 少なくとも1回。つまり1回は確実に配信されるが、重複(2回以上同じメッセージ)がありうる、損失なし At-Most-Once(ReceiveAndDeleteの場合) 最大1回。つまり0回=配信されないことがある。重複はない。 |
トランザクション | 非対応 | 対応 |
重複検出 | 非対応 | 対応 |
プロトコル | HTTP/HTTPS (RESTベース) | HTTPS (RESTベース) |
メッセージサイズ | 最大64KB | 256 KB または 100 MB |
メッセージの最大TTL | 無限 | 有限(TimeSpan.MaxValue??) |
処理数 | 最大2000メッセージ/秒 (1KBの場合) | (省略) |
キューサイズ | 最大500TB | 1 GB ~ 80 GB |
キューの最大数 | 無限 | 10,000 |
メッセージ保存期間 | 最大7日 | (省略) |
どちらを使うべきか
公式では、以下が必要な場合はService Busを使うべしとされています。
不要ならStorage Queueとなります。だいたい、あるなら使いたいとなりがちな気がしますが、
そうするとService Busになってしまいます。
扱いやすいStorage Queueを使うなら「必要ではない」を判断する必要があります。
azure-storage-queueの動作確認
Azure Storage Queueを操作するパッケージは、azure-storage-queueです。
クイックリファレンスによると、以下の機能をサポートしています。
- キューを作成する
- メッセージをキューに追加する
- キュー内のメッセージを表示する
- キュー内のメッセージを更新する
- キューの長さを取得する
- キューからメッセージを受信する
- キューからメッセージを削除する
- キューを削除する
対して、Service Busを操作するパッケージは、azure-servicebusです。
azure-storage-queueのように簡単に機能リストをまとめることはできないため省略。
抽象化のレベルが違うので、これだけでも面倒さが分かります。
まとめ
Storage QueueとService Busを比較し、まとめてみました。
次回はFunctionsのStorage Queueトリガ/バインドを使って非同期処理を書いてみます。