التعامل مع الأخطاء والاستثناءات في تطبيقات Azure المنطقية
يمكن أن تشكل الطريقة التي تتعامل بها أي بنية تكامل بشكل مناسب مع وقت التوقف عن العمل أو المشكلات التي تسببها الأنظمة التابعة تحديا. لمساعدتك في إنشاء عمليات تكامل قوية ومرنة تتعامل مع المشكلات وحالات الفشل بأمان، توفر Logic Apps تجربة من الدرجة الأولى للتعامل مع الأخطاء والاستثناءات.
نهُج إعادة المحاولة
للحصول على أبسط استثناءات ومعالجة للأخطاء، يمكنك استخدام نهج إعادة المحاولة في أي إجراء أو مشغل حيث يكون مدعوما، على سبيل المثال، راجع إجراء HTTP. تحدد سياسة إعادة المحاولة ما إذا كان الإجراء أو المشغل يعيد محاولة طلب عند انتهاء مهلة الطلب الأصلي أو فشله، وهو أي طلب ينتج عنه استجابة 408 أو 429 أو 5xx. إذا لم يتم استخدام سياسة إعادة المحاولة الأخرى، استخدام السياسة الافتراضية.
فيما يلي أنواع نهج إعادة المحاولة:
| النوع | الوصف |
|---|---|
| افتراضي | ترسل هذه السياسة ما يصل إلى أربع عمليات إعادة محاولة على فترات زمنية متزايدة بشكل كبير ، والتي يتم قياسها بمقدار 7.5 ثانية ولكن يتم الحد الأقصى لها بين 5 و 45 ثانية. |
| الفاصل الزمني الأسي | تنتظر هذه السياسة فاصلا عشوائيا محددا من نطاق متزايد أضعافا مضاعفة قبل إرسال الطلب التالي. |
| فاصل زمني ثابت | تنتظر هذه السياسة الفاصل الزمني المحدد قبل إرسال الطلب التالي. |
| بلا | لا تقم بإعادة إرسال الطلب. |
للحصول على معلومات حول حدود نهج إعادة المحاولة، راجع حدود التطبيقات المنطقية وتكوينها.
تغيير سياسة إعادة المحاولة
لتحديد نهج إعادة محاولة مختلف، اتبع الخطوات التالية:
افتح تطبيقك المنطقي في Logic App Designer.
افتح الإعدادات لإجراء أو مشغل.
إذا كان الإجراء أو المشغل يدعم نهج إعادة المحاولة، ضمن نهج إعادة المحاولة، حدد النوع الذي تريده.
أو يمكنك تحديد نهج إعادة المحاولة يدويا في inputs القسم الخاص بإجراء أو مشغل يدعم نهج إعادة المحاولة. إذا لم تحدد سياسة إعادة المحاولة، فسيستخدم الإجراء السياسة الافتراضية.
"<action-name>": {
"type": "<action-type>",
"inputs": {
"<action-specific-inputs>",
"retryPolicy": {
"type": "<retry-policy-type>",
"interval": "<retry-interval>",
"count": <retry-attempts>,
"minimumInterval": "<minimum-interval>",
"maximumInterval": "<maximum-interval>"
},
"<other-action-specific-inputs>"
},
"runAfter": {}
}
مطلوب
| القيمة | النوع | الوصف |
|---|---|---|
| <إعادة المحاولة-نوع السياسة> | سلسلة | نوع نهج إعادة المحاولة الذي تريد استخدامه: defaultأو ، ، fixedأو noneexponential |
| <الفاصل الزمني لإعادة المحاولة> | سلسلة | الفاصل الزمني لإعادة المحاولة حيث يجب أن تستخدم القيمة تنسيق ISO 8601. الحد الأدنى الافتراضي للفاصل الزمني هو والحد الأقصى للفاصل الزمني هو PT5SPT1D. عند استخدام نهج الفاصل الزمني الأسي، يمكنك تحديد قيم دنيا وقصوى مختلفة. |
| <محاولات إعادة المحاولة> | عدد صحيح | عدد محاولات إعادة المحاولة، والتي يجب أن تكون بين 1 و 90 |
اختياري
| القيمة | النوع | الوصف |
|---|---|---|
| <الحد الأدنى للفاصل الزمني> | سلسلة | بالنسبة لسياسة الفاصل الزمني الأسي، أصغر فاصل زمني للفاصل الزمني المحدد عشوائيا بتنسيق ISO 8601 |
| <الحد الأقصى للفاصل الزمني> | سلسلة | بالنسبة لسياسة الفاصل الزمني الأسي، أكبر فاصل زمني للفاصل الزمني المحدد عشوائيا بتنسيق ISO 8601 |
فيما يلي مزيد من المعلومات حول أنواع السياسات المختلفة.
افتراضي
إذا لم تحدد سياسة إعادة محاولة، فسيستخدم الإجراء السياسة الافتراضية، وهي في الواقع سياسة فاصل زمني أسي ترسل ما يصل إلى أربع عمليات إعادة محاولة على فترات زمنية متزايدة أضعافا مضاعفة يتم قياسها بمقدار 7.5 ثانية. يتم تحديد الفاصل الزمني بين 5 و 45 ثانية.
على الرغم من عدم تعريفها صراحة في الإجراء أو المشغل، إليك كيفية تصرف السياسة الافتراضية في مثال إجراء HTTP:
"HTTP": {
"type": "Http",
"inputs": {
"method": "GET",
"uri": "http://myAPIendpoint/api/action",
"retryPolicy" : {
"type": "exponential",
"interval": "PT7S",
"count": 4,
"minimumInterval": "PT5S",
"maximumInterval": "PT1H"
}
},
"runAfter": {}
}
بلا
لتحديد أن الإجراء أو المشغل لا يعيد محاولة الطلبات الفاشلة، قم بتعيين نوع >نهج إعادة المحاولة< إلى none.
فاصل زمني ثابت
لتحديد أن الإجراء أو المشغل ينتظران الفاصل الزمني المحدد قبل إرسال الطلب التالي، قم بتعيين نوع> نهج إعادة المحاولة < إلى fixed.
مثال
تحاول سياسة إعادة المحاولة هذه الحصول على آخر الأخبار مرتين أخريين بعد فشل الطلب الأول مع تأخير لمدة 30 ثانية بين كل محاولة:
"Get_latest_news": {
"type": "Http",
"inputs": {
"method": "GET",
"uri": "https://mynews.example.com/latest",
"retryPolicy": {
"type": "fixed",
"interval": "PT30S",
"count": 2
}
}
}
الفاصل الزمني الأسي
لتحديد أن الإجراء أو المشغل ينتظر فاصلا عشوائيا قبل إرسال الطلب التالي، قم بتعيين نوع> نهج إعادة المحاولة < إلى exponential. يتم تحديد الفاصل الزمني العشوائي من نطاق متزايد بشكل كبير. اختياريا، يمكنك أيضا تجاوز الفواصل الزمنية الدنيا والقصوى الافتراضية عن طريق تحديد الفواصل الزمنية الدنيا والقصوى الخاصة بك.
نطاقات المتغيرات العشوائية
يوضح هذا الجدول كيفية قيام Logic Apps بإنشاء متغير عشوائي موحد في النطاق المحدد لكل إعادة محاولة حتى عدد عمليات إعادة المحاولة وتضمينها:
| رقم إعادة المحاولة | الحد الأدنى للفاصل الزمني | الحد الأقصى للفاصل الزمني |
|---|---|---|
| 1 | الحد الأقصى (0 ، <الحد الأدنى للفاصل الزمني>) | min (الفاصل الزمني ، <الحد الأقصى للفاصل الزمني>) |
| 2 | الحد الأقصى (الفاصل الزمني ، <الحد الأدنى للفاصل الزمني>) | الحد الأدنى (2 * الفاصل الزمني ، <الحد الأقصى للفاصل الزمني>) |
| 3 | الحد الأقصى (2 * الفاصل الزمني ، <الحد الأدنى للفاصل الزمني>) | الحد الأدنى (4 * الفاصل الزمني ، <الحد الأقصى للفاصل الزمني>) |
| 4 | الحد الأقصى (4 * الفاصل الزمني ، <الحد الأدنى للفاصل الزمني>) | الحد الأدنى (8 * الفاصل الزمني ، <الحد الأقصى للفاصل الزمني>) |
| .... | .... | .... |
التقاط والتعامل مع حالات الفشل عن طريق تغيير سلوك "الجري بعد"
عند إضافة إجراءات في "مصمم التطبيقات المنطقية"، فإنك تعلن ضمنيا عن الأمر المطلوب استخدامه لتشغيل هذه الإجراءات. بعد انتهاء تشغيل أحد الإجراءات، يتم تمييز هذا الإجراء بحالة مثل Succeeded، ، ، FailedSkippedأو TimedOut. في كل تعريف إجراء runAfter ، تحدد الخاصية الإجراء السابق الذي يجب أن ينتهي أولا والحالات المسموح بها لذلك الإجراء السابق قبل تشغيل الإجراء الخلف. بشكل افتراضي، يتم تشغيل الإجراء الذي تضيفه في المصمم فقط بعد اكتمال الإجراء السابق بالحالة Succeeded .
عندما يلقي إجراء خطأ أو استثناء لم تتم معالجته ، يتم وضع علامة على الإجراء ، ويتم وضع علامة FailedSkippedعلى أي إجراء لاحق . في حالة حدوث هذا السلوك لإجراء له فروع متوازية، يتبع مشغل Logic Apps الفروع الأخرى لتحديد حالات الإكمال الخاصة بها. على سبيل المثال، إذا انتهى فرع بإجراء ما Skipped ، فإن حالة إكمال هذا الفرع تستند إلى الحالة السابقة لهذا الإجراء الذي تم تخطيه. بعد اكتمال تشغيل التطبيق المنطقي، يحدد المحرك حالة التشغيل بالكامل من خلال تقييم جميع حالات الفروع. إذا انتهى أي فرع بالفشل، وضع علامة Failedعلى تشغيل التطبيق المنطقي بالكامل.

للتأكد من أنه لا يزال من الممكن تشغيل إجراء على الرغم من حالة سابقه، قم بتخصيص سلوك "التشغيل التالي" للإجراء للتعامل مع الحالات غير الناجحة للإجراء السابق.
تخصيص سلوك "الجري بعد"
يمكنك تخصيص سلوك "التشغيل بعد" الإجراء بحيث يتم تشغيل الإجراء عندما تكون حالة السلف إما Succeeded، ، SkippedTimedOut، Failedأو أي من هذه الحالات. على سبيل المثال، لإرسال بريد إلكتروني بعد وضع علامة Failedعلى الإجراء السابق Excel Online Add_a_row_into_a_table ، بدلا من تغيير سلوك "تشغيل بعد" باتباع أي من Succeededالخطوتين:
في طريقة عرض التصميم، حدد زر علامات الحذف (...)، ثم حدد تكوين التشغيل بعد.

يعرض شكل الإجراء الحالة الافتراضية المطلوبة للإجراء السابق، وهي إضافة صف إلى جدول في هذا المثال:

تغيير سلوك "تشغيل بعد" إلى الحالة التي تريدها، والتي فشلت في هذا المثال:

لتحديد تشغيل الإجراء سواء تم وضع علامة على الإجراء السابق ك
Failed، أوTimedOut،Skippedحدد الحالات الأخرى:
في طريقة عرض التعليمات البرمجية، في تعريف JSON للإجراء، قم بتحرير
runAfterالخاصية، التي تتبع بناء الجملة هذا:"<action-name>": { "inputs": { "<action-specific-inputs>" }, "runAfter": { "<preceding-action>": [ "Succeeded" ] }, "type": "<action-type>" }على سبيل المثال، قم بتغيير الخاصية
runAfterمنSucceededإلىFailed:"Send_an_email_(V2)": { "inputs": { "body": { "Body": "<p>Failed to add row to @{body('Add_a_row_into_a_table')?['Terms']}</p>",, "Subject": "Add row to table failed: @{body('Add_a_row_into_a_table')?['Terms']}", "To": "Sophia.Owen@fabrikam.com" }, "host": { "connection": { "name": "@parameters('$connections')['office365']['connectionId']" } }, "method": "post", "path": "/v2/Mail" }, "runAfter": { "Add_a_row_into_a_table": [ "Failed" ] }, "type": "ApiConnection" }لتحديد تشغيل الإجراء سواء تم وضع علامة على الإجراء السابق ك
Failed، أوTimedOut،Skippedأضف الحالات الأخرى:"runAfter": { "Add_a_row_into_a_table": [ "Failed", "Skipped", "TimedOut" ] },
تقييم الإجراءات باستخدام النطاقات ونتائجها
على غرار الخطوات الجارية بعد الإجراءات الفردية باستخدام runAfter الموقع، يمكنك تجميع الإجراءات معا داخل نطاق. يمكنك استخدام النطاقات عندما تريد تجميع الإجراءات منطقيا معا، وتقييم الحالة الإجمالية للنطاق، وتنفيذ إجراءات استنادا إلى هذه الحالة. بعد انتهاء تشغيل جميع الإجراءات في النطاق ، يحصل النطاق نفسه على حالته الخاصة.
للتحقق من حالة النطاق، يمكنك استخدام نفس المعايير التي تستخدمها للتحقق من حالة تشغيل تطبيق منطقي، مثل Succeeded، Failedوما إلى ذلك.
بشكل افتراضي ، عندما تنجح جميع إجراءات النطاق ، يتم وضع علامة Succeededعلى حالة النطاق . إذا كان الإجراء النهائي في نطاق ما يؤدي إلى أو FailedAborted، يتم وضع علامة Failedعلى حالة النطاق .
لالتقاط الاستثناءات في Failed نطاق وتشغيل الإجراءات التي تتعامل مع هذه الأخطاء، يمكنك استخدام runAfter الخاصية لهذا Failed النطاق. وبهذه الطريقة، إذا فشلت أي إجراءات في النطاق، واستخدمت runAfter الخاصية لهذا النطاق، فيمكنك إنشاء إجراء واحد للقبض على حالات الفشل.
للاطلاع على القيود المفروضة على النطاقات، راجع الحدود والتكوين.
الحصول على السياق والنتائج للفشل
على الرغم من أن اكتشاف حالات الفشل من نطاق ما أمر مفيد، فقد تحتاج أيضا إلى سياق لمساعدتك في فهم الإجراءات التي فشلت بالضبط بالإضافة إلى أي أخطاء أو رموز حالة تم إرجاعها. تقوم الدالةresult() بإرجاع النتائج من إجراءات المستوى الأعلى في إجراء محدد النطاق عن طريق قبول معلمة واحدة، وهو اسم النطاق، وإرجاع صفيف يحتوي على نتائج إجراءات المستوى الأول هذه. تتضمن كائنات الإجراء هذه نفس سمات تلك التي تم إرجاعها بواسطة الدالة actions() ، مثل وقت بدء الإجراء ووقت الانتهاء والحالة والمدخلات ومعرفات الارتباط والمخرجات.
ملاحظة
ترجع الدالة result() النتائج من إجراءات المستوى الأول فقط وليس من الإجراءات المتداخلة الأعمق مثل إجراءات التبديل أو الشرط.
للحصول على سياق حول الإجراءات التي فشلت في نطاق، يمكنك استخدام @result() التعبير مع اسم النطاق والخاصية runAfter . لتصفية الصفيف الذي تم إرجاعه إلى الإجراءات التي لها Failed حالة، يمكنك إضافة إجراء تصفية الصفيف. لتشغيل إجراء لإجراء فاشل تم إرجاعه، خذ الصفيف الذي تمت تصفيته التي تم إرجاعها واستخدم " لكل حلقة".
في ما يلي مثال ، متبوعا بشرح مفصل ، يرسل طلب HTTP POST مع نص الاستجابة لأي إجراءات فشلت داخل إجراء النطاق المسمى "My_Scope":
"Filter_array": {
"type": "Query",
"inputs": {
"from": "@result('My_Scope')",
"where": "@equals(item()['status'], 'Failed')"
},
"runAfter": {
"My_Scope": [
"Failed"
]
}
},
"For_each": {
"type": "foreach",
"actions": {
"Log_exception": {
"type": "Http",
"inputs": {
"method": "POST",
"body": "@item()['outputs']['body']",
"headers": {
"x-failed-action-name": "@item()['name']",
"x-failed-tracking-id": "@item()['clientTrackingId']"
},
"uri": "http://requestb.in/"
},
"runAfter": {}
}
},
"foreach": "@body('Filter_array')",
"runAfter": {
"Filter_array": [
"Succeeded"
]
}
}
فيما يلي إرشادات تفصيلية تصف ما يحدث في هذا المثال:
للحصول على النتيجة من جميع الإجراءات داخل "My_Scope"، يستخدم الإجراء "صفيف عوامل التصفية " تعبير عامل التصفية هذا:
@result('My_Scope')شرط " صفيف عوامل التصفية" هو أي
@result()عنصر له حالة مساوية لFailed. يقوم هذا الشرط بتصفية الصفيف الذي يحتوي على جميع نتائج الإجراء من "My_Scope" وصولا إلى صفيف يحتوي على نتائج الإجراء الفاشل فقط.تنفيذ إجراء
For_eachحلقة على مخرجات الصفيف التي تمت تصفيتها . تنفذ هذه الخطوة إجراء لكل نتيجة إجراء فاشلة تمت تصفيتها مسبقا.في حالة فشل إجراء واحد في النطاق، يتم تشغيل الإجراءات الموجودة
For_eachفي الحلقة مرة واحدة فقط. تتسبب الإجراءات الفاشلة المتعددة في إجراء واحد لكل فشل.إرسال HTTP POST على نص استجابة العنصر
For_each، وهو@item()['outputs']['body']التعبير.شكل العنصر
@result()هو نفسه@actions()الشكل ويمكن تحليله بنفس الطريقة.قم بتضمين رأسين مخصصين باسم الإجراء الفاشل () ومعرف تعقب عميل التشغيل الفاشل (
@item()['name']@item()['clientTrackingId']).
للرجوع إليها، إليك مثال على عنصر واحد @result() ، يعرض name، bodyوالخصائص clientTrackingId التي تم تحليلها في المثال السابق. خارج أحد الإجراءات For_each ، @result() إرجاع صفيف من هذه الكائنات.
{
"name": "Example_Action_That_Failed",
"inputs": {
"uri": "https://myfailedaction.azurewebsites.net",
"method": "POST"
},
"outputs": {
"statusCode": 404,
"headers": {
"Date": "Thu, 11 Aug 2016 03:18:18 GMT",
"Server": "Microsoft-IIS/8.0",
"X-Powered-By": "ASP.NET",
"Content-Length": "68",
"Content-Type": "application/json"
},
"body": {
"code": "ResourceNotFound",
"message": "/docs/folder-name/resource-name does not exist"
}
},
"startTime": "2016-08-11T03:18:19.7755341Z",
"endTime": "2016-08-11T03:18:20.2598835Z",
"trackingId": "bdd82e28-ba2c-4160-a700-e3a8f1a38e22",
"clientTrackingId": "08587307213861835591296330354",
"code": "NotFound",
"status": "Failed"
}
لتنفيذ أنماط معالجة استثناءات مختلفة، يمكنك استخدام التعبيرات الموضحة سابقا في هذه المقالة. يمكنك اختيار تنفيذ إجراء معالجة استثناء واحد خارج النطاق الذي يقبل صفيف الفشل الذي تمت تصفيته بالكامل، وإزالة الإجراء For_each . يمكنك أيضا تضمين خصائص مفيدة أخرى من \@result() الاستجابة كما هو موضح سابقا.
إعداد سجلات Azure مراقبة
تعد الأنماط السابقة طريقة رائعة للتعامل مع الأخطاء والاستثناءات أثناء التشغيل ، ولكن يمكنك أيضا تحديد الأخطاء والاستجابة لها بشكل مستقل عن التشغيل نفسه. يوفر Azure Monitor طريقة بسيطة لإرسال جميع أحداث سير العمل، بما في ذلك جميع حالات التشغيل والإجراءات، إلى مساحة عمل Log Analytics أو حساب تخزين Azure أو مراكز أحداث Azure.
لتقييم حالات التشغيل، يمكنك مراقبة السجلات والمقاييس، أو نشرها في أي أداة مراقبة تفضلها. أحد الخيارات المحتملة هو دفق جميع الأحداث من خلال مراكز الأحداث إلى Azure Stream Analytics. في Stream Analytics، يمكنك كتابة طلبات بحث مباشرة استنادا إلى أي حالات شاذة أو متوسطات أو حالات فشل من سجلات التشخيص. يمكنك استخدام Stream Analytics لإرسال المعلومات إلى مصادر بيانات أخرى، مثل قوائم الانتظار أو الموضوعات أو SQL أو Azure Cosmos DB أو Power BI.