البرنامج التعليمي: إنشاء تطبيق دردشة في الوقت الحقيقي بلا خادم باستخدام Azure Functions وخدمة Azure Web PubSub

تساعدك خدمة Azure Web PubSub في إنشاء تطبيقات ويب للمراسلة في الوقت الفعلي باستخدام WebSockets ونمط النشر والاشتراك بسهولة. Azure Functions هو نظام أساسي بلا خادم يتيح لك تشغيل التعليمات البرمجية دون إدارة أي بنية أساسية. في هذا البرنامج التعليمي، ستتعلم كيفية استخدام خدمة Azure Web PubSub وAzure Functions لإنشاء تطبيق بلا خادم مع مراسلة في الوقت الفعلي ونمط اشتراك للنشر.

في هذا البرنامج التعليمي، تتعلم كيفية:

  • إنشاء تطبيق دردشة في الوقت الفعلي بلا خادم
  • العمل مع روابط المشغل لدالة Web PubSub وارتباطات الإخراج
  • توزيع الدالة إلى تطبيق Azure Function
  • تكوين مصادقة Azure
  • تكوين Web PubSub Event Handler لتوجيه الأحداث والرسائل إلى التطبيق

المتطلبات الأساسية

إذا لم يكن لديك اشتراك في Azure، فأنشئ حساب Azure مجاني قبل أن تبدأ.

تسجيل الدخول إلى Azure

سجل الدخول إلى مدخل Microsoft Azure على https://portal.azure.com/ باستخدام بيانات حساب Azure.

إنشاء مثيل خدمة Azure Web PubSub

سيقوم التطبيق بالاتصال بمثيل خدمة Web PubSub في Azure.

  1. حدد الزر جديد «New» الموجود في الزاوية العلوية اليسرى من مدخل Microsoft Azure. في الشاشة «New»، اكتب «Web PubSub» في مربع البحث واضغط على إدخال. (يمكنك أيضًا البحث في Azure Web PubSub من الفئة Web.)

    لقطة شاشة للبحث في Azure Web PubSub في المدخل.

  2. حدد «Web PubSub» من نتائج البحث، ثم حدد «Create».

  3. أدخل الإعدادات التالية.

    الإعدادات القيمة المقترحة ‏‏الوصف
    اسم المورد اسم فريد عالميًا الاسم الفريد العام الذي يعرّف مثيل خدمة Web PubSub الجديد. الأحرف الصالحة هي a-zو A-Z0-9و و.-
    الاشتراك اشتراكك اشتراك Azure الذي يتم بموجبه إنشاء مثيل خدمة Web PubSub الجديد هذا.
    مجموعة الموارد myResourceGroup اسم مجموعة الموارد الجديدة التي يتم فيها إنشاء مثيل خدمة Web PubSub.
    Location غرب الولايات المتحدة اختر منطقة قريبة منك.
    مستوى الأسعار مجاني يمكنك أولًا تجربة خدمة Azure Web PubSub مجانًا. تعرف على مزيد من التفاصيل حول مستويات تسعير خدمة Azure Web PubSub
    عدد الوحدات - يحدد عدد الوحدات عدد الاتصالات التي يمكن لمثيل خدمة PubSub على الويب قبولها. تدعم كل وحدة 1000 اتصال متزامن على الأكثر. لا يمكن تكوينه إلا في المستوى القياسي.

    لقطة شاشة لإنشاء مثيل Azure Web PubSub في المدخل.

  4. حدد «Create» لبدء نشر مثيل خدمة Web PubSub.

إنشاء الوظائف

  1. تأكد من تثبيت Azure Functions Core Tools. ثم قم بإنشاء دليل فارغ للمشروع. قم بتشغيل الأمر ضمن دليل العمل هذا.

    func init --worker-runtime javascript --model V4
    
  2. تثبيت Microsoft.Azure.WebJobs.Extensions.WebPubSub.

    قم بتأكيد وتحديث host.jsonextensionBundle إلى الإصدار 4.* أو أحدث للحصول على دعم Web PubSub.

    {
      "extensionBundle": {
        "id": "Microsoft.Azure.Functions.ExtensionBundle",
        "version": "[4.*, 5.0.0)"
      }
    }
    
  3. قم بإنشاء دالة index لقراءة واستضافة صفحة ويب ثابتة للعملاء.

    func new -n index -t HttpTrigger
    
    • قم بتحديث src/functions/index.js وانسخ التعليمات البرمجية التالية.
      const { app } = require('@azure/functions');
      const { readFile } = require('fs/promises');
      
      app.http('index', {
          methods: ['GET', 'POST'],
          authLevel: 'anonymous',
          handler: async (context) => {
              const content = await readFile('index.html', 'utf8', (err, data) => {
                  if (err) {
                      context.err(err)
                      return
                  }
              });
      
              return { 
                  status: 200,
                  headers: { 
                      'Content-Type': 'text/html'
                  }, 
                  body: content, 
              };
          }
      });
      
  4. أنشئ الدالة negotiate لمساعدة العملاء في الحصول على عنوان url لاتصال الخدمة مع رمز الوصول المميز.

    func new -n negotiate -t HttpTrigger
    

    إشعار

    في هذا النموذج، نستخدم عنوان x-ms-client-principal-name هوية مستخدم معرف Microsoft Entra لاسترداد userId. وهذا لن ينجح في دالة محلية. يمكنك جعله فارغًا أو التغيير إلى طرق أخرى للحصول على أو إنشاء userId عند اللعب باللغة المحلية. على سبيل المثال، اسمح للعميل بكتابة اسم مستخدم وتمريره في استعلام مثل دالة ?user={$username} عند استدعاء الدالة negotiate للحصول على عنوان URL لاتصال الخدمة. في الدالة negotiate، اضبط userId بقيمة {query.user}.

    • قم بتحديث src/functions/negotiate وانسخ التعليمات البرمجية التالية.
      const { app, input } = require('@azure/functions');
      
      const connection = input.generic({
          type: 'webPubSubConnection',
          name: 'connection',
          userId: '{headers.x-ms-client-principal-name}',
          hub: 'simplechat'
      });
      
      app.http('negotiate', {
          methods: ['GET', 'POST'],
          authLevel: 'anonymous',
          extraInputs: [connection],
          handler: async (request, context) => {
              return { body: JSON.stringify(context.extraInputs.get('connection')) };
          },
      });
      
  5. قم بإنشاء دالة message لبث رسائل العميل من خلال الخدمة.

    func new -n message -t HttpTrigger
    
    • قم بتحديث src/functions/message.js وانسخ التعليمات البرمجية التالية.
      const { app, output, trigger } = require('@azure/functions');
      
      const wpsMsg = output.generic({
          type: 'webPubSub',
          name: 'actions',
          hub: 'simplechat',
      });
      
      const wpsTrigger = trigger.generic({
          type: 'webPubSubTrigger',
          name: 'request',
          hub: 'simplechat',
          eventName: 'message',
          eventType: 'user'
      });
      
      app.generic('message', {
          trigger: wpsTrigger,
          extraOutputs: [wpsMsg],
          handler: async (request, context) => {
              context.extraOutputs.set(wpsMsg, [{
                  "actionName": "sendToAll",
                  "data": `[${context.triggerMetadata.connectionContext.userId}] ${request.data}`,
                  "dataType": request.dataType
              }]);
      
              return {
                  data: "[SYSTEM] ack.",
                  dataType: "text",
              };
          }
      });
      
  6. أضف صفحة index.html العميل الفردية في المجلد الجذر للمشروع وانسخ المحتوى.

    <html>
      <body>
        <h1>Azure Web PubSub Serverless Chat App</h1>
        <div id="login"></div>
        <p></p>
        <input id="message" placeholder="Type to chat..." />
        <div id="messages"></div>
        <script>
          (async function () {
            let authenticated = window.location.href.includes(
              "?authenticated=true"
            );
            if (!authenticated) {
              // auth
              let login = document.querySelector("#login");
              let link = document.createElement("a");
              link.href = `${window.location.origin}/.auth/login/aad?post_login_redirect_url=/api/index?authenticated=true`;
              link.text = "login";
              login.appendChild(link);
            } else {
              // negotiate
              let messages = document.querySelector("#messages");
              let res = await fetch(`${window.location.origin}/api/negotiate`, {
                credentials: "include",
              });
              let url = await res.json();
              // connect
              let ws = new WebSocket(url.url);
              ws.onopen = () => console.log("connected");
              ws.onmessage = (event) => {
                let m = document.createElement("p");
                m.innerText = event.data;
                messages.appendChild(m);
              };
              let message = document.querySelector("#message");
              message.addEventListener("keypress", (e) => {
                if (e.charCode !== 13) return;
                ws.send(message.value);
                message.value = "";
              });
            }
          })();
        </script>
      </body>
    </html>
    

إنشاء تطبيق وظائف Azure ونشره

قبل أن تتمكن من نشر رمز دالتك على Azure، تحتاج إلى إنشاء ثلاثة موارد:

  • مجموعة الموارد عبارة عن حاوية منطقية للموارد.
  • حساب تخزين، وهو يستخدم للاحتفاظ بالحالة والمعلومات الأخرى بشأن الدوال لديك.
  • تطبيق الوظيفة، الذي يوفر البيئة لتنفيذ التعليمة البرمجية للوظيفة. يتيح تطبيق الدالة التعيين إلى مشروع الدالة المحلي وتجميع الدوال كوحدة منطقية لتيسير إدارة الموارد وتوزيعها ومشاركتها.

استخدم الأوامر التالية لإنشاء هذه العناصر.

  1. إذا لم تكن قد فعلت ذلك بالفعل، سجل الدخول إلى Azure:

    az login
    
  2. إنشاء مجموعة موارد أو يمكنك التخطي عن طريق إعادة استخدام إحدى خدمات Azure Web PubSub:

    az group create -n WebPubSubFunction -l <REGION>
    
  3. إنشاء حساب تخزين للأغراض العامة في مجموعة الموارد والمنطقة الخاصة بك:

    az storage account create -n <STORAGE_NAME> -l <REGION> -g WebPubSubFunction
    
  4. أنشئ تطبيق الدالة في Azure:

    az functionapp create --resource-group WebPubSubFunction --consumption-plan-location <REGION> --runtime node --runtime-version 18 --functions-version 4 --name <FUNCIONAPP_NAME> --storage-account <STORAGE_NAME>
    

    إشعار

    تحقق من وثائق إصدارات وقت تشغيل Azure Functions لتعيين --runtime-version المعلمة إلى القيمة المدعومة.

  5. انشر مشروع الدالة في Azure:

    بعد إنشاء تطبيق الوظائف الخاص بك بنجاح في Azure، أنت الآن جاهز لنشر مشروع الوظائف المحلية باستخدام الأمر func azure functionapp publish .

    func azure functionapp publish <FUNCIONAPP_NAME>
    
  6. تكوين WebPubSubConnectionString لتطبيق الدالة الجديدة:

    أولاً، ابحث عن مورد Web PubSub من مدخل Microsoft Azure وانسخ سلسلة الاتصال ضمن مفاتيح. ثم انتقل إلى Function App settings في مدخل Microsoft Azure ->الإعدادات ->Configuration. وأضف عنصرًا جديدًا ضمن إعدادات التطبيق، باسم يساوي WebPubSubConnectionString والقيمة هي سلسلة اتصال مورد Web PubSub.

تكوين خدمة Web PubSub Event Handler

في هذه العينة، نستخدم WebPubSubTrigger للاستماع إلى طلبات المصدر للخدمة. لذلك يحتاج Web PubSub إلى معرفة معلومات نقطة النهاية الخاصة بالدالة من أجل إرسال طلبات العميل المستهدفة. ويتطلب تطبيق Azure Function مفتاح نظام للأمان فيما يتعلق بأساليب webhook الخاصة بالملحق. في الخطوة السابقة بعد نشر تطبيق الدالة بوظائف message، يمكننا الحصول على مفتاح النظام.

انتقل إلى مدخل Microsoft Azure -> ابحث عن مورد Function App ->مفاتيح التطبيق ->مفاتيح النظام ->webpubsub_extension. انسخ القيمة كـ <APP_KEY>.

 لقطة شاشة للحصول على مفاتيح نظام الوظائف.

قم بتعيين Event Handler في خدمة Azure Web PubSub. انتقل إلى مدخل Microsoft Azure -> ابحث عن مورد Web PubSub ->الإعدادات. إضافة تعيين إعدادات مركز جديد إلى الدالة الواحدة المستخدمة. استبدل <FUNCTIONAPP_NAME> و<APP_KEY> لك.

  • اسم المركز: simplechat
  • قالب URL: https://< FUNCTIONAPP_NAME.azurewebsites.net/runtime/webhooks/webpubsub?code>=<APP_KEY>
  • نمط حدث المستخدم: *
  • أحداث النظام: - (لا حاجة للتكوين في هذا النموذج)

 لقطة شاشة لإعداد معالج الحدث.

تكوين لتمكين مصادقة العميل

انتقل إلى مدخل Microsoft Azure -> ابحث عن مورد Function App ->Authentication. انقر فوق Add identity provider . قم بتعيين إعدادات مصادقة App Service إلى السماح بالوصول غير المصادق عليه، بحيث يمكن زيارة صفحة فهرس العميل من قبل مستخدمين مجهولين قبل إعادة التوجيه للمصادقة. ثم احفظ.

هنا نختار Microsoft كموفر تعريف، والذي يستخدم x-ms-client-principal-name كما هو الحال userId في الدالة negotiate . بالإضافة إلى ذلك، يمكنك تكوين موفري الهوية الآخرين باتباع الارتباطات، ولا تنس تحديث القيمة في negotiate الدالة userId وفقا لذلك.

جرب التطبيق

يمكنك الآن اختبار صفحتك من تطبيق وظيفتك: https://<FUNCTIONAPP_NAME>.azurewebsites.net/api/index. راجع اللقطة.

  1. انقر فوق login to auth yourself.
  2. اكتب رسالة في مربع الإدخال للدردشة.

في دالة الرسالة، نقوم ببث رسالة المتصل إلى جميع العملاء ونعيد المتصل بالرسالة [SYSTEM] ack. لذلك يمكننا أن نعرف في عينة لقطة الدردشة، أول أربع رسائل من العميل الحالي وآخر رسالتين من عميل آخر.

 لقطة شاشة لنموذج من الدردشة.

تنظيف الموارد

إذا كنت لن تستمر في استخدام هذا التطبيق، فاحذف جميع الموارد التي تم إنشاؤها بواسطة هذا المستند من خلال الخطوات التالية حتى لا تتحمل أي رسوم:

  1. من القائمة اليسرى في مدخل Azure، حدد مجموعات الموارد ثم حدد مجموعة الموارد التي أنشأتها. يمكنك استخدام مربع البحث للعثور على resourceGroup باسمها بدلاً من ذلك.

  2. في النافذة التي تفتح، حدد resourceGroup، ثم حدد Delete resource group.

  3. في النافذة الجديدة، اكتب اسم resourceGroup المراد حذفها، ثم حدد Delete.

الخطوات التالية

في هذا التشغيل السريع، تعلمت كيفية تشغيل تطبيق دردشة بلا خادم. الآن، يمكنك البدء في إنشاء تطبيقك.