[マイクロサービス アーキテクチャ設計] マイクロサービスは魔法ではない: 処理タイムアウト

マイクロサービスは重要です。これらは私たちのアーキテクチャとチームにとってかなり大きな勝利につながる可能性がありますが、マイクロサービスには多額のコストもかかります。マイクロサービス、サーバーレス、その他の分散システム アーキテクチャが業界でさらに普及するにつれて、それらの問題とそれらを解決するための戦略を内面化することが重要です。この記事では、ネットワーク境界によって引き起こされる可能性のある多くのやっかいな問題の一例であるタイムアウトについて検討します。

「分散システム」という用語を恐れる前に、Node バックエンドを備えた小さな React アプリや、AWS Lambda と通信する単純な iOS クライアントでも、分散システムを表すことを思い出してください。このブログ投稿を読んでいるあなたは、Web ブラウザ、コンテンツ配信ネットワーク、ファイル ストレージ システムを含む分散システムにすでに参加していることになります。

背景として、選択した言語で API 呼び出しを実行し、その成功と失敗を処理する方法を理解していることを前提とします。ただし、それらの API 呼び出しが同期か非同期か、HTTP かどうかは関係ありません。馴染みのない用語やアイデアが出てきても、心配しないでください。Twitter やその他の場所でさらに議論できることを嬉しく思い、必要に応じてリンクを追加するように努めました。

私たちが調査しようとしている問題は次のとおりです。非常に遅い API 呼び出しがあり、最終的にはタイムアウトになり、(a) 成功するか、(b) 失敗すると仮定する場合、バグがあることになります。タイムアウト (さらに悪いことに、無限に長い待機) は分散システムの基本的な事実であり、タイムアウトに対処する方法を知る必要があります。

質問


思考実験から始めましょう。同僚に何かを依頼するためにメールを送信したことがありますか?

  • [火曜日、午前 9 時 58 分] あなた: 「ねえ、当社のメンタ​​ー候補リストに私を加えてくれませんか?」

  • 同僚:"……"

  • [金曜日、午後 2 時 30 分] あなた: [?]

あなたは何をするべきか?

要求を満たしたい場合は、最終的には応答がないことを確認する必要があります。もっと待ってもらえますか?どれくらい待ちますか?

では、どれくらい待つかを決めたら、どのようなアクションをとりますか? もう一度メールを送信してみましたか? さまざまなコミュニケーション媒体を試してみますか? 彼らはそんなことはしないと思いますか?

さて、ここで一体何が起こっているのでしょうか?このリクエストとレスポンスの動作を見てみましょう。

05299aecbcbd799a98f6b626054ad491.png

しかし、何か問題が発生しました。いくつかの可能性があります:

  • 彼らはそのメッセージを決して受け取りませんでした。

9e39a000a5bd4be590e7a13d61bc937c.png

  • 彼らはメールを受け取り、それを正常に処理し、あなたから何も聞いていない返信をあなたに送り返しました(またはスパムフォルダに移動しました)。

fa52b63d6632b1ff09c90f0e9d5429a1.png

  • 彼らは情報を手に入れましたが、まだそれについて考えているか、情報を失っているか、[息を呑む! ] 彼らは忘れていました。

396f44aba9b73bedaa30f2ea70254853.png

  • 結局のところ、私たちは知らないだけなのです!

44ea42fdc2caea02bb31f790c9a9281b.png

この問題は、分散システム上のあらゆる通信で発生します。

当社はリクエスト、処理、または応答に遅延が生じる場合があり、これらの遅延は任意に長くなる場合があります。したがって、電子メールの例と同様に、 「どれくらい待つ必要がありますか?」という質問に対する答えがあることを確認する必要があり、その期間をタイムアウトと呼びます。

この記事から 1 つのレッスンだけを学ぶ場合は、timeouts を使用してください。そうしないと、完了しない操作を永遠に待つことになる危険があります。

しかし、待機時間の上限であるタイムアウトに達したらどうすればよいでしょうか?

方法


リモート システム コールでタイムアウトが発生する一般的な方法がいくつかあります。このリストが網羅的であるとは主張しませんが、私がこれまでに見た最も一般的なシナリオの多くをカバーしています。

方法1


タイムアウトが発生した場合は、成功したものとみなし、次に進みます。

これはやめてください。[1] 残念ながら、これは実稼働アプリケーションでもよくある意図的でない選択であり、UX にかなり悪い影響を与えると言わざるを得ません。手術が成功したと仮定すると、私たち貧しい消費者は当然うまくいったと考えるでしょうが、後で結果を知ったときに失望し混乱するだけです。

ネットワーキング会議があるときは、成功と失敗を確認してください。たとえば、JavaScript で Promise.then(...) 経由で非同期 API を使用している場合は、対応する .catch(...) がどこにあるのかを自問してください。それが見つからない場合は、ほぼ確実にバグがあります。

非常に特殊なケースでは、当然のことながら、リクエストが成功するか失敗するかを気にしないこともあります。UDP は、この特性を備えた非常に成功したプロトコルです。さらに、多くのソフトウェアが壊れていますが、とにかくお金を稼ぎ続けてください。ただし、これをデフォルトにしないでください。最初に他のオプションをすべて検討してください。

方法 #2


読み取りリクエストの場合は、キャッシュまたはデフォルトを使用します。

リクエストが読み取りリクエストであり、リモート側に影響を与えるつもりがない場合は、これが良い選択となる可能性があります。この場合、以前に成功したリクエストからキャッシュされた値を使用できます。あるいは、成功したリクエストがまだない場合、またはキャッシュが意味をなさない場合は、デフォルトを使用することもできます。このアプローチは比較的単純であり、パフォーマンスのオーバーヘッドや実装の複雑さはあまり追加されません。ただし、ネットワーク経由でアクセスされるアウトプロセス キャッシュ (memcached、Redis など) を使用している場合は、そのような状態に戻ることになり、リクエストがキャッシュに対してタイムアウトになる可能性があることに注意してください。それ自体

方法 #3

タイムアウトが発生した場合は、リモート操作が失敗したものとみなされ、自動的に再試行されます。

これにより、さらに次のような疑問が生じます。

  • 再試行するのが安全でない場合はどうすればよいですか? ネットワーク接続の反対側のサービスが重複するのはただ迷惑なのでしょうか? それともクレジットカードに二重請求していませんか?(!)

  • 再試行は同期的に行うべきでしょうか、それとも非同期的に行うべきですか?

  • 同期的に再試行すると、消費者の観点から見ると、それらの再試行によって速度が低下することになります。消費者の期待に応えられない可能性はありますか? これは、エンドユーザー アプリケーションではなく、サービスにおいて特に重要です。

  • 非同期で再試行する場合、操作の成功について消費者に何を伝えることになりますか? 一度に 1 つずつ試しますか、それとも一定期間にわたってバッチで再試行しますか?

  • 何回再試行する必要がありますか? (1回?2回?10回?成功するまで?)

  • 再試行までの時間をどのように遅らせる必要がありますか? (指数バックオフ [例: 1 秒、2 秒、4 秒、8 秒、16 秒、...] は最大レイテンシーによって制限されますか? ディザリングを使用しますか?)

  • リモート サーバーに過負荷によるパフォーマンスの問題がある場合、再試行するとパフォーマンスが悪化しますか?

リモート API が安全に再試行できる場合、それをべき等と呼びます。冪等プロパティがないと、 (クレジット カード請求の場合のように) 重複データが作成されたり、競合状態が発生したりする可能性があります (つまり、電子メール アドレスを 2 回変更しようとし、2 回目の変更が完了した後に最初の再試行が行われた場合など)。

自動再試行を安全にするには、多くの場合、アーキテクチャ上で多大な労力が必要になる場合があります。ただし、安全に再試行できる場合 (たとえば、リクエスト UUID を送信し、リモート側でこれらを追跡する)、物事は非常に簡単になります。この動作の良い例については、Stripe API を確認してください。

方法 #4


リクエストが成功したかどうかを確認し、安全であれば再試行してください。

ここでの考え方は、場合によっては、タイムアウトしたリクエストの後に別のリクエストをフォローアップして、元のリクエストのステータスを尋ねることができるということです。このアプローチには、明らかに、必要な情報を提供できるエンドポイントの存在が必要です。このようなエンドポイントを想定すると、エンドポイントがリクエストが成功したと示した場合、再試行する必要はないと明示的に言えます。

しかし、ここには重大な問題があります。再試行しても安全かどうかは実際にはわかりません。通常、リモート サービスはリクエストを受信できますが、まだ処理中であるため、チェックしているクエリ エンドポイントは成功を確認できませんもちろん、チェック自体がタイムアウトになる可能性もあります。最初の障害と同じ理由でリモート サーバーに完全にアクセスできない可能性がありますが、たとえそれが本当だとしても、問題が最初のリクエストの処理前に発生したのか、処理後に発生したのかを知る方法はまだありません。

方法 #5


諦めてユーザーに理解してもらいましょう。

これにより必要な労力が最小限に抑えられ、間違いなく間違った決定を下すことを防ぐことができるため、多くの場合、これが最良の選択肢となる可能性があります。また、「ユーザーは正しい行動を見つけられるだろうか?」と自問する必要もあります。彼らは、前進する方法を決定するのに十分な情報と他のシステムに関する洞察を持っていますか?

場合によっては、消費者にこの問題について知らせたほうがよい場合もあります。再試行を伴うメソッドの場合、無限回の再試行を許可したくない場合は、最終的にこの道に戻る可能性があります。

結論は


したがって、現時点では状況は暗いように見えるかもしれません。分散システムは難しく、これらのソリューションの 1 つだけを万能薬として選択することはできないようです。失敗したと感じたら、勇気を出して、完璧を善の敵にしないでください。

タイムアウトを使用します。


すべてのネットワーク リクエストには、タイムアウトが 5 秒、10 秒、またはそれ以上など長い場合でも、ある程度のタイムアウトが必要です。タイムアウトの選択は難しい場合があります。リクエストが最終的に成功するときに、あまりにも多くの失敗 (誤検知) が発生することは望ましくありません。また、あまりにも多くの時間を無駄にしてアプリケーションが異常な状態になるリスクも避けたいと考えます。過去のリクエストの分布と傾向、およびアプリケーション独自のパフォーマンス保証やリスク プロファイルを確認することで、適切な値を決定できます。

いかなる状況でも、アプリケーション サーバーのキュー、接続プール、リング バッファ、その他のボトルネックが、永遠に待機するもので詰まるのは望ましくありません。本番環境のニーズに応じて、サーキット ブレーカーやバルクヘッドなどのより高度なものを調査して追加することはできますが、タイムアウトは安価で、ライブラリによって十分にサポートされています。それらを使用してください!

デフォルトで再試行を安全にします。


コードをよりシンプルかつ安全にすることに加えて、「冪等性」について話しているのは興味深いですね。

仕事を別の方法で委任することを検討してください。


非同期メッセージングには、リモート サービスが高速かつ可用性である必要がなくなり、メッセージ ブローカーだけが高速かつ可用性を実現できるため、いくつかの魅力的な特性があります。ただし、メッセージング/非同期性は万能薬ではありません。ブローカーがメッセージを受信することを確認する必要があります残念ながら、これは難しいかもしれません。メッセージ ブローカーにもトレードオフがあります。ユーザーは、いつ再試行する必要があるかを知ることができます。たとえば、メッセージ処理に遅延があった場合、注文が注文履歴にまだ表示されていないため、再送信することを決定する可能性があります。分散ロギング/ストリーミング プラットフォームでも同様の問題が発生する可能性があります。メッセージング ルートを検討している場合は (そうでない場合でも)、Enterprise Integration Patterns をよく見てください。古いものにもかかわらず、そのパターンは今日のアーキテクチャに非常に関連しています。

そして、パーティーのうんちになる危険を承知で、ネットワーク境界を完全に移動または削除できる可能性があることを忘れないでください。難しい問題を簡単な問題に変えることは恥ずかしいことではありません。したがって、5 つのネットワーク リクエストの代わりに 1 つのネットワーク リクエストを使用したり、2 つのサービスを一緒にインライン化したりすることもできます。あるいは、上記のアプローチのいずれかを使用して、信頼性が高く安全な方法でタイムアウトを処理することもできます。どちらの方法を選択する場合でも、ユーザーはマイクロサービスを使用するかどうかを気にしていないことを忘れないでください。ユーザーは単に物事が機能することを望んでいるだけです。

この記事: https://architect.pub/microservices-arent-magic-handling-timeouts
ディスカッション: Knowledge Planet [チーフ アーキテクト サークル] または WeChat トランペット [ca_cto] を追加するか、QQ グループを追加します [792862318]
一般公開なし
 
【jiagoushipro】
【スーパーアーキテクト】
アーキテクチャの方法論、アーキテクチャの実践、技術原則、技術トレンドについての鮮やかなグラフィックと詳細な説明。
お待ちしておりますので、ぜひスキャンしてご注目ください。
WeChatのトランペット
 
[ca_cea]
エンタープライズ アーキテクチャ、クラウド コンピューティング、ビッグ データ、データ サイエンス、モノのインターネット、人工知能、セキュリティ、フルスタック開発、DevOps、デジタル化について議論する 50,000 人のコミュニティ。
 

QQグループ
 
[285069459] エンタープライズ アーキテクチャ、ビジネス アーキテクチャ、アプリケーション アーキテクチャ、データ アーキテクチャ、技術アーキテクチャ、統合アーキテクチャ、セキュリティ アーキテクチャの詳細な交換。そして、ビッグデータ、クラウドコンピューティング、モノのインターネット、人工知能などのさまざまな新興テクノロジー。
QQ グループに参加して、貴重なレポートや乾物を共有してください。

ビデオ番号 【スーパーアーキテクト】
建築に関する基本的な概念、モデル、手法、経験が1分ですぐに理解できます。
1日1分、仕組みはおなじみです。

知識の惑星 [チーフアーキテクトサークル] 著名人に質問したり、連絡を取ったり、プライベートな情報を共有したりしてください。  

ヒマラヤ [スーパーアーキテクト] 最新のブラックテクノロジー情報と建築体験を道路や車の中で学びましょう。 [知的な瞬間、ミスター・アーキテクチャーがブラックテクノロジーについて語ります]
知識の惑星 より多くの友人、職場、技術的なチャットに会いましょう。 ナレッジプラネット【職場とテクノロジー】
リンクトイン ハリー https://www.linkedin.com/in/architect-harry/
LinkedInグループ LinkedIn アーキテクチャ グループ https://www.linkedin.com/groups/14209750/
微博 【スーパーアーキテクト】 賢い瞬間‍
ビリビリ 【スーパーアーキテクト】

チクタク 【cea_cio】スーパーアーキテクト

早い労働者 【cea_cio_cto】スーパーアーキテクト

小さな赤い本 [cea_csa_cto] スーパーアーキテクト  

Webサイト CIO(最高情報責任者) https://cio.ceo
Webサイト CIO、CTO、CDO https://cioctocdo.com
Webサイト アーキテクトの実践的な共有 https://architect.pub   
Webサイト プログラマーによるクラウド開発の共有 https://pgmr.cloud
Webサイト チーフアーキテクトコミュニティ https://jiagoushi.pro
Webサイト アプリケーション開発と開発プラットフォーム https://apaas.dev
Webサイト 開発情報ネットワーク https://xinxi.dev
Webサイト スーパーアーキテクト https://jiagou.dev
Webサイト 企業向け技術トレーニング https://peixun.dev
Webサイト プログラマーの本 https://pgmr.pub    
Webサイト 開発者チャット https://ブログ.開発者.チャット
Webサイト CPOコレクション https://cpo.work

ご清聴、転送、いいね、ご視聴ありがとうございます。

おすすめ

転載: blog.csdn.net/jiagoushipro/article/details/131950667