マイクロサービスのタイムアウト配信を理解するための 1 つの記事

藏色散人
リリース: 2021-10-18 16:06:59
転載
2406 人が閲覧しました

タイムアウト制御が必要なのはなぜですか?

多くの連鎖的な障害シナリオでよくある問題は、サーバーがクライアントの期限をすでに超えているリクエストを処理するために大量のリソースを消費していることです。その結果、サーバーは価値のある処理を何も行わずに大量のリソースを消費してしまいます。タイムアウトしたリクエストに返信しても意味がありません。

タイムアウト制御は、サービスの安定性を確保するための重要な防御線であると言えます。その本質はフェイルファストであることです。優れたタイムアウト制御戦略により、高レイテンシーのリクエストをできるだけ早くクリアし、リソースをすぐに解放できます。リクエストの蓄積を可能な限り回避します。

サービス間のタイムアウト配信

リクエストに複数のステージがある場合 (一連の RPC 呼び出しで構成される場合など)、サービスは各ステージの開始前にチェックする必要があります。期限は無駄な作業を避けるため、つまりリクエストを処理するのに十分な時間が残っているかどうかを確認するためのものです。

一般的な実装エラーは、各 RPC サービスに固定タイムアウトを設定することです。各サービス間でタイムアウトを渡す必要があります。タイムアウトは、最初のリクエストによってサービス呼び出しのトップレベルで設定できます。トリガーされた RPC ツリーには、同じ絶対期限が設定されます。たとえば、サービス リクエストの最上位でタイムアウトを 3 秒に設定します。サービス A がサービス B をリクエストします。サービス B の実行には 1 秒かかります。その後、サービス B がサービス C をリクエストします。このとき、タイムアウト時間は 2 秒のままです。サービス C には時間がかかります。実行まで 1 秒。これは、サービス C がサービス D を要求したとき、サービス D の実行には 500 ミリ秒かかるなどです。理想的には、同じタイムアウト配信メカニズムが呼び出しチェーン全体で使用されます。

マイクロサービスのタイムアウト配信を理解するための 1 つの記事

タイムアウト配信メカニズムが使用されていない場合、次の状況が発生します。

  1. サービス A がサービス B にリクエストを送信し、 set timeout 時間は 3 秒です。
  2. サービス B はリクエストの処理に 2 秒かかり、サービス C のリクエストを継続します。
  3. タイムアウト配信を使用する場合、サービス C のタイムアウト期間は 1 秒である必要がありますが、ここではタイムアウト配信が使用されているため、タイムアウト時間は構成で 3 秒プログラムされています
  4. サービス C の継続的な実行には 2 秒かかります。実際には、最上位層によって設定されたタイムアウトはこの時点で期限切れになり、次のようになりますリクエストは無意味です
  5. リクエストを続行しますサービス D

サービス B がタイムアウト配信メカニズムを採用している場合、期限に達しており、サービス C でリクエストは直ちに破棄される必要があります。クライアントがエラーを報告した可能性があります。タイムアウト配信を設定する場合、ネットワークの送信時間やクライアントが応答を受信した後の処理時間を考慮して、通常は配信期限を 100 ミリ秒などに短縮します。

プロセス内タイムアウト送信

Mysql、Redis、MySQL など、サービス間のタイムアウト送信だけでなく、プロセス内でのタイムアウト送信も必要です。プロセス内でシリアルに呼び出されます。サービス B の場合、合計リクエスト時間を 3 秒に設定します。Mysql をリクエストしてから、再度 Redis をリクエストするのに 1 秒かかります。タイムアウトは 2 秒です。Redis を実行してからサービス B をリクエストするのに 500 ミリ秒かかります。タイムアウトは各ミドルウェアまたはサービスが構成ファイルで固定タイムアウトを設定するため、残り時間と設定時間の最小値を取得する必要があります。

マイクロサービスのタイムアウト配信を理解するための 1 つの記事

context はタイムアウト配信を実装します

コンテキストの原理は非常に単純ですが、関数は非常に強力であり、 go も実装されました コンテキストのサポートに加えて、さまざまなオープンソース フレームワークでもコンテキストのサポートが実装され、コンテキストが標準となり、タイムアウト配信もコンテキストに依存します。

通常、タイムアウトを 3 秒に設定するなど、タイムアウト制御転送のためにサービスの最上位層に初期コンテキストを設定します。

ctx, cancel := context.WithTimeout(context.Background(), time.Second*3)defer cancel()
ログイン後にコピー

コンテキスト転送が実行されるとき (たとえば、上図の場合、以下の方法で残り時間を取得し、Redis が設定しているタイムアウトと比較して小さい方の時間を取得します

dl, ok := ctx.Deadline()
ログイン後にコピー
timeout := time.Now().Add(time.Second * 3)if ok := dl.Before(timeout); ok {
    timeout = dl}
ログイン後にコピー

サービス間のタイムアウト転送とは、主に RPC 呼び出し時のタイムアウト転送を指します。追加の処理については、gRPC 自体がタイムアウト配信をサポートしています。原理は上記と同様です。メタデータを通じて配信され、最終的には次のように grpc-timeout の値に変換されます。コード grpc-go/internal/transport/handler_server. go:79

if v := r.Header.Get("grpc-timeout"); v != "" {
        to, err := decodeTimeout(v)
        if err != nil {
            return nil, status.Errorf(codes.Internal, "malformed time-out: %v", err)
        }
        st.timeoutSet = true
        st.timeout = to}
ログイン後にコピー

タイムアウト配信はサービスの安定性を確保するための重要な防御線です。原理と実装は非常にシンプルです。タイムアウトあり配信はフレームワークに実装されていますか?そうでない場合は、すぐに行動を起こしてください。

go-zero

go-zero でのタイムアウト配信は、構成ファイル API ゲートウェイTimeout および # # を通じて構成できます。 #rpc サービスのタイムアウト。サービス間で自動的に渡されます。

前の

記事では、Go タイムアウト コントロールの実装方法を理解しています。 タイムアウト コントロールの使用方法について説明しています。

参考

「SRE: Googleの運用とメンテナンスの復号化」

プロジェクトアドレス

github。 com /zeromicro/go-zero

go-zerostar/fork を使用して私たちをサポートしてください。

推奨: 「

golang チュートリアル

以上がマイクロサービスのタイムアウト配信を理解するための 1 つの記事の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:learnku.com
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート