デッドライン
信頼性の低いバックエンドを効果的に処理するためにデッドラインがどのように使用できるかを説明します。
デッドライン
概要
デッドラインとは、クライアントがサーバーからの応答を待つつもりがない時点を指定するためのものです。この単純な考え方は、堅牢な分散システムを構築する上で非常に重要です。不必要に待機しないクライアントと、リクエストの処理をいつ中止すべきかを知っているサーバーは、システムのリソース利用率とレイテンシーを向上させます。
一部の言語APIにはデッドラインという概念がありますが、他のAPIではタイムアウトという考え方を使用していることに注意してください。APIがデッドラインを要求する場合、呼び出しがその時点を超えてはならない時間を指定します。タイムアウトは、呼び出しが許容される最大時間です。タイムアウトは、アプリケーションが呼び出しを開始する際に現在の時間にタイムアウトを加算することでデッドラインに変換できます。簡単にするために、このドキュメントではデッドラインのみを参照します。
クライアント側のデッドライン
デフォルトでは、gRPCはデッドラインを設定しないため、クライアントが実質的に無限に応答を待ってしまう可能性があります。これを避けるためには、常にクライアントで現実的なデッドラインを明示的に設定する必要があります。適切なデッドラインを決定するには、システムの特性(ネットワークレイテンシー、サーバー処理時間など)に基づいた推測から開始し、負荷テストによって検証するのが理想的です。
サーバーがリクエスト処理中にデッドラインを超過した場合、クライアントは処理を中止し、DEADLINE_EXCEEDEDステータスでRPCを失敗させます。
サーバー側のデッドライン
サーバーは、クライアントから非現実的に短いデッドラインを持つRPCを受信する可能性があります。これにより、サーバーは応答を間に合わせるための十分な時間を確保できなくなり、貴重なリソースを浪費し、最悪の場合、サーバーをクラッシュさせる可能性があります。gRPCサーバーは、クライアントによって設定されたデッドラインが経過すると、自動的に呼び出しをキャンセルする(CANCELLEDステータス)ことで、この状況に対処します。
RPCのサービスのために開始したアクティビティを停止する責任は、サーバーアプリケーションにあることに注意してください。長時間実行されるプロセスを実行している場合は、それを開始したRPCがキャンセルされたかどうかを定期的にチェックし、キャンセルされた場合は処理を停止する必要があります。
デッドラインの伝播
サーバーが応答を生成するために別のサーバーを呼び出す必要がある場合があります。サーバーもクライアントとして機能するこれらのケースでは、元のクライアントによって設定されたデッドラインを尊重したいと思うでしょう。一部のgRPC実装では、着信RPCから発信RPCへのデッドラインの自動伝播がサポートされています。一部の言語では、この機能は明示的に有効にする必要があります(例: C++)、他の言語ではデフォルトで有効になっています(例: JavaおよびGo)。この機能を使用すると、各発信RPCのデッドラインを手動で含めるというエラーが発生しやすいアプローチを回避できます。
デッドラインは特定の時点であるため、そのままサーバーに伝播すると、両サーバーの時計が同期していない場合に問題が発生する可能性があります。この問題に対処するために、gRPCはデッドラインをタイムアウトに変換し、既に経過した時間を差し引きます。これにより、クロックスキューの問題からシステムを保護します。
%%{init: { "sequence": { "mirrorActors": false }}}%%
sequenceDiagram
participant c as Client
participant us as User Server
participant bs as Billing Server
note right of c: Request at 13:00:00<br>Should complete in 2s
activate c
c ->> us: GetUserProfile<br>(deadline: 13:00:02)
activate us
note right of us: 0.5s spent before<br>calling billing server
us ->> bs: GetTransactionHistory<br>(timeout: 1.5s)
activate bs
bs ->> bs: Retrieve transactions
note left of bs: It's 13:00:02<br>Time's up!
note right of c: Stop waiting for server
c ->> c: Stop waiting for server<br>DEADLINE_EXCEEDED
deactivate c
us ->> us: Stop waiting for server
us -->> c: Cancel
deactivate us
bs -->> us: Cancel
bs ->> bs: Clean up resources<br>(after noticing that the<br>call was cancelled)
deactivate bs
言語サポート
| 言語 | 例 |
|---|---|
| Java | Javaの例 |
| Go | Goの例 |
| C++ | C++の例 |
| Python | Pythonの例 |