يُشير تسلسل الدالة إلى نمط تنفيذ تسلسل الدالات بترتيبِ معين. في هذا النمط، يتم تطبيق إخراج دالة واحدة على إدخال دالةٍ أخرى. توضح هذه المقالة تسلسل التسلسل الذي تقوم بإنشائه عند إكمال التشغيل السريع ل Durable Functions (C# أو JavaScript أو TypeScript أو Python أو PowerShell أو Java). لمزيدٍ من المعلومات عن الدوال المتينة يُرجى إلقاء نظرة عامة على الدوال المتينة.
المتطلبات الأساسية
إشعار
يتوفر الإصدار 4 من نموذج البرمجة Node.js ل Azure Functions بشكل عام. تم تصميم نموذج v4 الجديد للحصول على تجربة أكثر مرونة وبديهية لمطوري JavaScript وTypeScript. تعرف على المزيد حول الاختلافات بين v3 وv4 في دليل الترحيل.
في القصاصات البرمجية التالية، يشير JavaScript (PM4) إلى نموذج البرمجة V4، التجربة الجديدة.
الدوال
توضح هذه المقالة الدوال التالية في تطبيق العينة:
E1_HelloSequence
دالة منسق التي تستدعي E1_SayHello
عدة مرات في تسلسل. فإنه يخزن المخرجات من E1_SayHello
المكالمات ويسجل النتائج.
E1_SayHello
دالة نشاط التي تضيف سلسلة مع "مرحبا".
HttpStart
تشغيل HTTP دالة عميل دائم الذي يبدأ على الفور من المنسق.
E1_ مرحبًا تعاقب دالة المنسق
[FunctionName("E1_HelloSequence")]
public static async Task<List<string>> Run(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
var outputs = new List<string>();
outputs.Add(await context.CallActivityAsync<string>("E1_SayHello", "Tokyo"));
outputs.Add(await context.CallActivityAsync<string>("E1_SayHello", "Seattle"));
outputs.Add(await context.CallActivityAsync<string>("E1_SayHello_DirectInput", "London"));
// returns ["Hello Tokyo!", "Hello Seattle!", "Hello London!"]
return outputs;
}
يجب أن يكون لكافة دالات التزامن C# معلمة من النوع DurableOrchestrationContext
، موجودة في Microsoft.Azure.WebJobs.Extensions.DurableTask
التجميع. يتيح لك هذا السياق استدعاء وظائف نشاط أخرى وتمرير معلمات الإدخال باستخدام CallActivityAsync
أسلوبها.
استدعاء التعليمات البرمجية E1_SayHello
ثلاث مرات في تسلسل مع قيم معلمة مختلفة. تتم إضافة قيمة الإرجاع لكل استدعاء إلى outputs
القائمة التي يتم إرجاعها في نهاية الدالة.
function.json
إذا كنت تستخدم رمز Visual Studio أو مدخل Azure للتطوير، فإليك محتوى function.js في الملف لدالة المنسق. معظم ملفات المنسق function.json تبدو بالضبط تقريبًا مثل هذا.
{
"bindings": [
{
"name": "context",
"type": "orchestrationTrigger",
"direction": "in"
}
],
"disabled": false
}
الشيء المهم هو نوع الربط orchestrationTrigger
. يجب أن تستخدم كافة دالات التزامن مشغلاً من هذا النوع.
تحذير
للالتزام بقاعدة "عدم الإدخال/الإخراج" من دالات التزامن، لا تستخدم أي روابط إدخال أو إخراج بيانات عند استخدام orchestrationTrigger
ربط المشغل. إذا كانت هناك حاجة إلى روابط إدخال أو إخراج أخرى، يجب استخدامها بدلاً من ذلك في سياق activityTrigger
الدالات، والتي يتم استدعاؤها من قِبل المنسق. لمزيد من المعلومات، راجع المقالة قيود رمز دالة المنسق.
index.js
ها هو منسق الدالة
const df = require("durable-functions");
module.exports = df.orchestrator(function* (context) {
context.log("Starting chain sample");
const output = [];
output.push(yield context.df.callActivity("E1_SayHello", "Tokyo"));
output.push(yield context.df.callActivity("E1_SayHello", "Seattle"));
output.push(yield context.df.callActivity("E1_SayHello", "London"));
return output;
});
يجب أن تتضمن كافة وظائف التزامن JavaScript durable-functions
الوحدة النمطية. إنها مكتبة تمكنك من كتابة دوال متينة في JavaScript. هناك ثلاثة اختلافات هامة بين دالة التزامن ووظائف JavaScript الأخرى:
- دالة المنسق هي دالة مولد.
- يتم تضمين الدالة في استدعاء
durable-functions
إلى أسلوب الوحدة النمطية orchestrator
df
(هنا).
- يجب أن تكون الدالة متزامنة. لأن الأسلوب 'المتسق' يعالج استدعاء 'context.done'، يجب أن 'ترجع' الدالة.
يحتوي الكائن context
على كائن سياق تزامن دائم df
يتيح لك استدعاء وظائف نشاط أخرى وتمرير معلمات الإدخال باستخدام أسلوب callActivity
بها. تستدعي التعليمات البرمجية E1_SayHello
ثلاث مرات في تسلسل مع قيم معلمة مختلفة، باستخدام yield
للإشارة إلى التنفيذ ينبغي الانتظار على لاستدعاءات دالة النشاط المتزامنة ليتم إرجاعها. تتم إضافة قيمة الإرجاع لكل استدعاء إلى صفيف outputs
، الذي يتم إرجاعه في نهاية الدالة.
const df = require("durable-functions");
const helloActivityName = "sayHello";
df.app.orchestration("helloSequence", function* (context) {
context.log("Starting chain sample");
const output = [];
output.push(yield context.df.callActivity(helloActivityName, "Tokyo"));
output.push(yield context.df.callActivity(helloActivityName, "Seattle"));
output.push(yield context.df.callActivity(helloActivityName, "Cairo"));
return output;
});
يجب أن تتضمن كافة وظائف التزامن JavaScript durable-functions
الوحدة النمطية. تمكنك هذه الوحدة من كتابة Durable Functions في JavaScript. لاستخدام نموذج برمجة عقدة V4، تحتاج إلى تثبيت إصدار المعاينة v3.x
من durable-functions
.
هناك اختلافان كبيران بين دالة المنسق ووظائف JavaScript الأخرى:
- دالة المنسق هي دالة مولد.
- يجب أن تكون الدالة متزامنة. يجب أن تكون الدالة ببساطة "إرجاع".
يحتوي الكائن context
على كائن سياق تزامن دائم df
يتيح لك استدعاء وظائف نشاط أخرى وتمرير معلمات الإدخال باستخدام أسلوب callActivity
بها. تستدعي التعليمات البرمجية sayHello
ثلاث مرات في تسلسل مع قيم معلمة مختلفة، باستخدام yield
للإشارة إلى التنفيذ ينبغي الانتظار على لاستدعاءات دالة النشاط المتزامنة ليتم إرجاعها. تتم إضافة قيمة الإرجاع لكل استدعاء إلى صفيف outputs
، الذي يتم إرجاعه في نهاية الدالة.
إشعار
دوال Python المتينة متاحة لدوال 3.0 وقت التشغيل فقط.
function.json
إذا كنت تستخدم رمز Visual Studio أو مدخل Azure للتطوير، فإليك محتوى function.js في الملف لدالة المنسق. معظم ملفات المنسق function.json تبدو بالضبط تقريبًا مثل هذا.
{
"scriptFile": "__init__.py",
"bindings": [
{
"name": "context",
"type": "orchestrationTrigger",
"direction": "in"
}
]
}
الشيء المهم هو نوع الربط orchestrationTrigger
. يجب أن تستخدم كافة دالات التزامن مشغلاً من هذا النوع.
تحذير
للالتزام بقاعدة "عدم الإدخال/الإخراج" من دالات التزامن، لا تستخدم أي روابط إدخال أو إخراج بيانات عند استخدام orchestrationTrigger
ربط المشغل. إذا كانت هناك حاجة إلى روابط إدخال أو إخراج أخرى، يجب استخدامها بدلاً من ذلك في سياق activityTrigger
الدالات، والتي يتم استدعاؤها من قِبل المنسق. لمزيد من المعلومات، راجع المقالة قيود رمز دالة المنسق.
__init__.py
ها هو منسق الدالة
import azure.functions as func
import azure.durable_functions as df
def orchestrator_function(context: df.DurableOrchestrationContext):
result1 = yield context.call_activity('E1_SayHello', "Tokyo")
result2 = yield context.call_activity('E1_SayHello', "Seattle")
result3 = yield context.call_activity('E1_SayHello', "London")
return [result1, result2, result3]
main = df.Orchestrator.create(orchestrator_function)
يجب أن تتضمن كافة وظائف التزامن JavaScript durable-functions
الحزمة. إنها مكتبة تعليمات برمجية تمكنك من كتابة وظائف دائمة في Python. هناك اختلافان كبيران بين دالة التزامن ودوال Python الأخرى:
- دالة المنسق هي دالة مولد.
- ينبغي أن يسجل الملفدالة المنسق كمنسق بإشارة
main = df.Orchestrator.create(<orchestrator function name>)
في نهاية الملف. يساعد هذا على تمييزه عن الدالات الأخرى المساعدة، التي تم تعريفها في الملف.
يتيح لك كائن context
استدعاء دوال نشاط أخرى وتمرير معلمات الإدخال باستخدام أسلوب call_activity
بها. تستدعي التعليمات البرمجية E1_SayHello
ثلاث مرات في تسلسل مع قيم معلمة مختلفة، باستخدام yield
للإشارة إلى التنفيذ ينبغي الانتظار على لاستدعاءات دالة النشاط المتزامنة ليتم إرجاعها. يتم إرجاع قيمة الإرجاع لكل استدعاء في نهاية الدالة.
دالة نشاط E1_SayHello
[FunctionName("E1_SayHello")]
public static string SayHello([ActivityTrigger] IDurableActivityContext context)
{
string name = context.GetInput<string>();
return $"Hello {name}!";
}
تستخدم الأنشطة ActivityTrigger
السمة. استخدم المقدم IDurableActivityContext
لتنفيذ الإجراءات المتعلقة بالنشاط، مثل الوصول إلى قيمة الإدخال باستخدام GetInput<T>
.
تنفيذ E1_SayHello
عملية تنسيق سلسلة بسيطة نسبيًا.
بدلاً من الربط إلى IDurableActivityContext
، يمكنك الربط مباشرةً إلى النوع الذي يتم تمريره إلى دالة النشاط. على سبيل المثال:
[FunctionName("E1_SayHello_DirectInput")]
public static string SayHelloDirectInput([ActivityTrigger] string name)
{
return $"Hello {name}!";
}
E1_SayHello/function.js على
دالة.js في الملف لدالة النشاط E1_SayHello
مشابهة لتلك التي باستثناء أنه يستخدم E1_HelloSequence
نوع ربط بدلاً من نوع activityTrigger
orchestrationTrigger
آخر.
{
"bindings": [
{
"name": "name",
"type": "activityTrigger",
"direction": "in"
}
],
"disabled": false
}
إشعار
يجب أن تُستخدم كافة دوال النشاط التي تسمى المقصودة من خلال التنسيق activityTrigger
الربط.
تنفيذ E1_SayHello
عملية تنسيق سلسلة بسيطة نسبيًا.
E1_SayHello/index.js
module.exports = function (context) {
context.done(null, `Hello ${context.bindings.name}!`);
};
بعكس دالة التزامن، لا تحتاج دالة النشاط إلى إعداد خاص. الإدخال الذي تم تمريره إليه بواسطة دالة المنسق موجود على context.bindings
الكائن تحت اسم الربط - في هذه activityTrigger
الحالة، context.bindings.name
. يمكن تعيين اسم الربط كمعلمة الدالة المصدرة والوصول إليه مباشرة، وهو ما يقوم به نموذج التعليمات البرمجية.
تنفيذ sayHello
عملية تنسيق سلسلة بسيطة نسبيًا.
const df = require("durable-functions");
const helloActivityName = "sayHello";
df.app.activity(helloActivityName, {
handler: function (input) {
return `Hello ${input}`;
},
});
بعكس دالة التزامن، لا تحتاج دالة النشاط إلى إعداد خاص. الإدخال الذي تم تمريره إليه بواسطة دالة المنسق هو الوسيطة الأولى للدالة. الوسيطة الثانية هي سياق استدعاء، والذي لا يتم استخدامه في هذا المثال.
E1_SayHello/function.js على
دالة.js في الملف لدالة النشاط E1_SayHello
مشابهة لتلك التي باستثناء أنه يستخدم E1_HelloSequence
نوع ربط بدلاً من نوع activityTrigger
orchestrationTrigger
آخر.
{
"scriptFile": "__init__.py",
"bindings": [
{
"name": "name",
"type": "activityTrigger",
"direction": "in"
}
]
}
إشعار
يجب أن تُستخدم كافة دوال النشاط التي تسمى المقصودة من خلال التنسيق activityTrigger
الربط.
تنفيذ E1_SayHello
عملية تنسيق سلسلة بسيطة نسبيًا.
E1_SayHello/__init__.py
def main(name: str) -> str:
return f"Hello {name}!"
بعكس دالة المنسق لا تحتاج دالة النشاط إلى أي إعداد خاص. الإدخال الذي تم تمريره إليه عبر دالة المنسق يمكن الوصول إليه مباشرة كمعلمة الدالة.
وظيفة عميل HttpStart
يمكنك بدء تشغيل مثيل دالة التزامن باستخدام دالة عميل. ستستخدم HttpStart
الدالة HTTP المشغلة لبدء مثيلات E1_HelloSequence
.
public static class HttpStart
{
[FunctionName("HttpStart")]
public static async Task<HttpResponseMessage> Run(
[HttpTrigger(AuthorizationLevel.Function, methods: "post", Route = "orchestrators/{functionName}")] HttpRequestMessage req,
[DurableClient] IDurableClient starter,
string functionName,
ILogger log)
{
// Function input comes from the request content.
object eventData = await req.Content.ReadAsAsync<object>();
string instanceId = await starter.StartNewAsync(functionName, eventData);
log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
return starter.CreateCheckStatusResponse(req, instanceId);
}
}
للتفاعل مع المنسقين، يجب أن تتضمن الوظيفة ارتباط إدخال DurableClient
. يمكنك استخدام العميل لبدء تشغيل التزامن. كما يمكن أن يساعدك في إرجاع استجابة HTTP تحتوي على عناوين "URL" للتحقق من حالة التزامن الجديد.
HttpStart/function.js
{
"bindings": [
{
"authLevel": "anonymous",
"name": "req",
"type": "httpTrigger",
"direction": "in",
"route": "orchestrators/{functionName}",
"methods": ["post"]
},
{
"name": "$return",
"type": "http",
"direction": "out"
},
{
"name": "starter",
"type": "orchestrationClient",
"direction": "in"
}
],
"disabled": false
}
للتفاعل مع المنسقين، يجب أن تتضمن الوظيفة ارتباط إدخال durableClient
.
HttpStart/index.js.js
const df = require("durable-functions");
module.exports = async function (context, req) {
const client = df.getClient(context);
const instanceId = await client.startNew(req.params.functionName, undefined, req.body);
context.log(`Started orchestration with ID = '${instanceId}'.`);
return client.createCheckStatusResponse(context.bindingData.req, instanceId);
};
يستخدم df.getClient
للحصول على DurableOrchestrationClient
عنصر. يمكنك استخدام العميل لبدء تشغيل التزامن. كما يمكن أن يساعدك في إرجاع استجابة HTTP تحتوي على عناوين "URL" للتحقق من حالة التزامن الجديد.
const df = require("durable-functions");
const { app } = require("@azure/functions");
app.http("httpStart", {
route: "orchestrators/{orchestratorName}",
extraInputs: [df.input.durableClient()],
handler: async (request, context) => {
const client = df.getClient(context);
const body = await request.json();
const instanceId = await client.startNew(request.params.orchestratorName, { input: body });
context.log(`Started orchestration with ID = '${instanceId}'.`);
return client.createCheckStatusResponse(request, instanceId);
},
});
لإدارة المنسقين والتفاعل معهم، تحتاج الدالة durableClient
إلى ربط إدخال. يجب تحديد هذا الربط في الوسيطة extraInputs
عند تسجيل الدالة. durableClient
يمكن الحصول على إدخال عن طريق استدعاء df.input.durableClient()
.
يستخدم df.getClient
للحصول على DurableClient
عنصر. يمكنك استخدام العميل لبدء تشغيل التزامن. كما يمكن أن يساعدك في إرجاع استجابة HTTP تحتوي على عناوين "URL" للتحقق من حالة التزامن الجديد.
HttpStart/function.js
{
"scriptFile": "__init__.py",
"bindings": [
{
"authLevel": "anonymous",
"name": "req",
"type": "httpTrigger",
"direction": "in",
"route": "orchestrators/{functionName}",
"methods": [
"post",
"get"
]
},
{
"name": "$return",
"type": "http",
"direction": "out"
},
{
"name": "starter",
"type": "durableClient",
"direction": "in"
}
]
}
للتفاعل مع المنسقين، يجب أن تتضمن الوظيفة ارتباط إدخال durableClient
.
HttpStart/__init__.py
import logging
import azure.functions as func
import azure.durable_functions as df
async def main(req: func.HttpRequest, starter: str) -> func.HttpResponse:
client = df.DurableOrchestrationClient(starter)
instance_id = await client.start_new(req.route_params["functionName"], None, None)
logging.info(f"Started orchestration with ID = '{instance_id}'.")
return client.create_check_status_response(req, instance_id)
استخدم DurableOrchestrationClient
الدالة الإنشائية للحصول على عميل "دالات متينة". يمكنك استخدام العميل لبدء تشغيل التزامن. كما يمكن أن يساعدك في إرجاع استجابة HTTP تحتوي على عناوين "URL" للتحقق من حالة التزامن الجديد.
تشغيل تطبيق العرض التوضيحي
لتنفيذ E1_HelloSequence
التزامن، إرسال طلب HTTP POST التالي إلى HttpStart
الدالة.
POST http://{host}/orchestrators/E1_HelloSequence
إشعار
يفترض قصاصة محتوى HTTP السابق وجود إدخال في host.json
الملف الذي يزيل api/
البادئة الافتراضية من كافة عناوين URLدوال تشغيل HTTP. يمكنك العثور على علامات هذا التكوين في host.json
الملف في العينات.
على سبيل المثال، إذا كنت تقوم بتشغيل العينة في تطبيق دالة يسمى "myfunctionapp"، استبدل "{host}" ب "myfunctionapp.azurewebsites.net".
والنتيجة هي استجابة HTTP 202، مثل هذا (قلصت للإيجاز) :
HTTP/1.1 202 Accepted
Content-Length: 719
Content-Type: application/json; charset=utf-8
Location: http://{host}/runtime/webhooks/durabletask/instances/96924899c16d43b08a536de376ac786b?taskHub=DurableFunctionsHub&connection=Storage&code={systemKey}
(...trimmed...)
عند هذه النقطة، التزامن في قائمة الانتظار ويبدأ التشغيل مباشرة. يمكن استخدام عنوان موقع ويب في Location
الرأس للتحقق من حالة التنفيذ.
GET http://{host}/runtime/webhooks/durabletask/instances/96924899c16d43b08a536de376ac786b?taskHub=DurableFunctionsHub&connection=Storage&code={systemKey}
والنتيجة هي حالة التزامن. يتم تشغيله وإكماله بسرعة، بحيث تراه في الحالة المكتملة مع استجابة تبدو هكذا (تم اقتطاعها للإيجاز):
HTTP/1.1 200 OK
Content-Length: 179
Content-Type: application/json; charset=utf-8
{"runtimeStatus":"Completed","input":null,"output":["Hello Tokyo!","Hello Seattle!","Hello London!"],"createdTime":"2017-06-29T05:24:57Z","lastUpdatedTime":"2017-06-29T05:24:59Z"}
كما ترى، runtimeStatus
للمثيل مكتمل ويحتوي output
على نتيجة تسلسل JSON تنفيذ دالة المنسق.
إشعار
يمكنك تنفيذ منطق بداية مشابه لأنواع المشغلات الأخرى، مثل queueTrigger
أو eventHubTrigger
أو timerTrigger
.
انظر إلى سجلات تنفيذ الدالة. E1_HelloSequence
بدأت الدالة واكتملت عدة مرات بسبب سلوك إعادة وصفها في موضوع موثوقية التزامن. ومن ناحية أخرى، لم تنفذ سوى ثلاث عمليات E1_SayHello
لأن هذه التنفيذات للدالة لا تعاد.
الخطوات التالية
وقد أظهرت هذه العينة البسيطة دالة سلسلة التزامن. تظهر العينة التالية كيفية تنفيذ نمط fan-out\fan-in.