「SQSに渡して非同期にする」とはどういう意味なのか?

「SQSに渡して非同期にする」とはどういう意味なのか?

最近仕事である処理を作成した。その機能がある程度まとまってきたとき、上司に「その処理はまるまるSQSに渡して非同期処理させてほしい」と言われて、その場で「はい!」と答えたが、全部の単語の意味が分からなかったため調べることにした。

SQSとは

Amazon Web Service(以下、AWS)の中の1つのサービス。Amazon Simple Queue Serviceを略して「Amazon SQS」や単に「SQS」と呼ぶ。
AWSのドキュメントを参照すると、

Amazon Simple Queue Serviceは、分散されたソフトウェアシステムとコンポーネントを統合および分離することができる、安全で耐久性があり、利用可能なホストされたキューを提供します。(更に続く、、、)

https://docs.aws.amazon.com/ja_jp/AWSSimpleQueueService/latest/SQSDeveloperGuide/welcome.html

と書いてある。いや、全然分からんわ。もう少し深掘りすることにしよう。

AWSってなによ

そもそも論すぎるが名前だけたくさん聞いて、イマイチその詳細が掴めていないAWS。それの概要について調べてみた。

AWSは、Amazonが提供しているWebサービス。Amazonの自社サイト「Amazon.com」の運営で得たノウハウを活用して、それを外部にも商品としてサービスを展開した。具体的には、サーバやデータベースをネット上で貸し出している。

AWSの様な、サービスをネット上で貸し出す方法を「クラウドコンピューティング」という。一方で自社内にサーバなどの設備を用意するのを「オンプレミス」という。

多くの場合は、オンプレミスではサーバやソフトウェアなどの情報システムを企業が管理する施設内に管理して、運用することがあたり前だった(寧ろそれ以外がない)。その機材を買うお金や設置する費用、施設の物理的な制限など、あらゆるリソースを割かないといけないのがオンプレミスである。

その一方で、最近台頭してきたクラウドコンピューティングはネット上でサーバなどの情報システムを貸し出すため、導入した企業が実際に設置するためのリソースを割かなくて良くなった(実際は物理的な設置場所は世界各地に存在するが、それはAmazonが管理するため、借りる企業が管理する必要がない)。

これらのメリットから、人材・土地・資金などが豊富ではないような小さい企業を中心にAWSが世界の色んな人に使われだしている。そのサービスの中の1つがAmazon SQSってわけ。

Queue(キュー)とは

SQSの中にQueue(キュー)という単語が含まれている。queueとはどういう意味なのか。

weblio英和辞典によると、

(順番を待つ人や乗り物の)列

と書いてある。ざっくり言うと「列、待つ」みたいなニュアンスが大事らしい。

Queue自体は、物事が並ぶ順番を指すことが多い様だ(文脈で変わることがあると何かに書いてあった)。

例えば、真夏に自動販売機に行列ができていたとする。現在並んでいる順番は「A, B, C, D」である。この時にXが自販機で飲み物を買おうとした場合、いきなり自販機で飲み物を買うのではなくて、一旦列の最後尾に並ばないといけない。この様な仕組みを「キュー」と呼ぶ。システム関係で言うと、データをキューで順番に並ばせて、処理が行われるのを待たせるということだ。

キューから要素が出ることを「エンキュー(enqueue)」、要素が追加されることを「デキュー(dequeue)」という(調べたらキューで用いる単語らしい。スタックの時はpushとpopっていうらしい)。

列の先頭から順々に処理されることを「FIFO(First In First Out)」という。日本語で書くと「先入先出」と表現する。キューは「FIFO」を用いている。列があった時、列の先頭から順に処理され、後から来たデータは列の最後の格納されるということです。上記の自販機の列や(追い越しがない)トンネルから出てくる順番が該当する。

逆に列の末尾から順々に処理されることを「LIFO(Last In First Out)」、日本語では「後入先出」と表現する。キューとは対義語の「スタック」がこの処理をする。列があった時に、後から来た要素を列の末尾に追加しても、その末尾から処理するということだ。FIFOよりケースは少ないが、例えば取り込んで山積みになった洗濯物を上から畳んだらLIFOである。食事で使った食器を上から洗っていったらそれもLIFOになる。

実践的にキューを理解

ここで実用例として、パソコンからデータを紙に印刷したい時を想像する。その時にする処理として、

  • コピーしたいデータをコピー機に送信する
  • コピー機がコピーする
  • (完成)

至極当たり前だが、上記の3つが流れである。まだキューは発生しない。問題となるのが、コピーしたい人が複数存在する時だ。A、BとCの3人がほぼ同時に同じコピー機にコピーしたいデータを送信したとする。タイミングの差でデータがB→A→Cの順番でコピー機に届いたとする。しかし、実際にコピー機が届いたデータを紙にするのにはある程度の時間がかかる。この時にそれらのデータをキューとして並ばせて、順々にコピーすると言う作業が必要になる。ここで「キュー」が登場する。もちろんこの時のキューは「B、A、C」である。

最初に届いたBをまずコピーする。そのコピーが終了するまで、AとCはキューに入って待つことになる。もちろん順番は「A、C」である。Bが終了したら、次はAの処理が始まる。Cはまだキューの残って順番を待っている。Aが処理中の時に、例えばDが新しく来たとする。「Dをコピーする」とパソコンから信号を受けたコピー機は、Dが来た途端にAのコピーを中断してDをコピーし始めるわけではない。キューを利用し、DをCの次に並ばせて自分の番が来るのを待つ。これで送信した順番に(正確には受信された順番だが)コピーが処理されることになった。

普段エンジニアとしてプログラムをいじっていると、配列(?)を先頭から取り出し、追加する要素を配列の末尾に追加する作業を高速で処理するのには高度な技術力を要することが想像つく。

非同期とは

通信や処理には2つの種類がある。「同期通信」と「非同期通信」の2種類である。

同期通信とは、相手に要求を出したときにその返答を待つ通信のこと。一方で非同期通信とは、相手に出した要求の返答を待たない通信。

加えると同期通信は相手の応答を待つが、文字通り「待つ」ので、この間は他の処理ができなくなる。その「待つ」動作をしないで他の通信もするのが非同期になる。

同期通信の場合は要求の送信タイミングと応答の受信タイミングが一緒だから、データ量が少なくて済む(らしい)。一方で非同期通信は、そのタイミングが異なるから、応答を受け取れるようにするために通信データに「スタートビット」と「ストップビット」というデータを付加して送受信する。非同期通信はこういう冗長なデータが含まれるからデータ量が多くなってしまうというデメリットも存在する。

通信を待ってもいい処理の場合は同期通信にして、スピード感が必要な通信の場合は非同期通信にするといいね。

「SQSに渡して非同期通信にする」の意味は?

さっきのコピー機の例をまた考えよう。処理の順番は「B, A, C」だった。キュー的にBが最初にコピーを開始されるが、その間AとCはコピーがされるのを待つことになる。これらの通信が同期通信だとすると、AとCのパソコンはコピーが完了するまで通信ができず、ずっと待ってる状態になってしまう(多分最初のBも同じと思われる)。だから、これらを非同期にすることでコピーが終わるのを待たなくても、自分のパソコンは普通に作動するような仕組みを実現したいのが狙いだと思う。

【結論】

SQSがあると非同期にできるから、即時性が求められる通信にはもってこいだねっ!