GameWith Developer Blog

GameWith のエンジニア、デザイナーが技術について日々発信していきます。

Amazon SQSを使って処理をキューイングするシステムを構築してみた #GameWith #TechWith #AWS #SQS

こんにちは! スケールアーキテクトチームの@shgx です。

今回はAWSのSQS(Simple Queue Service)を使って処理をキューイングするシステムを構築してみた話になります。

そもそもキューイングって何なのか?とか言うところもあるかもしれないと思うので、それも含めて最初に軽く説明したいと思います。

キューイングと長所・短所について

「キューイング」は「待ち行列」という意味で、一個一個処理を貯めていってそれらを任意のタイミング(非同期)で順次処理する、という形を実現してくれるシステムです。

こんな感じで、1,2,3,4という順番で箱に詰めていって1,2,3,4と取り出すような処理。

キューイングの何が良いかと言うと非同期で任意のタイミングで順次処理できる、というところになります。基本的にシステム間での処理の連携は同期的に行われるものです。しかし、Webからくるアクセスや処理の要求は不確定でいつ数万回/sなど想定しないアクセス数が来るか分からないものです。そんな時、受信側の処理が追いつかず送信側はメッセージを送信できない状態になりがちです。キューイングは非同期なので、それを防ぎながら処理を進めることが出来ます。そういう状況を必ず防ぎたい・処理に時間がかかるものや処理を待っても問題ないものに利用されることが多いです。

一方、キューイングの悪いところは処理が非同期になる、というところです。状態を持たないと送信側は処理が終わっているという確証が得づらいです。キューイングの処理側に依りますが、処理が追いつかなくなりキューが溜まりすぎて処理が一向に終わらないということも起こりえます。そのため、それらデメリットを踏まえた上でシステムを実装する必要があります。

・SQSについて

SQSとはAWSが提供する分散型メッセージキューイングサービスで、上記の項目で説明したようなキューイングをサーバーレスで実現できるサービスです。

SQSはキューイングされたキューを処理する順番でタイプが2つ分かれています。

  1. キューを入れた順序を考慮しない標準タイプ

  2. キューを入れた順番を考慮するFIFOタイプ

標準キューではメッセージの取得順が保証されません。重複取得の可能性もありますが、ほぼ無制限のAPIコールをサポートしています。

一方FIFOキューはメッセージの順番が保証されます。代わりに1秒あたりの最大メッセージ数が限られていて(※)、料金も若干標準キュータイプより高くなっています。

※通常秒間300~3000件、更に料金が加算されるが高スループットモードを有効にするとバッチ処理ありで 1 秒あたり最大 30,000 件のメッセージが可能になっています。

料金体系について2022/11/30現在こんな感じ。

最新はこちらを参照:https://aws.amazon.com/jp/sqs/pricing/

比較的安いのでいろんなシステムに使いやすいと思います。

・アーキテクチャ

今回は荒らしコメントが増えていたので、掲示板系システムのコメントの投稿を監視して荒らしコメントを削除するシステムを作る、という要件でした。

まずどうやって荒らしコメントを判断するかの評価システムについて気になる方も多いと思いますが、それは置いておいてここではアーキテクチャ周りについてお話します。

普通ならコメントを評価するシステムを作ってそこに投稿コメントを流すだけなのですが、今回コメント評価の処理の流れ・負荷も含めてシステム上APIのコール数が限られる状態でしたのでSQSを利用してキューイングをすることにしました。

投稿順に順次監視して処理したかったので、SQSのFIFOタイプを利用して以下のような感じでぼんやりとアーキテクチャを考えていました。

図:SQSとworker

キュー貯めるSQSとキューを処理してコメントを判断するコメント評価workerと言う風な感じで役割を分けました。workerはSQSを一定時間ポーリングしてキューがあるかを定期的に監視しています。

しかし、上記のようなアーキテクチャのままだとClient側がSQSのキューイングシステムを意識する必要(AWS SDKを利用するなど)があったのと、SQS側でアクセス制御・ログ等色々多く担う必要があることに気が付きました。 SQSに依存してスケールしづらくなる可能性もあったため、より疎結合にするためClientとSQSの間にコメント情報を受け取る入り口としてAPIを挟むことにしました。

古いシステム・言語、新しい言語を使っている場合AWSのSDKが整備されていないこともあるので、こういうラッピングでどのシステムでも使えるRESTにするのは結構大事だと思っています。SQSを知らない人でも簡単に使いやすい形になっています。

上記の図をベースに最終的に以下のような感じのアーキテクチャを考えました。

APIはALB(Application Load Balancer)とECS(Elastic Container Service)が担う感じになっています。ALBは外部などアクセス制御のために利用しています。ECSはコンテナを利用したサービスですが、コンテナで管理することでdeployの自動化、CI/CDも含めてAPIとWorkerの実装を整備しやすい形にしています。

GameWithの掲示板コメントは様々なシステムに分散しているので、キューイングを意識しないで疎結合にして汎用的に使えるように設計することでうまい感じに運用出来る感じになりました。

・終わりに

上記で構築したシステムは現在運用状態に乗っています。現状まだ導入途中ですが順次各掲示板のコメントシステムにも追加していく感じになると思います。規模も大きくなっていくと思われます。間を入れ替えたりスケールできるアーキテクチャにしていけるとこういう時、臨機応変で良いかもしれないですね。

あと、今回話したところ以外、ECSのキュー送信とキュー受信の実装部分についてや、コメント評価部分の処理についてはまた今度書きたいと思います。