التزامنات الدائمة
تعد الدالات الدائمة امتداداً لـ مهام Azure. يمكنك استخدام دالة التزامن لتنسيق تنفيذ وظائف دائمة أخرى داخل تطبيق دالة. تتسم الدالات التزامنية بما يلي:
- تعرف الدالات التزامنية سير عمل الوظيفة باستخدام الأكواد الإجرائية. لا تُطلب مخططات تعريفية أو مصممون.
- يمكن أن تستدعي دالات التزامن دالات دائمة أخرى بشكل متزامن وغير متزامن. يمكن حفظ المخرج من الدالات المذكورة بشكل موثوق في المتغيرات المحلية.
- تتسم دالات التزامن بأنها دائمة وموثوق بها. يجري التحقق التلقائي من التقدم المحرز في التنفيذ عندما "تنتظر" أو "تثمر" الدالة. لا تُفقد الحالة المحلية أبداً عند إعادة تدوير العملية أو إعادة تمهيد الجهاز الظاهري.
- يمكن أن تكون الدالات التزامنية طويلة الأمد. يمكن أن يستغرق إجمالي عمر مثيل التزامن ثواني أو أياماً أو أشهراً أو قد لا تنتهي أبدا.
تمنحك هذه المقالة نظرة عامة على الدالات التزامنية وكيف يمكنها أن تساعدك على حل تحديات تطوير التطبيقات المختلفة. إذا لم تكن معتاداً على أنواع الدالات المتوفرة في تطبيق "دالات دائمة"، فاقرأ مقالة أنواع الوظائف الدائمة أولاً.
هوية التزامن
كل مثيل من تزامن له معرف مثيل (يطلق عليه أيضاً اسم معرف مثيل). وافتراضياً، كل معرف مثيل هو GUID أُنشئ تلقائياً. ومع ذلك، لا بد أن تبلغ قيمة معرفات المثيل أيضاً أي قيمة نصية أنشأها المستخدم. ولا بد أن يكون كل معرف تزامن مثيل معرفاً فريداً داخل task hub.
فيما يلي بعض القواعد المتعلقة بمعرفات المثيل:
- يجب أن يتراوح عدد معرفات المثيل بين 1 و100 حرف.
- يتعين ألا تبدأ معرفات المثيل بـ
@
. - ينبغي ألا تحتوي معرفات المثيل على أحرف
/
،\
،#
أو?
. - يجب ألا تحتوي معرفات المثيل على أحرف تحكم.
إشعار
يوصى عموماً باستخدام معرفات المثيلات المتجانسة تلقائياً، كلما أمكن ذلك. تعد معرفات المثيل التي أنشأها المستخدم مخصصة للسيناريوهات التي يوجد تعيين واحد بين مثيل التزامن وكيان خاص بالتطبيق الخارجي، مثل أمر شراء أو مستند.
أيضا، قد يختلف الإنفاذ الفعلي لقواعد تقييد الأحرف اعتمادا على موفر التخزين الذي يستخدمه التطبيق. لضمان السلوك والتوافق الصحيحين، يوصى بشدة باتباع قواعد معرف المثيل المذكورة سابقا.
يعد معرف مثيل التزامن معياراً مطلوباً لمعظم عمليات إدارة المثيل. كما أنها مهمة للتشخيص، مثل البحث في بيانات تتبع التزامن في تطبيق Insights لاستكشاف الأخطاء وإصلاحها أو لأغراض التحليلات. لهذا السبب، من الجيد حفظ معرفات المثيل التي أنشئت في بعض المواقع الخارجية (على سبيل المثال، قاعدة بيانات أو في سجلات التطبيق) حيث يمكن الرجوع إليها بسهولة لاحقاً.
الموثوقيه
تحافظ دالات التزامن بشكل موثوق على حالة التنفيذ باستخدام نمط تصميم تعيين مصادر الحدث. بدلاً من تخزين حالة التزامن الحالية تخزيناً مباشراً، يستخدم "إطار عمل المهمة الدائمة" مخزناً للتعديل فقط؛ لتسجيل سلسلة كاملة من الإجراءات التي يضطلع بها تزامن الدالة. ولمخزن التعديل فقط العديد من الفوائد مقارنة بـ "تفريغ" حالة وقت التشغيل الكاملة. وتشمل الفوائد زيادة الأداء وقابلية التوسع والاستجابة. يمكنك أيضاً الحصول على الاتساق النهائي لبيانات المعاملات ومسارات التدقيق الكاملة وتاريخها. وتدعم مسارات التدقيق إجراءات تعويض موثوقة.
تستخدم الوظائف الدائمة خاصية تعيين مصادر الحدث بشفافية. خلف الكواليس، عامل التشغيل await
(C#) أو yield
(JavaScript/Python) في دالة تزامن ترجع التحكم في مؤشر ترابط التزامن مرة أخرى إلى مرسل إطار المهمة الدائم. في حالة Java، لا توجد كلمة أساسية خاصة باللغة. بدلاً من ذلك، سيؤدي استدعاء .await()
مهمة إلى إعادة التحكم إلى المرسل عبر مخصص Throwable
. ثم يضطلع المرسل بأي إجراءات جديدة وضعتها دالة التزامن (مثل استدعاء دالة تابعة واحدة أو أكثر أو جدولة مؤقت دائم) في المخزن. يحدث إجراء الالتزام الشفاف محفوظات تاريخ تنفيذ مثيل التزامن عن طريق إدخال جميع الأحداث الجديدة في المخزن، مثل سجل الإدخال فقط. وبالمثل، يرسل إجراء الالتزام رسائل في المخزن بغرض جدولة العمل الفعلي. عند هذه النقطة، يمكن إلغاء تحميل دالة التزامن من الذاكرة. تستخدم "الدالات الدائمة"، افتراضياً، مخزن Azure بوصفه مخزن حالة وقت التشغيل، ولكن يُدعم مقدمو خدمات التخزين الآخرون أيضاً.
عند إسناد مزيد من العمل إلى دالة تزامن (على سبيل المثال، يتم تلقي رسالة استجابة أو تنتهي صلاحية المؤقت الدائم)، وتكون عملية التزامن نشطة، وتعيد تنفيذ الدالة بأكملها من البداية إلى إعادة إنشاء الحالة المحلية. أثناء إعادة التشغيل، إذا حاول استدعاء دالة (أو القيام بأي عمل غير متزامن آخر)، يستشير إطار العمل الدائم تاريخ التنفيذ من التزامن الحالي. إذا نفذت دالة النشاط بالفعل تنفيذ وأسفرت عن نتيجة، يُعاد الرد على نتيجة تلك الدالة ويستمر تشغيل كود التزامن. تستمر إعادة التشغيل حتى انتهاء رمز الدالة أو جدولة عمل مزامنة جديد.
إشعار
لكي يعمل نمط الإعادة بشكل صحيح وموثوق، ينبغي أن يكون كود دالة التزامن محدداً. قد يسفر كود التزامن غير الحتمي عن أخطاء وقت التشغيل أو سلوك غير متوقع آخر. لمزيد من المعلومات حول قيود الأكواد ودالات التزامن، راجع وثائق قيود أكواد دالة التزامن.
إشعار
إذا كانت دالة تزامن ما تبعث رسائل السجل، قد يؤدي سلوك إعادة التشغيل إلى إعادة بعث رسائل السجل المكررة. راجع موضوع التسجيل لمعرفة المزيد حول سبب حدوث هذا السلوك وكيفية العمل حوله.
تاريخ التزامن
سلوك إصدار الحدث لإطار عمل المهمة الدائم يرتبط ارتباطاً وثيقاً بكود دالة التزامن الذي تكتبه. افترض أن لديك دالة تزامن متسلسلة النشاط مثل دالة التزامن التالية:
إشعار
يتوفر الإصدار 4 من نموذج البرمجة Node.js ل Azure Functions بشكل عام. تم تصميم نموذج v4 الجديد للحصول على تجربة أكثر مرونة وبديهية لمطوري JavaScript وTypeScript. تعرف على المزيد حول الاختلافات بين v3 وv4 في دليل الترحيل.
في القصاصات البرمجية التالية، يشير JavaScript (PM4) إلى نموذج البرمجة V4، التجربة الجديدة.
[FunctionName("HelloCities")]
public static async Task<List<string>> Run(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
var outputs = new List<string>();
outputs.Add(await context.CallActivityAsync<string>("SayHello", "Tokyo"));
outputs.Add(await context.CallActivityAsync<string>("SayHello", "Seattle"));
outputs.Add(await context.CallActivityAsync<string>("SayHello", "London"));
// returns ["Hello Tokyo!", "Hello Seattle!", "Hello London!"]
return outputs;
}
عند تخطيط وظيفة نشطة، فإن نقاط اختبار إطار العمل الدائم لحالة تنفيذ الدالة في خلفية التخزين الدائم (تخزين جدول Azure بشكل افتراضي). هذه الحالة هي ما يشار إليه بتاريخ التزامن.
جدول المحفوظات
وبصفة عامة، يقوم إطار عمل المهمة الدائم بما يلي عند كل نقطة تحقق:
- حفظ تاريخ التنفيذ في مخزن دائم.
- صف رسائل الدالات التي يرغب المزامن في استدعائها.
- صف الرسائل للمنسق نفسه على سبيل المثال، رسائل المؤقت الدائم.
بمجرد اكتمال نقطة التحقق، تكون إزالة دالة التزامن من الذاكرة عملية حرة حتى يكون هناك المزيد من العمل للقيام به.
إشعار
لا توفر Azure Storage أي ضمانات معاملاتية بين حفظ البيانات في ذاكرة الجدول وقوائم الانتظار. لمعالجة حالات الفشل، يستخدم موفر ذاكرة Azure للوظائف الدائمة أنماط التناسق النهائية. تضمن هذه الأنماط عدم فقدان أي بيانات إذا حدث عطل أو فقدان للاتصال في منتصف نقطة التحقق. قد يوفر مقدمو الذاكرة البديلة، مثل موفر ذاكرة MSSQL للوظائف الدائمة، ضمانات اتساق أقوى.
عند الانتهاء، يبدو تاريخ الدالة المعروضة سابقاً مثل الجدول التالي في ذاكرة جدول Azure (مختصر لأغراض توضيحية):
PartitionKey (InstanceId) | EventType | الطابع الزمني | الإدخال | الاسم | نتيجة | الحالة |
---|---|---|---|---|---|---|
eaee885b | ExecutionStarted | 2021-05-05T18:45:28.852Z | قيمة فارغة | HelloCities | ||
eaee885b | OrchestratorStarted | 2021-05-05T18:45:32.362Z | ||||
eaee885b | TaskScheduled | 2021-05-05T18:45:32.670Z | SayHello | |||
eaee885b | OrchestratorCompleted | 2021-05-05T18:45:32.670Z | ||||
eaee885b | TaskCompleted | 2021-05-05T18:45:34.201Z | """مرحباً طوكيو!""" | |||
eaee885b | OrchestratorStarted | 2021-05-05T18:45:34.232Z | ||||
eaee885b | TaskScheduled | 2021-05-05T18:45:34.435Z | SayHello | |||
eaee885b | OrchestratorCompleted | 2021-05-05T18:45:34.435Z | ||||
eaee885b | TaskCompleted | 2021-05-05T18:45:34.763Z | """مرحباً سياتل!""" | |||
eaee885b | OrchestratorStarted | 2021-05-05T18:45:34.857Z | ||||
eaee885b | TaskScheduled | 2021-05-05T18:45:34.857Z | SayHello | |||
eaee885b | OrchestratorCompleted | 2021-05-05T18:45:34.857Z | ||||
eaee885b | TaskCompleted | 2021-05-05T18:45:34.919Z | """مرحباً لندن!""" | |||
eaee885b | OrchestratorStarted | 2021-05-05T18:45:35.032Z | ||||
eaee885b | OrchestratorCompleted | 2021-05-05T18:45:35.044Z | ||||
eaee885b | ExecutionCompleted | 2021-05-05T18:45:35.044Z | "[""مرحباً طوكيو!""، ""مرحباً سياتل!""،" "مرحباً لندن!""]" | مكتمل |
بعض الملاحظات بشأن قيم العمود:
- PartitionKey: يحتوي على معرف مثيل التزامن.
- EventType: يمثل نوع الحدث. يمكنك العثور على أوصاف مفصلة لجميع أنواع أحداث المحفوظات هنا.
- Timestamp: الطابع الزمني لـ UTC لحدث التاريخ.
- Name: اسم الدالة التي استدعيت.
- Input: مدخل الدالة بتنسيق JSON.
- Result: مخرج الدالة; أي، قيمة إرجاعها.
تحذير
بالرغم من أنه مفيدة بصفته أداة تصحيح الأخطاء، لا تعتمد على هذا الجدول. قد يتغير مع تطور ملحق Durable Functions.
في كل مرة يتم فيها استئناف الوظيفة بعد انتظار اكتمال مهمة، يعيد Durable Task Framework تشغيل دالة المنسق من البداية. في كل إعادة تشغيل، تستشير محفوظات التنفيذ لتحديد ما إذا كانت عملية التزامن الحالية قد أُجريت. إذا أظهرت محفوظات التنفيذ أن المهمة قد اكتملت بالفعل، فإن إطار العمل يعيد تشغيل إخراج تلك المهمة وينتقل إلى المهمة التالية. تستمر هذه العملية حتى يُعاد تشغيل المحفوظات بأكملها. بمجرد إعادة تشغيل المحفوظات الحالية، ترجع المتغيرات المحلية إلى قيمها السابقة.
المميزات والأنماط
تصف الأقسام التالية مميزات دالات التزامن وأنماطها.
التزامن الفرعي
تستدعي دالات التزامن دالات النشاط ودالات التزامن الأخرى. على سبيل المثال، يمكنك إنشاء تزامن أكبر من مكتبة دالات التزامن. أو يمكنك تشغيل مثيلات متعددة لدالة التوازن بالتوازي.
لمزيد من المعلومات وعلى سبيل المثال، راجع مقالة التزامن الفرعي.
مؤقتات دائمة
يمكن أن يجدول التزامن المؤقتات الدائمة لتنفيذ التأخير أو لإعداد معالجة المهلة على الإجراءات المتزامنة. استخدم المؤقتات الدائمة في وظائف المنسق بدلاً من واجهات برمجة التطبيقات "السكون" الأصلية للغة.
لمزيد من المعلومات وعلى سبيل المثال، راجع مقالة المؤقتات الدائمة.
الأحداث الخارجية
يمكن أن تنتظر دالات التزامن الأحداث الخارجية لتحديث مثيل التزامن. غالباً ما تكون خاصية "الدالات الدائمة" مفيدة للتعامل مع تفاعل بشري أو عمليات رد اتصال خارجية أخرى.
لمزيد من المعلومات، راجع مقالة الأحداث الخارجية.
معالجة الخطأ
يمكن أن تستخدم دالات التزامن مميزات معالجة الأخطاء للغة البرمجة. الأنماط الموجودة مثل try
/catch
معتمدة في كود التزامن.
يمكن لدالات التزامن إضافة نهج إعادة المحاولة إلى وظائف التزامن الفرعي أو النشاط اللذان يقتضيانهما. إذا فشل نشاط أو دالة تزامن فرعية باستثناء ما، يمكن أن يؤدي نهج إعادة المحاولة المحدد تلقائياً إلى تأخير التنفيذ وإعادة محاولة تنفيذه حتى عدد محدد من المرات.
إشعار
إذا كانت هناك استثناء غير معالج في دالة التزامنية، يكتمل مثيل التزامن في حالةFailed
. لا يمكن إعادة محاولة مثيل التزامن بمجرد الفشل.
لمزيد من المعلومات، راجع مقالة معالجة الأخطاء.
المقاطع الحيوية (الوظائف الدائمة 2.x، وحالياً .NET فقط)
تكون مثيلات التزامن ذات ترابط واحد لذلك ليس من الضروري القلق بشأن ظروف السباق داخل التزامن. وعلى الرغم من ذلك، تكون حالة التعارض ممكنة عندما تتفاعل التزامنات مع الأنظمة الخارجية. لتخفيف حالات التعارض عند التفاعل مع أنظمة خارجية، يمكن لوظائف المنسق تحديد critical sections باستخدام أسلوب LockAsync
في .NET.
يظهر نموذج الكود التالي دالة تزامن تعرف القسم الحيوي. تدخل المقطع الحيوي باستخدام LockAsync
الأسلوب. يتطلب هذا الأسلوب تمرير مرجع واحد أو أكثر إلى كيان دائم، والذي يدير حالة التأمين إدارة دائمة. ينفذ مثيل واحد فقط من هذا التزامن الكود في المقطع الحيوي في آن واحد.
[FunctionName("Synchronize")]
public static async Task Synchronize(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
var lockId = new EntityId("LockEntity", "MyLockIdentifier");
using (await context.LockAsync(lockId))
{
// critical section - only one orchestration can enter at a time
}
}
يحصل LockAsync
على تأمين دائم (أو تأمينات دائمة) ويعيدها IDisposable
ما ينهي المقطع الحيوي عند التخلص منه. يمكن استخدام هذه IDisposable
النتيجة مع using
كتلة ما للحصول على تمثيل تركيبي للمقطع الحيوي. عند دخول دالة تزامن في مقطع حيوي، يمكن لمثيل واحد فقط أن ينفذ تلك الكتلة من الكود. سيتم حظر أي مثيلات أخرى تحاول دخول المقطع الحيوي إلى أن يخرج المثيل السابق منه.
كما أن خاصية المقطع الحيوي مفيدة لتنسيق التغييرات في الكيانات الدائمة. لمزيد من المعلومات حول المقاطع الحيوية، راجع موضوع "تنسيق كيان" للكيانات الدائمة.
إشعار
تتوفر الأقسام الهامة في Durable Functions 2.0. حاليا، تقوم تنسيقات .NET في proc فقط بتنفيذ هذه الميزة. الكيانات والأقسام الهامة غير متوفرة بعد في Durable Functions لعامل dotnet المعزول.
استدعاء نقاط نهاية HTTP، وهي (Durable Functions 2.x)
لا يُسمح لوظائف التزامن بالقيام بـ الإدخال/إخراج، على النحو الموضح في قيود كود الدالة التزامنية. ويكمن الحل البديل لهذا القيد في تغليف أي كود يحتاج إلى القيام بعملية الإدخال/الإخراج في دالة نشاط. تستخدم التزامنات التي تتفاعل مع أنظمة خارجية تفاعلاً متكرراً دالات النشاط لإجراء مكالمات HTTP وإرجاع النتيجة إلى التزامن.
لتبسيط هذا النمط الشائع، يمكن أن تستخدم دالات التزامن CallHttpAsync
الأسلوب لاستدعاء واجهات برمجة التطبيقات HTTP مباشرةً.
[FunctionName("CheckSiteAvailable")]
public static async Task CheckSiteAvailable(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
Uri url = context.GetInput<Uri>();
// Makes an HTTP GET request to the specified endpoint
DurableHttpResponse response =
await context.CallHttpAsync(HttpMethod.Get, url);
if ((int)response.StatusCode == 400)
{
// handling of error codes goes here
}
}
بالإضافة إلى دعم أنماط الطلب/الاستجابة الأساسية، تدعم الطريقة المعالجة التلقائية لأنماط الاستقصاء المشتركة لـ HTTP 202، كما تدعم أيضاً المصادقة مع الخدمات الخارجية باستخدام الهويات المدارة.
لمزيد من المعلومات وللحصول على أمثلة تفصيلية، راجع مقالة خصائص HTTP.
إشعار
استدعاء نقاط نهاية HTTP مباشرة من دالات التزامن المتاحة في إصدارDurable Functions 2.0 وأي إصدار أحدث.
تمرير معايير متعددة
لا يمكن تمرير معايير متعددة إلى دالة نشاط مباشرةً. وتفيد التوصية بتمرير صفيف من العناصر أو الكائنات المركبة.
في ".NET" يمكنك أيضاً استخدام عناصر ValueTuple. يستخدم النموذج التالي خصائص جديدة من ValueTuple المضافة مع C # 7:
[FunctionName("GetCourseRecommendations")]
public static async Task<object> RunOrchestrator(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
string major = "ComputerScience";
int universityYear = context.GetInput<int>();
object courseRecommendations = await context.CallActivityAsync<object>(
"CourseRecommendations",
(major, universityYear));
return courseRecommendations;
}
[FunctionName("CourseRecommendations")]
public static async Task<object> Mapper([ActivityTrigger] IDurableActivityContext inputs)
{
// parse input for student's major and year in university
(string Major, int UniversityYear) studentInfo = inputs.GetInput<(string, int)>();
// retrieve and return course recommendations by major and university year
return new
{
major = studentInfo.Major,
universityYear = studentInfo.UniversityYear,
recommendedCourses = new []
{
"Introduction to .NET Programming",
"Introduction to Linux",
"Becoming an Entrepreneur"
}
};
}