إشعار
يتطلب الوصول إلى هذه الصفحة تخويلاً. يمكنك محاولة تسجيل الدخول أو تغيير الدلائل.
يتطلب الوصول إلى هذه الصفحة تخويلاً. يمكنك محاولة تغيير الدلائل.
يقوم Azure Functions بتنفيذ كود تطبيقك باستخدام معالجات خاصة باللغات. تسمح هذه المعالجات الخاصة باللغة للوظائف بدعم معظم اللغات الرئيسية بشكل افتراضي. ومع ذلك، قد تحتاج إلى تشغيل كود بلغة أو حزمة أخرى.
المعالجات المخصصة هي خوادم ويب خفيفة الوزن تستقبل الأحداث من عملية استضافة Azure Functions. يمكنك استخدام معالجات مخصصة لنشر أي مشروع كود يدعم أساسيات HTTP على Azure Functions.
تعد المعالجات المخصصة هي الأنسب للمواقف التي تريد فيها أن تقوم بما يلي:
- قم بتنفيذ تطبيق وظائف بلغة غير متوفرة حاليا بشكل جاهز، مثل Go أو Rust.
- تنفيذ تطبيق وظيفة في وقت تشغيل غير مميز حالياً بشكل افتراضي، مثل Deno.
- نشر خادم مبني باستخدام مجموعات تطوير MCP القياسية على Azure Functions.
باستخدام المعالجات المخصصة، يمكنك استخدام المشغلات وروابط الإدخال والإخراج عبر حزم الملحق.
ابدأ استخدام معالجات Azure Functions المخصصة من خلال قوالب التشغيل السريع لـ Go وRust.
نظرة عامة
يوضح الرسم التخطيطي التالي العلاقة بين مضيف الوظائف وخادم الويب الذي تم تنفيذه كمعالج مخصص.
- يقوم كل حدث بتشغيل طلب يتم إرساله إلى مضيف الوظائف. الحدث هو أي مشغل يدعمه Azure Functions.
- ومن ثَم يقوم مضيف الوظائف بإصدار بيانات طلب أساسية إلى خادم الويب. تحمل البيانات الأساسية بيانات المدخلات وربط المشغل وبيانات التعريف الأخرى للوظيفة.
- ينفذ خادم الويب الوظيفة الفردية، ويعيد بيانات الاستجابة الأساسية إلى مضيف الوظائف.
- يمرر مضيف الوظائف البيانات من الاستجابة إلى روابط إخراج الوظيفة لأجل المعالجة.
يجب أن يقوم تطبيق Azure Functions المنفذ كمعالج مخصص بتكوين ملفات host.json وlocal.settings.json وfunction.json وفقاً لبعض الاصطلاحات.
نشر خوادم MCP المستضافة ذاتيا
المعالجات المخصصة تتيح لك أيضا استضافة خوادم MCP التي تبنيها باستخدام مجموعات تطوير البرمجيات الرسمية في Azure Functions. المعالجات المخصصة توفر تجربة بسيطة وبسيطة لاستضافة خوادم MCP الخاصة بك على Azure. لمزيد من المعلومات، راجع خادم MCP البعيد المستضاف ذاتيا على Azure Functions.
إشعار
إمكانية استضافة Azure Functions لخوادم MCP التي تنشئها باستخدام مجموعات تطوير البرمجيات الرسمية ل MCP حاليا قيد المعاينة.
بنية التطبيق
لتنفيذ معالج مخصص، يحتاج تطبيقك إلى الجوانب التالية:
- ملف host.json في جذر تطبيقك
- ملف local.settings.json في جذر تطبيقك
- ملف function.json لكل وظيفة (داخل مجلد يطابق اسم الوظيفة)
- أمر أو سكريبت أو ملف تنفيذي يشغل خادم ويب
يوضح الرسم التخطيطي التالي كيف تبدو هذه الملفات على نظام الملفات لدالة تسمى "MyQueueFunction" ومعالج مخصص قابل للتنفيذ يسمى handler.exe.
| /MyQueueFunction
| function.json
|
| host.json
| local.settings.json
| handler.exe
التكوين
تقوم بتكوين التطبيق من خلال ملفات host.json وlocal.settings.json .
host.json
host.json يوجه مضيف الوظائف إلى أين يرسل الطلبات من خلال الإشارة إلى خادم ويب يمكنه معالجة أحداث HTTP.
حدد معالجا مخصصا عن طريق تكوين ملف host.json مع تفاصيل كيفية تشغيل خادم الويب عبر القسم customHandler .
{
"version": "2.0",
"customHandler": {
"description": {
"defaultExecutablePath": "handler.exe"
}
}
}
يشير قسم customHandler إلى هدف كما هو محدد بواسطة defaultExecutablePath. يمكن أن يكون هدف التنفيذ أمرا أو ملف تنفيذي أو ملف يتم فيه تنفيذ خادم الويب.
استخدم الصفيف arguments لتمرير أية وسيطات إلى الملف القابل للتنفيذ. تدعم الحجج توسيع متغيرات البيئة (إعدادات التطبيق) باستخدام %% الترميز.
يمكنك أيضاً تغيير دليل العمل الذي يستخدمه الملف القابل للتنفيذ مع workingDirectory.
{
"version": "2.0",
"customHandler": {
"description": {
"defaultExecutablePath": "app/handler.exe",
"arguments": [
"--database-connection-string",
"%DATABASE_CONNECTION_STRING%"
],
"workingDirectory": "app"
}
}
}
دعم الروابط
تتوفر المشغلات القياسية بجانب روابط الإدخال والإخراج من خلال الرجوع إلى حزم الملحق في ملف host.json.
local.settings.json
يحدد local.settings.json إعدادات التطبيق المستخدمة عند تشغيل تطبيق الوظيفة محلياً. لأنه قد يحتوي على أسرار، استبعد local.settings.json من التحكم في المصدر. في Azure، استخدم إعدادات التطبيق بدلاً من ذلك.
بالنسبة إلى المعالجات المخصصة، اضبط FUNCTIONS_WORKER_RUNTIME على Custom في local.settings.json.
{
"IsEncrypted": false,
"Values": {
"FUNCTIONS_WORKER_RUNTIME": "Custom"
}
}
بيانات تعريف الوظيفة
عند استخدام معالج مخصص، تكون محتوياتfunction.json نفسها عند تعريف دالة في أي سياق آخر. الشرط الوحيد هو وضع function.json الملفات في مجلد يحمل اسما ليطابق اسم الوظيفة.
يعمل ملف function.json التالي على تكوين وظيفة بها مشغل قائمة انتظار وربط إخراج قائمة انتظار. ونظراً إلى وجودها في مجلد باسم MyQueueFunction، فإنها تحدد وظيفة تسمى MyQueueFunction.
MyQueueFunction/function.json
{
"bindings": [
{
"name": "myQueueItem",
"type": "queueTrigger",
"direction": "in",
"queueName": "messages-incoming",
"connection": "AzureWebJobsStorage"
},
{
"name": "$return",
"type": "queue",
"direction": "out",
"queueName": "messages-outgoing",
"connection": "AzureWebJobsStorage"
}
]
}
بيانات الطلب الأساسية
عندما يتلقى مضيف الوظائف رسالة طابور، يرسل طلب HTTP post إلى المعالج المخصص مع حمولة في الجسم.
الكود التالي يعرض حمولة طلب عينة. تتضمن البيانات الأساسية بنية JSON مع عضوين: Data وMetadata.
يشتمل العضو Data على مفاتيح تطابق أسماء الإدخال والمشغل كما هو محدد في صفيف الروابط في ملف function.json.
ويشتمل العضو Metadata على بيانات تعريف تم إنشاؤها من مصدر الحدث.
{
"Data": {
"myQueueItem": "{ message: \"Message sent\" }"
},
"Metadata": {
"DequeueCount": 1,
"ExpirationTime": "2019-10-16T17:58:31+00:00",
"Id": "800ae4b3-bdd2-4c08-badd-f08e5a34b865",
"InsertionTime": "2019-10-09T17:58:31+00:00",
"NextVisibleTime": "2019-10-09T18:08:32+00:00",
"PopReceipt": "AgAAAAMAAAAAAAAAAgtnj8x+1QE=",
"sys": {
"MethodName": "QueueTrigger",
"UtcNow": "2019-10-09T17:58:32.2205399Z",
"RandGuid": "24ad4c06-24ad-4e5b-8294-3da9714877e9"
}
}
}
بيانات الاستجابة الأساسية
حسب الاصطلاح، يتم تنسيق استجابات الوظائف كأزواج مفتاح/قيمة. تتضمن المفاتيح المدعمة:
|
|
نوع البيانات | الملاحظات |
|---|---|---|
Outputs |
كائن | يحمل قيم الاستجابة كما هو محدد بواسطة صفيف bindings في function.json.على سبيل المثال، إذا تم تكوين دالة بربط مخرج الطابور يسمى "myQueueOutput"، فإنها Outputs تحتوي على مفتاح باسم myQueueOutput، والذي يقوم المعالج المخصص بتعيينه على الرسائل التي يرسلها إلى الطابور. |
Logs |
صفيف | الرسائل التي تظهر في سجلات استدعاء الوظائف. عند التشغيل في Azure، تظهر الرسائل في Application Insights. |
ReturnValue |
سلسلة | تُستخدم لتقديم استجابة عند تكوين خرج مثل $return في ملف function.json. |
يعرض هذا الجدول مثالا على حمولة استجابة.
{
"Outputs": {
"res": {
"body": "Message enqueued"
},
"myQueueOutput": [
"queue message 1",
"queue message 2"
]
},
"Logs": [
"Log message 1",
"Log message 2"
],
"ReturnValue": "{\"hello\":\"world\"}"
}
الأمثلة
يمكنك تنفيذ معالجات مخصصة بأي لغة تدعم استقبال أحداث HTTP. الأمثلة التالية توضح كيفية تنفيذ معالج مخصص باستخدام لغة البرمجة Go.
الوظيفة مع الروابط
يظهر هذا المثال دالة تحمل order طلبا POST مع حمولة تمثل طلب منتج. عندما ترسل طلبا إلى الدالة، فإنها تنشئ رسالة تخزين الطابور وتعيد استجابة HTTP.
تنفيذ
في المجلد المسمى الطلب، يقوم ملف function.json بتكوين الوظيفة التي يتم تشغيلها بواسطة HTTP.
order/function.json
{
"bindings": [
{
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": ["post"]
},
{
"type": "http",
"direction": "out",
"name": "res"
},
{
"type": "queue",
"name": "message",
"direction": "out",
"queueName": "orders",
"connection": "AzureWebJobsStorage"
}
]
}
يتم تعريف هذه الوظيفة على أنها وظيفة يتم تشغيلها بواسطة HTTP والتي تعرض استجابة HTTP وتخرج رسالة تخزين قائمة الانتظار.
في جذر التطبيق، تمت تكوين ملف host.json لتشغيل ملف قابل للتنفيذ باسم handler.exe (handler في Linux أو macOS).
{
"version": "2.0",
"customHandler": {
"description": {
"defaultExecutablePath": "handler.exe"
}
},
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[4.*, 5.0.0)"
}
}
يعد هذا هو طلب HTTP المرسل إلى وقت تشغيل الوظائف.
POST http://127.0.0.1:7071/api/order HTTP/1.1
Content-Type: application/json
{
"id": 1005,
"quantity": 2,
"color": "black"
}
يرسل وقت تشغيل الوظائف طلب HTTP التالي إلى المعالج المخصص:
POST http://127.0.0.1:<FUNCTIONS_CUSTOMHANDLER_PORT>/order HTTP/1.1
Content-Type: application/json
{
"Data": {
"req": {
"Url": "http://localhost:7071/api/order",
"Method": "POST",
"Query": "{}",
"Headers": {
"Content-Type": [
"application/json"
]
},
"Params": {},
"Body": "{\"id\":1005,\"quantity\":2,\"color\":\"black\"}"
}
},
"Metadata": {
}
}
إشعار
تمت إزالة بعض أجزاء البيانات الأساسية لغرض الإيجاز.
يعد handler.exe عبارة عن برنامج معالج لغة Go المخصص للتحويل برمجياً والذي يقوم بتشغيل خادم ويب ويستجيب لطلبات استدعاء الوظيفة من مضيف الوظائف.
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"os"
)
type InvokeRequest struct {
Data map[string]json.RawMessage
Metadata map[string]interface{}
}
type InvokeResponse struct {
Outputs map[string]interface{}
Logs []string
ReturnValue interface{}
}
func orderHandler(w http.ResponseWriter, r *http.Request) {
var invokeRequest InvokeRequest
d := json.NewDecoder(r.Body)
d.Decode(&invokeRequest)
var reqData map[string]interface{}
json.Unmarshal(invokeRequest.Data["req"], &reqData)
outputs := make(map[string]interface{})
outputs["message"] = reqData["Body"]
resData := make(map[string]interface{})
resData["body"] = "Order enqueued"
outputs["res"] = resData
invokeResponse := InvokeResponse{outputs, nil, nil}
responseJson, _ := json.Marshal(invokeResponse)
w.Header().Set("Content-Type", "application/json")
w.Write(responseJson)
}
func main() {
customHandlerPort, exists := os.LookupEnv("FUNCTIONS_CUSTOMHANDLER_PORT")
if !exists {
customHandlerPort = "8080"
}
mux := http.NewServeMux()
mux.HandleFunc("/order", orderHandler)
fmt.Println("Go server Listening on: ", customHandlerPort)
log.Fatal(http.ListenAndServe(":"+customHandlerPort, mux))
}
في هذا المثال، يقوم المعالج المخصص بتشغيل خادم ويب للتعامل مع أحداث HTTP ويستمع للطلبات عبر .FUNCTIONS_CUSTOMHANDLER_PORT
على الرغم من أن مضيف الوظائف يستقبل طلب HTTP الأصلي عند /api/order، فإنه يستدعي المعالج المخصص باستخدام اسم الدالة (اسم المجلد الخاص به). في هذا المثال، يتم تحديد الوظيفة في مسار /order. يرسل المضيف إلى المعالج المخصص طلب HTTP في مسار /order.
عند إرسال POST الطلبات إلى هذه الوظيفة، تتوفر بيانات الزناد وبيانات الوظيفة عبر جسم طلب HTTP. يمكنك الوصول إلى جسم طلب HTTP الأصلي في ملف Data.req.Body.
يتم تنسيق استجابة الوظيفة في أزواج مفتاح/قيمة حيث يحتفظ العضو Outputs بقيمة JSON حيث تتطابق المفاتيح مع المخرجات كما هو محدد في ملف function.json.
هذا مثال على البيانات الأساسية التي يقوم هذا المعالج بإرجاعها إلى مضيف الوظائف.
{
"Outputs": {
"message": "{\"id\":1005,\"quantity\":2,\"color\":\"black\"}",
"res": {
"body": "Order enqueued"
}
},
"Logs": null,
"ReturnValue": null
}
من خلال تعيين إخراج message مساوياً لبيانات الطلب الواردة من الطلب، تقوم الوظيفة بإخراج بيانات الطلب إلى قائمة الانتظار المكونة. يعمل مضيف الوظائف أيضاً على إرجاع استجابة HTTP المكونة في res إلى المستدعي.
وظيفة HTTP فقط
بالنسبة للوظائف التي تعمل ب HTTP بدون قيود أو مخرجات إضافية، قد ترغب في أن يعمل معالجك مباشرة مع طلب واستجابة HTTP بدلا من طلبات المعالج المخصصة وحمولة الرد . يمكنك تكوين هذا السلوك في host.json باستخدام الإعداد enableProxyingHttpRequest الذي يدعم بث الاستجابة.
هام
الغرض الأساسي من ميزة المعالجات المخصصة هو تمكين اللغات وأوقات التشغيل التي لا تدعم حاليا وظائف Azure من الدرجة الأولى. بينما قد تتمكن من تشغيل تطبيقات الويب باستخدام معالجات مخصصة، فإن Azure Functions ليس وكيل عكسي عادي. قد تكون بعض مكونات طلب HTTP، مثل بعض الرؤوس والمسارات، مقيدة. قد يواجه طلبك أيضا بداية باردة جدا.
لمعالجة هذه الظروف، ضع في اعتبارك تشغيل تطبيقات الويب في Azure App Service.
يوضح المثال التالي كيفية تكوين وظيفة يتم تشغيلها بواسطة HTTP بدون روابط أو مخرجات إضافية. يتميز السيناريو الذي تم تنفيذه في هذا المثال بوظيفة تسمى hello تقبل GET أو POST.
تنفيذ
في المجلد المسمى hello، يقوم ملف function.json بتكوين الوظيفة المشغلة بواسطة HTTP.
hello/function.json
{
"bindings": [
{
"type": "httpTrigger",
"authLevel": "anonymous",
"direction": "in",
"name": "req",
"methods": ["get", "post"]
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
يتم تكوين الدالة لقبول كلا GETPOST الطلبين، ويتم توفير قيمة النتيجة من خلال وسيط يسمى res.
في جذر التطبيق، تم تكوين ملف host.json لتشغيل handler.exe وتعيين enableProxyingHttpRequest إلى true.
{
"version": "2.0",
"customHandler": {
"description": {
"defaultExecutablePath": "handler.exe"
},
"enableProxyingHttpRequest": true
}
}
فيما يلي طلب POST إلى مضيف الوظائف. ثم يرسل مضيف الوظائف الطلب إلى معالج التعديل.
POST http://127.0.0.1:7071/api/hello HTTP/1.1
Content-Type: application/json
{
"message": "Hello World!"
}
ينفذ ملف handler.go وظيفة خادم ويب وHTTP.
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
)
func helloHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
if r.Method == "GET" {
w.Write([]byte("hello world"))
} else {
body, _ := ioutil.ReadAll(r.Body)
w.Write(body)
}
}
func main() {
customHandlerPort, exists := os.LookupEnv("FUNCTIONS_CUSTOMHANDLER_PORT")
if !exists {
customHandlerPort = "8080"
}
mux := http.NewServeMux()
mux.HandleFunc("/api/hello", helloHandler)
fmt.Println("Go server Listening on: ", customHandlerPort)
log.Fatal(http.ListenAndServe(":"+customHandlerPort, mux))
}
في هذا المثال، يقوم المعالج المخصص بإنشاء خادم ويب للتعامل مع أحداث HTTP ويستمع للطلبات عبر .FUNCTIONS_CUSTOMHANDLER_PORT
يتم معالجة طلبات GET من خلال إرجاع السلسلة، ويكون لطلبات POST حق الوصول إلى نص الطلب الأساسي.
يعد مسار وظيفة الطلب هنا هو /api/hello، مثل الطلب الأصلي.
إشعار
FUNCTIONS_CUSTOMHANDLER_PORT ليس المنفذ المواجه للجمهور المستخدم لاستدعاء الوظيفة. يستخدم مضيف الوظائف هذا المنفذ لاستدعاء المعالج المخصص.
النشر
يمكنك نشر معالج مخصص لكل خيار استضافة Azure Functions. إذا كان معالجك يتطلب اعتمادات على نظام التشغيل أو المنصة (مثل وقت تشغيل اللغة)، فقد تحتاج إلى استخدام حاوية مخصصة.
عند إنشاء تطبيق وظائف في Azure للمعالجات المخصصة، اختر .NET Core كمكدس.
لنشر تطبيق معالج مخصص باستخدام Azure Functions Core Tools، قم بتشغيل الأمر التالي.
func azure functionapp publish $functionAppName
إشعار
تأكد من أن جميع الملفات المطلوبة لتشغيل المعالج المخصص موجودة في المجلد ومضمنة في عملية النشر. إذا كان المعالج المخصص عبارة عن ملف ثنائي قابل للتنفيذ أو يحتوي على تبعيات خاصة بالنظام الأساسي، فتأكد من تطابق هذه الملفات مع النظام الأساسي للنشر المستهدف.
القيود
- يجب أن يبدأ خادم الويب المخصص للمعالج في غضون 60 ثانية.
العينات
للحصول على أمثلة حول كيفية تنفيذ الدوال بلغات مختلفة، راجع عينات المعالج المخصصة في مستودع GitHub.
استكشاف الأخطاء وإصلاحها والدعم
تتبع التسجيل
إذا فشل تشغيل عملية المعالج المخصص لديك أو إذا واجهت مشاكل في التواصل مع مضيف الوظائف، قم بزيادة مستوى سجل تطبيق الدالة لرؤية Trace المزيد من رسائل التشخيص من المضيف.
لتغيير مستوى السجل الافتراضي لتطبيق الوظيفة، قم بتكوين الإعداد logLevel في قسم logging لـ host.json.
{
"version": "2.0",
"customHandler": {
"description": {
"defaultExecutablePath": "handler.exe"
}
},
"logging": {
"logLevel": {
"default": "Trace"
}
}
}
يقوم مضيف الوظائف بإخراج رسائل سجل إضافية، بما في ذلك معلومات تتعلق بعملية المعالج المخصص. استخدم السجلات لاستكشاف المشكلات في بدء تشغيل معالجة المعالج المخصص أو استدعاء الوظائف في المعالج المخصص.
بشكل محلي، تتم طباعة السجلات على وحدة التحكم.
في Azure، استعلم عن تتبعات Application Insights لعرض رسائل السجل. إذا كان تطبيقك ينتج عدداً كبيراً من السجلات، فسيتم إرسال مجموعة فرعية فقط من رسائل السجل إلى Application Insights. قم بتعطيل أخذ العينات لضمان تسجيل جميع الرسائل.
اختبار المعالج المخصص بمعزل عن غيره
تطبيقات المعالجات المخصصة هي عمليات خادم ويب، لذا قد يكون من المفيد تشغيلها بنفسها واختبار استدعاءات الوظائف بإرسال طلبات HTTP وهمية. لإرسال طلبات HTTP مع حمولات، تأكد من اختيار أداة تحافظ على أمان بياناتك. لمزيد من المعلومات، راجع أدوات اختبار HTTP.
ويمكنك أيضاً استخدام هذه الإستراتيجية في مسارات التكامل المستمر والتسليم المستمر لإجراء اختبارات تلقائية على معالجك المخصص.
بيئة التنفيذ
تعمل المعالجات المخصصة في نفس البيئة مثل تطبيق Azure Functions النموذجي. اختبر المعالج للتأكد من أن البيئة تحتوي على جميع التبعيات التي تحتاجها للتشغيل. بالنسبة للتطبيقات التي تتطلب تبعيات إضافية، قد تحتاج إلى تشغيلها باستخدام صورة حاوية مخصصة مستضافة على خطة Azure Functions Premium.
الحصول على الدعم
إذا كنت بحاجة إلى مساعدة بشأن تطبيق وظيفة مع معالجات مخصصة، فيمكنك إرسال طلب من خلال قنوات الدعم العادية. ومع ذلك، وبسبب التنوع الكبير في اللغات الممكنة المستخدمة لبناء تطبيقات معالجات مخصصة، فإن الدعم ليس بلا حدود.
يتوفر الدعم إذا واجه مضيف الوظائف مشاكل في بدء عملية المعالج المخصص أو الاتصال بها. بالنسبة للمشاكل المتعلقة بكيفية عمل عملية المعالج المخصص لديك، مثل مشاكل في اللغة أو الإطار العملي المختار، لا يمكن لفريق الدعم لدينا تقديم المساعدة في هذا السياق.
الخطوات التالية
ابدأ في إنشاء تطبيق Azure Functions باستخدام لغة Go أو Rust من خلال التشغيل السريع المخصص للمعالجات.