非同期処理を使いこなそう !
- 第 1 回 非同期処理ってなんだろう ? -
五十嵐 直人
こんにちは、プロフェッショナルサービス本部クラウドアプリケーションアーキテクトの五十嵐です。
先日、Web で美味しそうな料理の写真を見かけ、自宅で作ってみることにしました。
大きく分けて以下の手順が必要でしたが、みなさまでしたらどのように調理を進めるでしょうか ?
- 鍋で水を沸騰させる
- 野菜を切る
- 野菜を茹でる
- 調味料で味付けをする
- 皿に盛り付ける
1. で鍋を火にかけた後、鍋の前で沸騰するのをじっと待ちますか ? 今回は次の手順が沸騰を待たなくてもできる「野菜を切る」のため、沸騰を待たずに 2. で野菜を切り始め、沸騰したことを確認してから 3. で野菜を茹で始めると思います。
このようにして、完成までの時間を短縮化させる工夫をするのではないでしょうか。「他タスク (今回は水の沸騰) の完了を待たなくても良いケース (野菜を切る)」と、「他タスクの完了を待つべきケース (野菜を茹でる)」をうまく使い分けることで、効率よく調理を済ませることができます。
さて、このように「あるタスクの結果を待つ必要があるのか ?」が今回の連載で考えていくテーマ「非同期処理」となります。
みなさまはアプリケーションを設計するときにも、この「非同期処理」を活用されてますでしょうか ? お客様のプロジェクトに参画すると「同期処理と何が違うの ?」「非同期処理にしないと困ることはあるの ?」「具体的なアーキテクチャ構成を知りたい !」そういった様々なご意見を耳にします。実は日常生活や業務の中では、冒頭で記載したように様々なシーンで非同期処理が行われています。非同期処理をアプリケーション設計に取り入れることで、応答性の改善、耐障害性の向上、スループットの向上、コスト削減など様々なメリットが期待できます。
そのメリットを享受するためにも、非同期処理をテーマとした全 4 回の連載記事を執筆し、みなさまの疑問を解決できればと思います。
まず第 1 回目となる今回は、EC サイトの事例を用いて同期処理と非同期処理の特徴や使いどころを理解していただきます。
次回以降の連載では、同期処理と非同期処理についてより深く解説していきます。 特に連載記事のテーマでもある非同期処理に着目して、 AWS サービスを利用した具体的なアーキテクチャ例や、設計時の考慮ポイントなどもご紹介し、最終的にはみなさまご自身がアーキテクチャ設計で同期処理と非同期処理を使いこなしていただける連載記事にしていきたいと思います。
連載記事を通して、非同期処理を使いこなせるようになりましょう !
この連載記事のその他の記事はこちら
- 選択
- 第 1 回 非同期処理ってなんだろう ?
- 第 2 回 非同期処理と同期処理の処理構造
- 第 3 回 AWS サービスを活用した非同期処理アーキテクチャ
- 第 4 回 非同期処理の設計上の検討ポイント
EC サイトと同期/非同期処理
多くの方々は、オンラインの EC サイトを通して本や生活用品など何かしらの商品を購入したことがあるのではないでしょうか。ここでは、そんな EC サイトを題材として同期/非同期処理を説明していきたいと思います。
まずはじめに、EC サイトで注文を受け付けてから配送処理を完了するまでの簡易的な流れを考えてみましょう。
エンドユーザーは、EC サイトの画面上で商品カタログを参照し、欲しい商品に対して注文を実施します。EC サイトはこの注文を受け付けた後、倉庫から必要な在庫の確保を実施します。そこからさらに、商品をエンドユーザーの手元に届けるために配送の手配を実施します。配送は他社の配送業者にお願いすると仮定すると、他社のシステムに対するデータの連携が必要となります。
次に、これらの流れをシステムで実現するために、類似の機能群を以下のように「サービス」として定義します。
- 注文処理サービス : 商品カタログの表示や注文の受け付けなどエンドユーザーとのインタフェースを担う (※)
- 在庫管理サービス : 注文情報をもとに倉庫から必要な在庫の確保を担う
- 配送処理サービス : 配送業者のシステムに対する配送依頼や配送状況の確認を担う
(※) 本来、商品カタログ表示や注文受け付けの処理は異なるサービスになると考えられますが、本連載記事では同期/非同期処理の理解に焦点を当てるため、これらは 1 つのサービスとして簡略化した記載としています。
これを図示すると以下のような構成となります。
さて、ここまでのところでシステムに必要なサービスが洗い出されました。このシステムをエンドユーザーへ提供するために、みなさまはどのようなことを考慮して設計されるでしょうか。
例えば、注文を正しく受け付けるための機能を具体的に考えたり、セキュリティや可用性といった非機能を考えたりするかと思います。ここでは重要な設計ポイントの 1 つとして、エンドユーザーに対する応答性能 (レスポンス速度) を考えてみたいと思います。
みなさまが EC サイトで商品を購入されたときを思い出してみてください。長い時間、ロード画面で待たされたことはないでしょうか。あまりに反応が遅くて購入を取りやめたことがあるかもしれませんし、注文した後になかなか受付結果が表示されずやきもきされたことがあるかもしれません。
Web サイトにとって、レスポンス速度はエンドユーザーの離脱や満足度の低下に影響する重要な要素となります。エンドユーザーがすぐに結果を返してほしい情報については、それに適した方式でシステムも実現する必要があります。
それでは、先ほど挙げた 3 つのサービスですぐに結果を返してほしい情報がないか見てみましょう。
まず「注文処理サービス」は、注文の確定状況 (注文が正常に受け付けられたのか、あるいはエラーとなったのか) を返すサービスとなります。エンドユーザーはすぐにこの結果が欲しいと考えられます。
次に「在庫管理サービス」は、在庫の確保状況を返すサービスとなります。もし在庫が無いのであれば、エンドユーザーは代替品や他のサイトを探しに行きたいと考えられますので、これもすぐに結果が欲しい情報と考えられます。
「配送処理サービス」は、配送日の確定状況を返すサービスとなります。配送されるのが数日以内なのか 1 ヶ月ほど後なのか、おおよその日程さえ分かれば、具体的な配送日の確定情報は後でも良いと考えられます。今回のケースでは、この具体的な配送日について、すぐには不要な情報と考えます。
システム観点で考えてみると、「注文処理サービス」からは「在庫管理サービス」を利用することで在庫が確保ができ、「配送処理サービス」を呼び出すことで配送日の情報が取得できます。
「在庫管理サービス」は自社システムのサービスであるためすぐに結果を返すことができそうですが、「配送処理サービス」は配送業者のシステムと連携する必要があり、その完了まで待つと時間がかかると想定されます。長い時間待機することは、顧客体験としても良いとは言えません。よって「注文処理サービス」は、在庫の確保までを即時結果として利用し、具体的な配送日の情報は外部システムの処理が完了した後で、別途エンドユーザーに通知することが最善と考えます。
ここまでの内容をまとめると、処理を実施する各サービスによって「処理の結果を待つ必要が "ある" サービス呼び出し」と「処理の結果を待つ必要が "ない" サービス呼び出し」に分類することができます。
- 処理の結果を待つ必要が "ある" サービス呼び出し
→「注文処理サービス」から「在庫管理サービス」の呼び出し - 処理の結果を待つ必要が "ない" サービス呼び出し
→「注文処理サービス」から「配送処理サービス」の呼び出し
では、これらの要件を満たすために、なにか良い処理方式はあるのでしょうか。
当連載では、「処理の結果を待つ必要が "ある" サービス呼び出し」を同期処理、「処理の結果を待つ必要が "ない" サービス呼び出し」を非同期処理と定義し、解説していきます。
ここからがいよいよ本題、同期/非同期処理の登場です !
同期処理と非同期処理の使い分け
リクエストを処理したいとき、まず最初に思いつく処理方式は「同期処理」ではないでしょうか。
同期処理の特徴は、リクエストに対するレスポンスで処理結果を受け取り、その処理結果を持って次の処理に進めることができる点です。このため、「注文処理サービス」から「在庫管理サービス」を呼び出す時のように、結果を待ってエンドユーザーに情報を応答するような場合には、同期処理として設計するのが適切です。
一方、時間のかかる処理や外部システムに接続するような処理を同期処理で呼び出すと、レスポンスタイムに影響が出てエンドユーザの離脱や満足度の低下を招く可能性があるため、同期処理が適切でない場合もあります。その場合には、別のタイミングで処理結果をユーザーに提供すれば良いわけです。
時間の問題で処理結果を待てない、あるいは処理結果がなくても次の処理に進められる、そんな場合にぜひ候補に入れていただきたいのが「非同期処理」です。
非同期処理の特徴は、リクエストの受付と処理の実施を分離できる点です。処理の完了を待つことなく受付の完了のみを応答するため、エンドユーザーに対する応答性の改善や処理能力の改善を図ることができます。
技術的な仕様でもこの非同期は考慮されており、一例として HTTP のプロトコル仕様が定義されている RFC 2616 では、HTTP のステータスとして「202 Accepted」といったものが定義されています。これは「リクエストを受け付けたが処理はまだ実施されていない」ということを示すステータスです。つまり、この HTTP ステータスを利用することで、処理が非同期で実施されていることをリクエスト元に伝えることができるわけです。
非同期処理の採用による処理能力の改善例として、宣伝などにより突如、EC サイトへのリクエスト数が増加するケースをイメージしてみましょう。同期処理の場合には、各リクエストに対してすべての処理を実施してからレスポンスを返しますので、急激なリクエスト数の増加にサーバーサイドの処理能力が追いつかない可能性があります。
もしかするとみなさまも、Web サイトにアクセスしたけどリクエスト過多でサーバーがダウンしている状況に遭遇したことがあるのではないでしょうか。このように、本来受けられるはずだったリクエストを受けられない状況は、エンドユーザーの顧客体験悪化や EC サイトにとっての機会損失に繋がります
非同期処理の場合、リクエストを受け付けた後すぐに処理を実施せず、一旦キューに入れて一次応答だけレスポンスすることが可能です。この方式の場合、比較的軽量な受付処理だけで応答するため、サービス提供側のリソース消費が同期処理に比べて軽くなるケースが多いです。これにより、サーバーがダウンするような状況を回避しやすくなります。(もちろん、キューはそのリクエスト数に対応できるスケーラビリティや可用性が求められます)。一旦リクエストはすべて受けておくことで、エンドユーザーにとっても EC サイトにとっても機会損失を避けることができます。
先述の「配送処理サービス」は、配送業者のシステムへデータを連携する必要があるため、処理に時間がかかるサービスでした。可能であれば即時結果を伝えることが望ましいかもしれませんが、今回のケースでは、在庫の確保を最短でお客様に回答し、具体的な配送日の情報は別のタイミング応答することが顧客体験として良いと考えたため、このサービスには非同期処理が向いていると言えます。
非同期処理はここまでにご紹介した利用者の立場だけでなく、開発者の立場でも拡張性や変更容易性などいくつものメリットを享受することができます。これについては、第 2 回以降で詳細をお伝えしたいと思いますのでご期待ください。
開発者向けの情報をより早く詳しく知りたい方は、AWS がお届けする Web セミナーシリーズ AWS DevAx::connect シーズン 1 「イベント駆動」で紹介された 第 1 回 イベント駆動アーキテクチャ入門 〜基本となる考え方から実装パターンまで〜 がございますのでぜひご覧ください。
ここまでの内容をまとめると、以下のように整理することができます。
処理の結果を待つ必要が "ある" サービス呼び出し
→"同期処理" で実現可能
「注文処理サービス」から「在庫管理サービス」の呼び出し
処理の結果を待つ必要の "ない" サービス呼び出し
→"非同期処理" で実現可能
「注文処理サービス」から「配送処理サービス」の呼び出し
クリックすると拡大します
クリックすると拡大します
みなさまがアプリケーションを実装する際、あるサービスを同期処理として呼び出したいと考えたとしても、呼び出すサービス側が非同期処理を前提としている場合もあるかと思います。そのような場合には、サービスを呼び出して受付完了の結果を受け取った後、ポーリング等によりサービスの処理完了をチェックするような実装方式があります。
あるいは、自身のアプリケーションが本当に結果を待つ必要があるのかを再考し、結果は待たずに別のタイミングでサービスの処理結果を後続処理に連携する方式もあります。これらも第 2 回以降で改めてご説明したいと思います。
同期処理と非同期処理は、決して排他的な存在ではありません。1 つのアーキテクチャ内で共存させることによって、さらなる価値を享受することができるのです。
まとめ
第 1 回目となる今回は、EC サイトを題材にして同期処理と非同期処理の使い分けを説明しました。
それぞれの処理は決して排他的な存在ではありません。1 つのアーキテクチャの中で特徴を理解しながら使い分けることで、エンドユーザにとって快適な Web サイトを構築することができます。
次回以降では、これら同期処理と非同期処理の技術面についてより深く解説すると共に、図を交えながら EC サイトを例にした論理構成や、AWS サービスを利用したアーキテクチャについて順次ご紹介していきます。
次回もぜひご覧いただけますと幸いです。それではまたお会いしましょう !
この連載記事のその他の記事はこちら
- 選択
- 第 1 回 非同期処理ってなんだろう ?
- 第 2 回 非同期処理と同期処理の処理構造
- 第 3 回 AWS サービスを活用した非同期処理アーキテクチャ
- 第 4 回 非同期処理の設計上の検討ポイント
筆者プロフィール
五十嵐 直人
アマゾン ウェブ サービス ジャパン合同会社
プロフェッショナルサービス本部 クラウドアプリケーションアーキテクト
クラウドアプリケーションアーキテクトとして、サーバーレスを中心としたアーキテクチャ設計やアプリケーション開発に取り組んでいます。技術を通してビジネス課題を解決すべく、日々活動しています。
最近は山とウイスキーが好きです。今年から雪山登山とテント泊をはじめました。
AWS を無料でお試しいただけます