締め切り
信頼性の低いバックエンドに効果的に対処するために締め切りをどのように使用できるかを説明します。
締め切り
概要
締め切りは、クライアントがサーバーからの応答を待つことを望まない時点を指定するために使用されます。このシンプルなアイデアは、堅牢な分散システムを構築する上で非常に重要です。不必要に待機しないクライアントと、リクエストの処理をいつ諦めるべきかを知っているサーバーは、システムのリソース使用率とレイテンシを向上させます。
一部の言語APIには**締め切り**の概念がありますが、他の言語APIは**タイムアウト**の概念を使用することに注意してください。APIが締め切りを要求する場合、リクエストが過ぎてはならない時点を指定します。タイムアウトは、リクエストが実行できる最大時間です。簡単にするために、このドキュメントでは締め切りについてのみ説明します。
クライアント側の締め切り
デフォルトでは、gRPCは締め切りを設定しません。これは、クライアントが事実上永遠に応答を待つことになる可能性があることを意味します。これを回避するには、常にクライアントに現実的な締め切りを明示的に設定する必要があります。適切な締め切りを決定するには、システム(ネットワークレイテンシ、サーバー処理時間など)に関する知識に基づいた推測から始め、負荷テストによって検証するのが理想的です。
サーバーがリクエストの処理中に締め切りを過ぎた場合、クライアントは諦めて、`DEADLINE_EXCEEDED`ステータスでRPCを失敗させます。
サーバー側の締め切り
サーバーは、クライアントから非現実的に短い締め切りでリクエストを受け取る場合があります。これにより、サーバーが時間内に応答するのに十分な時間が与えられなくなります。これは、サーバーが貴重なリソースを無駄にするだけであり、最悪の場合、サーバーがクラッシュする可能性があります。 gRPCサーバーは、クライアントによって設定された締め切りが過ぎると、自動的にコールをキャンセル(`CANCELLED`ステータス)することで、この状況に対処します。
サーバーアプリケーションは、リクエストを処理するために生成したアクティビティを停止する責任があります。アプリケーションが長時間実行されるプロセスを実行している場合は、それを開始したリクエストがキャンセルされたかどうかを定期的にチェックし、キャンセルされた場合は処理を停止する必要があります。
締め切りの伝播
サーバーは、応答を生成するために別のサーバーを呼び出す必要がある場合があります。サーバーがクライアントとしても機能する場合、元のクライアントによって設定された締め切りを尊重する必要があります。受信リクエストから送信リクエストへの締め切りの自動伝播は、一部のgRPC実装でサポートされています。一部の言語では、この動作を明示的に有効にする必要があり(例:C ++)、他の言語ではデフォルトで有効になっています(例:JavaおよびGo)。この機能を使用すると、各送信RPCの締め切りを手動で含めるというエラーが発生しやすいアプローチを回避できます。
締め切りは設定された時点であるため、それをそのままサーバーに伝播すると、2つのサーバーのクロックが同期されていない可能性があるため、問題が発生する可能性があります。これを解決するために、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++ | |
Python | Pythonの例 |