Retry Spring هي وظيفة طاقة مستقلة عن دفعة الربيع ، والتي تنفذ بشكل أساسي إعادة المحاولة والفتيل. هناك قيود على السيناريو لإعادة المحاولة ، وليس كل السيناريوهات مناسبة لإعادة المحاولة ، مثل التحقق غير القانوني للمعلمة ، وعمليات الكتابة ، وما إلى ذلك (تحتاج إلى النظر في ما إذا كانت الكتابة غير معلقة) ليست مناسبة لإعادة المحاولة. يمكن إعادة إعادة محاولة مهلة الاتصال عن بعد أو انقطاع الشبكة. في إطار إدارة الخدمات المجهرية ، عادة ما يكون له تكوين إعادة المحاولة والتهمة المهلة. على سبيل المثال ، يمكن لـ Dubbo تعيين إعادة محاكاة = 1 ، المهلة = 500 فشل المكالمة وإعادة المحاولة مرة واحدة فقط ، وفشل المكالمة إذا لم تعود بعد أكثر من 500 مللي ثانية. في ربيع الربيع ، يمكنك تحديد نوع الاستثناء الذي يحتاج إلى إعادة إعادة المحاولة ، وتعيين الفاصل الزمني لكل إعادة المحاولة وإذا فشلت إعادة المحاولة ، سواء للاستمرار في إعادة المحاولة أو فتيل (توقف عن إعادة المحاولة).
التصميم والتنفيذ
تحدد RetryOperations API Retry. RetryTemplate هو تنفيذ وضع القالب في واجهة برمجة التطبيقات ، التي تنفذ عملية إعادة المحاولة وكسر الدائرة. واجهة برمجة التطبيقات المقدمة كما يلي:
إعادة تشغيل الواجهة العامة {<t ، e يمتد remable> t تنفيذ (RetryCallback <t ، e> retrycallback) رمي e ؛ } // تم حذف واجهات برمجة التطبيقات الأخرى يحدد RetryCallback العملية التي يجب تنفيذها. بعد تحديد العملية ، إنها مسألة كيفية إعادة المحاولة. تنفذ RetryTemplate منطق كيفية إعادة المحاولة عن طريق صياغة استراتيجيات إعادة المحاولة المختلفة. استراتيجية إعادة المحاولة الافتراضية هي SimpleRetryPlicy ، مما يعني أنه سيتم إعادة إعادة محاولته 3 مرات. إذا نجحت إعادة المحاولة ، فلن تستمر في المحاولة مرة أخرى. فماذا لو فشلت إعادة محاولة 3 أقدام؟ تنتهي العملية أو تُرجع النتيجة من أسفل إلى أعلى. لإرجاع النتيجة من أسفل إلى أعلى ، تحتاج إلى تكوين RecoveyCallBack . من الاسم ، يمكنك أن ترى أن هذه واجهة رد اتصال من أسفل إلى أعلى ، وهي منطق التنفيذ بعد فشل إعادة المحاولة. بالإضافة إلى SimpleRetryPolicy ، هناك استراتيجيات إعادة محاكمة أخرى. دعنا نلقي نظرة على واجهة RetryPolicy :
الواجهة العامة RetryPolicy تمتد مسلسل {boolean canretry (RetryContext Context) ؛ RetryContext Open (RetryContext Parent) ؛ إغلاق باطل (سياق إعادة المحاولة) ؛ void registerThorWable (سياق إعادة RetryContext ، قابل للتخفيف) ؛} يتم استدعاء canRetry في كل مرة تحاول مرة أخرى. شرط الحكم حول ما إذا كان يمكنك الاستمرار في المحاولة مرة أخرى
تم استدعاؤه قبل بدء إعادة المحاولة open ، وسيتم إنشاء سياق إعادة المحاولة إلى RetryContext ، وسيتم حفظ مكدس إعادة المحاولة.
يتم استدعاء registerThrowable في كل مرة يتم إعادة إعادة الاستثناء (هناك استثناء وسيستمر في إعادة المحاولة)
خذ SimpleRetryPolicy كمثال. عندما يصل عدد إعادة المحاولة إلى 3 (افتراضي 3 مرات) ، توقف عن إعادة المحاولة ، ويتم حفظ عدد إعادة المحاولة في سياق إعادة المحاولة.
توفير تنفيذ استراتيجية إعادة المحاولة التالية:
إعادة محاولة استراتيجية الاحتياطية تشير إلى ما إذا كانت كل إعادة محاكمة يتم إعادة إعادة المحاولة فورًا أو انتظر لفترة من الوقت قبل المحاولة مرة أخرى. بشكل افتراضي ، تحتاج إلى تحديد BackOff Policy BackoffRetryPolicy إذا كنت بحاجة إلى تكوين فترة انتظار ثم حاول مرة أخرى. Backoffretrypolicy لديه التنفيذ التالي:
إعادة المحاولة العالية أو إعادة المحاولة عديمة الجنسية
تشير ما يسمى بإعادة المحاولة عديمة الجنسية إلى إعادة المحاولة المكتملة في سياق الخيط. خلاف ذلك ، إذا لم تكتمل إعادة المحاولة في سياق الخيط ، فهي إعادة محاكمة. كانت عملية SimpleRetryPolicy السابقة بمثابة إعادة محيطة عديمة الجنسية لأنه تم الانتهاء من إعادة المحاولة في حلقة. إذن ماذا يحدث بعد ذلك أو يحتاج إلى إعادة محاولة في دولة؟ عادة ما يكون هناك حالتان: تراجع المعاملات وقاطع الدائرة.
DataAccessException استثنائي. لا يمكن تنفيذ إعادة المحاولة ، ولكن إذا تم طرح استثناءات أخرى ، فيمكنك المحاولة مرة أخرى.
فتيل يعني عدم التعامل مع إعادة المحاولة في الحلقة الحالية ، ولكن إلى وضع إعادة المحاولة العالمية (وليس سياق الخيط). سوف يقفز قاطع الدائرة من الحلقة ، وستفقد معلومات مكدس سياق مؤشر الترابط. ثم من الضروري بالتأكيد حفظ هذه المعلومات في "الوضع العالمي". يتم وضع التنفيذ الحالي في ذاكرة التخزين المؤقت (تطبيق الخريطة). يمكنك الاستمرار في المحاولة مرة أخرى بعد الحصول عليها من ذاكرة التخزين المؤقت في المرة القادمة.
بداية سريعة
استخدم @EnableRetry على الفصل الذي يحتاج إلى إجراء إعادة المحاولة ، إذا تم تعيين proxyTargetClass=true ، وهذا يستخدم الوكيل الديناميكي CGLIB:
@configuration@enablerTry (proxyTargetClass = true)@componentpublic class receplamples {} Retry بناءً على الحد الأقصى لعدد استراتيجية إعادة المحاولة ، إذا تكررت إعادة المحاولة 3 مرات ولا يزال الاستثناء يتم إلقاؤه ، يتم إيقاف إعادة المحاولة ويتم تنفيذ رد الاتصال من أسفل إلى أعلى. لذلك ، فإن نتيجة الإخراج النهائي هي Integer.MAX_VALUE :
private void retryexample3 () يلقي استثناء {receptemplate receptemplate = new receplate () ؛ SimplerTryPolicy SimplerTerryPolicy = new SimplerTryPolicy () ؛ SimplerTryPolicy.setMaxattempts (3) ؛ receptemplate.setRetryPolicy (SimplerTryPolicy) ؛ integer result = retrytemplate.execute (جديد إعادة recealback <integer ، استثناء> () {int i = 0 ؛ RecoveryCallback <integer> () {// callback Override integer Recovery (RetryContext recepty) استثناء {log.info ("بعد إعادة المحاولة: log.info ("النتيجة النهائية: {}" ، نتيجة) ؛ } private int len (int i) يلقي الاستثناء {if (i <10) رمي استثناء جديد (i + "le 10") ؛ العودة أنا. }يصف ما يلي كيفية استخدام وضع سياسة Retry Circuit Breaker (CircuterBreakErretryPolicy). يجب تعيين المعلمات الثلاثة التالية:
فتح قاطع الدائرة وإغلاق الحكم:
رمز الاختبار كما يلي:
receptemplate template = جديد receplate () ؛ CircuterBreakErretryPolicy RetryPolicy = New CircuitBreakErretryPolicy (New SimplerTryPolicy (3)) ؛ recepolicy.setOpentimeout (5000) ؛ recepolicy.setResetTimeout (20000) ؛ template.setRetRypolicy (RetryPolicy) ؛ لـ (int i = 0 ؛ i <10 ؛ i ++) {//thread.sleep(100) ؛ حاول {Object Key = "Circuit" ؛ Boolean Isforcerefresh = false ؛ RetryState State = New DefaultRetryState (Key ، Isforcerefresh) ؛ string result = template.execute (جديد إعادة recealback <string ، runTimeException> () {Override public string dowithRetry (retryContext context) يلقي runtimeexception {log.info ("recept stringnfo <} {Override Public String Recovery (RetryContext Context) يلقي الاستثناء {Return "Default" ؛ log.info ("النتيجة: {}" ، نتيجة) ؛ } catch (استثناء e) {system.out.println (e) ؛ }} نظرًا لأن isForceRefresh = false تم تعيينه ، سيتم الحصول على قيمة key = "circuit" (أي ، إعادة المحاولة) من ذاكرة التخزين المؤقت. لذلك ، عندما تفشل إعادة المحاولة و this.time < this.openWindow تنصهر ، لا يزال بإمكانك الاستمرار في تنفيذ إعادة المحاولة في الوضع العالمي ( RetryContext الذي تم الحصول عليه هو نفسه).
تطوير التعليقات التوضيحية
إذا كانت كتابة RetryTemplate في كل مرة يكون فيها متطلبات إعادة المحاولة متضخمة للغاية ، فإن استخدام التعليقات التوضيحية يمكن أن يبسط بشكل كبير التطوير وتقليل الكود المكررة. فيما يلي إعادة محاكمة لأقصى استراتيجية إعادة المحاولة التي تم تنفيذها باستخدام التعليقات التوضيحية:
RETRYable (value = sqldataexception.class ، backoff = backoff (value = 0l)) public string service3 () يلقي sqldataexception {log.info ("service3 open") ؛ رمي sqldataexception () جديدة ؛ } Recover Public String Recovery (sqldataexception ne) {return "sqldataexception recovery" ؛ }تشمل التعليقات التوضيحية:
enableretry
regyable
Recover
backoff
circuitbreaker
enableretry: هل يمكنك المحاولة مرة أخرى؟ عندما تكون خاصية ProxyTargetClass صحيحة (خطأ افتراضي) ، استخدم وكيل CGLIB
recersable: الطريقة التي يجب إعادة محاولة التعليق التوضيحي
backoff: أعد إعادة استراتيجية الاحتياط (حاول الآن أو انتظر لفترة من الوقت قبل المحاولة مرة أخرى)
Recover: للاستخدام مع الأساليب. تستخدم كطريقة "مضمونة" عند فشل recerable. يجب أن تكون طريقة التعليق التوضيحي @الاسترداد متسقة مع طريقة "توقيع" التعليقات التوضيحية القابلة للإعادة. معلمة الإدخال الأولى هي الاستثناء الذي يتم إعادة محاولته. المعلمات الأخرى تتوافق مع @Retryable. يجب أن تكون قيمة الإرجاع هي نفسها ، وإلا لا يمكن تنفيذها!
circuitbreaker: يستخدم للطريقة ، تنفيذ وضع كسر الدائرة.
لمزيد من الأمثلة ، مرحبًا بك في github (https://github.com/happyxiaofan/springboot-learning-example). شكرًا
ما سبق هو كل محتوى هذه المقالة. آمل أن يكون ذلك مفيدًا لتعلم الجميع وآمل أن يدعم الجميع wulin.com أكثر.