Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【ITニュース解説】I didn't want Redis + workers just to run an HTTP request later

2026年10月01日に「Dev.to」が公開したITニュース「I didn't want Redis + workers just to run an HTTP request later」について初心者にもわかりやすく解説しています。

作成日: 更新日:

ITニュース概要

「後で実行する」処理はよくあるが、RedisやWorkerを使うとシステムが複雑になりがちだ。筆者は、HTTPリクエストを遅延実行し、失敗時には自動でリトライする「Asynclay」というサービスを開発した。これは複雑なワークフローではなく、HTTPエンドポイントの確実な後日実行に特化し、シンプルな連携で利用できる。

ITニュース解説

バックエンドアプリケーションの開発において、「この処理を後で実行したい」という要件は非常に頻繁に発生する。例えば、ユーザーが登録した後に確認メールを送る、購入された商品の注文処理を行う、外部の提携サービスに情報を連携する、時間のかかるレポートを非同期で生成する、あるいは一時的に失敗した処理をもう一度試す、といったケースだ。これらの処理は、ユーザーがウェブページを操作している最中にすぐに実行する必要はなく、少し遅れても問題ないことが多い。もしこれらの処理を即座に実行しようとすると、ユーザーは処理が完了するまで待たされることになり、ウェブサイトやアプリケーションの応答性が悪く感じられてしまう。

この「後で実行する」という要件を実現するために、多くのバックエンドシステムでは、比較的複雑なアーキテクチャが採用されてきた。典型的な構成は、まずユーザーからのリクエストを受け付けるAPIサーバーがあり、APIサーバーは、後で実行したい処理の内容をメッセージとして一時的に保存するデータベース(例えばRedisのような、高速なデータ保存・取得が可能なメモリベースのデータベース)に送る。このメッセージは「キュー」と呼ばれる待ち行列に格納される。そして、「ワーカー」と呼ばれる別のプログラムが、このキューからメッセージを順に取り出し、実際の処理を実行する。処理が失敗した場合には、自動的に再試行(リトライ)する仕組みや、システム全体の動作を監視する仕組みも組み込まれる。このようなAPI → Redis → キュー → ワーカー → リトライロジック → 監視といったアーキテクチャは、非常に複雑なバックグラウンド処理や、大量の処理を効率的に捌く必要がある場合には非常に強力で適切な選択肢となる。

しかし、もし「後で実行する」処理が、すでにHTTPリクエストとして表現できるような、よりシンプルなものである場合はどうだろうか。例えば、特定のURLに対してデータ(ペイロード)を送るだけで完了するような処理だ。このような場合でも、上記のような複雑なキューとワーカーのシステムを構築するのは、過剰に感じるかもしれない。開発者であるDavy氏も、この点に疑問を感じた。

この疑問から生まれたのが「Asynclay(アシンクレイ)」という新しいプロジェクトだ。Asynclayは、特定のHTTPエンドポイント(URL)へのリクエストを、指定された時間に、確実に、そして失敗した場合には自動で再試行しながら実行することを目的としている。その基本的なモデルは非常にシンプルで、アプリケーション → Asynclay → HTTPエンドポイント という流れになっている。

具体的には、アプリケーションは、実行したいHTTPリクエストのターゲットとなるURL、送りたいデータ(ペイロード)、そして必要であればいつ実行するかという実行時間をAsynclayに送信する。Asynclayはこれらの情報を永続的に保存し、指定されたタイミングで独立してHTTPリクエストを実行する。もしHTTPリクエストの実行に失敗した場合でも、Asynclayは自動的に再試行してくれる。そして、最終的に何が起こったか(成功したか、失敗したか、何回再試行したかなど)を記録し、ユーザーが確認できるようにする。

Asynclayは、このようなシンプルな機能を実現するために、内部的には分散システムの複雑な課題に取り組んでいる。分散システムとは、複数のコンピューターが連携して一つのシステムとして機能する仕組みのことだ。複数のAsynclayインスタンスが同時に動いていても、同じジョブ(HTTPリクエストの実行依頼)を重複して処理しないように、PostgreSQLというデータベースの特殊な機能(FOR UPDATE SKIP LOCKED)を使って、処理するジョブを安全に確保する仕組みが作られている。これは、複数の処理者が同時に一つのリストから仕事を選び取る際に、それぞれが異なる仕事を取るようにするための賢い方法だ。

また、もしジョブの実行中に、それを担当していたワーカー(Asynclayの内部で実際に処理を実行する部分)が予期せず停止してしまった場合でも、そのジョブが永遠に宙ぶらりんにならないように、「リース」という仕組みが導入されている。リースとは、ワーカーがジョブの処理権を一定期間だけ借りるようなもので、期間内に処理が終わらなければ、そのジョブは別のワーカーが処理できるように解放される。これにより、システム全体が停止することなく、処理が滞ることを防ぐ。

HTTPリクエストの配信については、「正確に1回」の配信(exactly-once)を保証することは、ネットワークの不安定性などにより技術的に非常に困難であり、現実的にはほぼ不可能である。そのためAsynclayは、「少なくとも1回」の配信(at-least-once)を保証するという方針を取っている。これは、ネットワークの問題などで一度のリクエストでは確実に届かない可能性があっても、最終的には必ずジョブが実行されるように、必要に応じて複数回リクエストが送られる可能性があるという意味だ。この際、ターゲットとなるHTTPエンドポイント側では、同じリクエストが複数回届いたとしても、システムの状態が矛盾しないように「冪等性(べきとうせい)」という性質を持たせる必要がある。冪等性とは、ある操作を何回繰り返しても、結果が同じになる、あるいはシステムの状態が同じになるという性質だ。Asynclayは、そのために安定したジョブ識別子をターゲットに提供し、ターゲット側で重複を検知・排除できるように配慮している。

リトライ(再試行)機能は、単に失敗したらすぐに再試行するだけでなく、失敗するたびに次の再試行までの間隔を徐々に長くする「バックオフ」という戦略を採用している。これにより、一時的な問題であればすぐに解決する可能性を高めつつ、根本的な問題がある場合には、システムに過度な負荷をかけずに問題解決の時間を与えられる。失敗した実行も監視可能で、何が起こったかを後から確認できる。

さらに、ユーザーはAsynclayに任意のURLをターゲットとして指定できるため、Asynclayの実行環境はセキュリティにも非常に注意を払っている。例えば、Asynclay自体が悪意のあるリクエストを勝手に生成して、外部からのサーバーに指示された不正なリクエストを内部ネットワークへ送信させる攻撃(SSRF:Server-Side Request Forgery)に利用されたり、プライベートなIPアドレス範囲へのアクセスを試みたり、DNSの変更や不審なリダイレクトを悪用されたりする可能性を考慮し、あらゆる外部へのリクエストを潜在的に危険なものとして扱って対策を講じている。

このようにAsynclayは、キューやワークフローシステム全般の代替を目指しているわけではない。もし複雑な処理の流れ(ワークフロー)、CPUを大量に消費するような計算、独自のカスタマイズされたワーカーが必要な場合、あるいはインフラの細部にわたる完全な制御が必要な場合には、BullMQのような既存の高性能なキューイングツールや、専用に構築されたワーカーシステムを使う方が適切だ。

Asynclayが最も力を発揮するのは、「HTTPエンドポイントがあり、それを後で実行したい。そして、失敗した場合には確実に再試行してほしい」という、より限定的で明確なユースケースだ。このような特定のニーズに対して、シンプルかつ信頼性の高いソリューションを提供することを目指している。現在、Davy氏は、Asynclayを実際に利用する開発者からのフィードバックを求めており、このモデルがどのような場面で限界を迎えるのか、あるいは外部サービスにバックグラウンド実行を任せることに抵抗を感じる点などについて意見を聞きたいと考えている。Asynclayは、既存のバックエンドシステムをシンプルにし、開発者が「後で実行する」という要件に悩むことなく、本来のアプリケーション開発に集中できるよう支援するツールとなるだろう。

関連コンテンツ

関連IT用語

関連ITニュース