春の再試行は、主に再試行とヒューズを実装するスプリングバッチから独立したエネルギー機能です。再試行にはシナリオ制限があり、すべてのシナリオが違法パラメーター検証、書き込み操作など、再試行に適しているわけではありません(書き込みが等身かどうかを考慮する必要があります)。リモートコールタイムアウトまたはネットワークの中断を再試行できます。マイクロサービスガバナンスフレームワークでは、通常、独自の再試行とタイムアウトの構成があります。たとえば、DubboはRETRIES = 1を設定し、タイムアウト= 500コールが失敗し、1回だけ再試行でき、500ミリ秒以上後に戻らないとコールが失敗します。春の再試行では、再試行する必要がある例外のタイプを指定し、各再試行の間隔を設定し、再試行が失敗した場合、再試行またはヒューズを継続するかどうか(再試行を停止)できます。
設計と実装
RetryOperations 、再試行APIを定義します。 RetryTemplateは、APIのテンプレートモード実装であり、再試行と回路の破壊を実装します。提供されたAPIは次のとおりです。
パブリックインターフェイスretryperations {<t、e extends throwable> t execute(retrycallback <t、e> retrycallback)スローe; } //他のAPIは省略されていますRetryCallback 、実行する必要がある操作を定義します。操作を定義した後、それはどのように再試行するかという問題です。 RetryTemplateさまざまな再試行戦略を策定することにより、再試行方法のロジックを実行します。デフォルトの再試行戦略はSimpleRetryPlicyです。つまり、3回再試行されます。再試行が成功した場合、再試行し続けることはありません。では、3フィートの再試行が失敗した場合はどうなりますか?プロセスは、ボトムアップの結果を終了または返します。ボトムアップの結果を返すには、 RecoveyCallBackを構成する必要があります。名前から、これはボトムアップコールバックインターフェイスであることがわかります。これは、再試行が失敗した後の実行のロジックです。 SimpleRetryPolicyに加えて、他の再試行戦略があります。 RetryPolicyインターフェイスを見てみましょう。
public interface retrypolicyはserializable {boolean canretry(retrycontextコンテキスト)を拡張します。 retryContext open(retryContext parent); void close(retrycontextコンテキスト); void RegisterThrowable(RetryContextコンテキスト、スロー可能なスロー可能);} canRetry 、再試行するたびに呼び出されます。もう一度試してみることができるかどうかの判断条件openレトリが開始される前に呼び出され、 RetryContextに再試行コンテキストが作成され、再生スタックが保存されます。
registerThrowableは、例外が再試行されるたびに呼び出されます(例外があり、再試行し続けます)
例としてSimpleRetryPolicyを取ります。再試行の数が3(デフォルト3回)に達すると、再試行を停止し、再試行の数が再試行のコンテキストで保存されます。
次の再試行戦略の実装を提供します。
再試行戦略とは、各再試行がすぐに再試行されるか、しばらく待ってから再試行するかどうかを指します。デフォルトでは、待機期間を構成してから再試行する必要がある場合は、バックオフポリシーBackoffRetryPolicy指定する必要があります。 BackOffretrypolicyには次の実装があります。
ステートフルな再試行または無国籍の再試行
いわゆるステートレス再試行とは、スレッドコンテキストで完了した再試行を指します。それ以外の場合、スレッドコンテキストで再試行が完了していない場合は、ステートフルな再試行です。以前のSimpleRetryPolicy 、再試行がループで完了したため、無国籍の再試行でした。それで、その後何が起こるか、または状態で再試行する必要があるのでしょうか?通常、トランザクションロールバックとサーキットブレーカーの2つの状況があります。
DataAccesSexceptionは例外的です。再試行は実行できませんが、他の例外がスローされている場合は、再試行できます。
ヒューズとは、現在のループでの再試行を処理するのではなく、グローバル再試行モード(スレッドコンテキストではない)を意味します。回路ブレーカーはループから飛び出し、スレッドコンテキストのスタック情報は必然的に失われます。その後、この情報を「グローバルモード」に保存する必要があります。現在の実装はキャッシュ(マップ実装)に配置されます。次回はキャッシュから取得した後も再試行し続けることができます。
クイックスタート
proxyTargetClass=trueが設定されている場合、再試行を実行する必要があるクラスで@EnableRetryを使用します。
@configuration@enableretry(proxytargetclass = true)@componentpublic class retryexamples {} Retries戦略の最大数に基づいて再試行します。再試行が3回繰り返され、例外がまだスローされ、再試行が停止し、ボトムアップコールバックが実行されます。したがって、最終的な出力結果はInteger.MAX_VALUEです。
private void retryexample3()throws exception {retrytemplate retrytemplate = new retrytemplate(); simpletertypolicy simpleretrypolicy = new simpleretrypolicy(); SimpleTetryPolicy.setMaxattempts(3); retrytemplate.setretrypolicy(simpleretrypolicy); integer result = retrytemplate.execute(new retrycallback <integer、例外>(){int i = 0; // operation @override public integer dowithretry(retrycontext retrycontext)スロー{log.info( "retry count:{}"、retrycontext.getretrycount({}; }、new RecoverCallback <Integer>(){// base callback @Override public integer Recover(RetryContext RetryContext)スロー{"log.info:{}、recover call!"、retrycontext.getretrycount(); log.info( "final result:{}"、result); } private int len(int i)スロー例外{if(i <10)スロー新しい例外(i + "le 10");私を返します。 }以下は、回路ブレーカー再試行ポリシーモード(CirdingBreakErretretryPolicy)の使用方法について説明します。次の3つのパラメーターを設定する必要があります。
サーキットブレーカーの開設と閉鎖判断:
テストコードは次のとおりです。
retrytemplateテンプレート= new retrytemplate(); circuit BreakErretryTolyPolicy retrypolicy = new Circuit BreakErretretryPolicy(new simpleretrypolicy(3)); retrypolicy.setopentimeout(5000); retrypolicy.setresettimeout(20000); template.setretrypolicy(retrypolicy); for(int i = 0; i <10; i ++){//thread.sleep(100); try {object key = "circuit"; boolean isforcerefresh = false; retrystate state = new Defaultretrystate(key、isforcerefresh); string result.execute(new retrycallback <string、runtimeexception>(){@override public string dowithretry(retrycontext context)throws runtimeexception {log.info( "retry count:{}"、context.getretrycount(); {@Overrideパブリック文字列回復(retryContextコンテキスト)スロー{default "}、state); log.info( "result:{}"、result); } catch(Exception e){System.out.println(e); }} isForceRefresh = falseが設定されるため、 key = "circuit" (つまり、retrycontext)の値がキャッシュから取得されます。したがって、再試行が失敗し、 this.time < this.openWindowが融合している場合、グローバルモードで再試行を実装し続けることができます(取得したRetryContextは同じです)。
注釈開発
RetryTemplate作成するたびにRetryの要件が肥大化しすぎると、注釈を使用することで開発を大幅に簡素化し、重複コードを削減できます。注釈を使用して実装された最大の再試行戦略の再試行です。
@retryable(value = sqldataexception.class、backoff = @backoff(value = 0l))public string service3()throws sqldataexception {log.info( "service3 open");新しいsqldataexception(); } @Recover public String Recover(sqldataexception ne){return "sqldataexception recover"; }注釈は次のとおりです。
@enableretry
@retryable
@回復する
@backoff
@circuitbreaker
@enableretry:もう一度やり直してもらえますか? ProxyTargetClassプロパティがTRUE(デフォルトのFALSE)の場合、CGLIBプロキシを使用します
@retryable:注釈を再試行する必要がある方法
@backoff:フォールバック戦略を再試行します(今すぐ試すか、もう一度試す前にしばらく待ちます)
@Recover:メソッドで使用します。 @retryableが失敗した場合、「保証された」メソッドとして使用されます。 @Recover Annotationの方法は、@retryable Annotationのメソッド「署名」と一致する必要があります。最初のエントリパラメーターは、再試行する例外です。他のパラメーターは@retryableと一致しています。返品値は同じでなければなりません。そうしないと、実行できません!
@circuitbreaker:メソッドに使用、回路壊しモードを実装します。
その他の例については、私のgithub(https://github.com/happyxiaofan/springboot-rearning-example)のスターへようこそ。ありがとう
上記はこの記事のすべての内容です。みんなの学習に役立つことを願っています。誰もがwulin.comをもっとサポートすることを願っています。