البرنامج التعليمي: نشر الرسائل والاشتراك فيها بين عملاء WebSocket باستخدام بروتوكول فرعي
مقالة
في إنشاء برنامج تعليمي لتطبيق الدردشة، تعلمت كيفية استخدام واجهات برمجة تطبيقات WebSocket لإرسال البيانات وتلقيها باستخدام Azure Web PubSub. يمكنك أن ترى أنه لا توجد حاجة إلى بروتوكول عندما يتصل العميل بالخدمة. على سبيل المثال، يمكنك إرسال أي نوع من البيانات باستخدام WebSocket.send()، ويتلقى الخادمها تماما كما هي. عملية واجهات برمجة تطبيقات WebSocket سهلة الاستخدام، ولكن الوظيفة محدودة. على سبيل المثال، لا يمكنك تحديد اسم الحدث عند إرسال الحدث إلى الخادم، أو نشر رسالة إلى عملاء آخرين بدلا من إرسالها إلى الخادم. في هذا البرنامج التعليمي، ستتعلم كيفية استخدام البروتوكول الفرعي لتوسيع وظائف العميل.
في هذا البرنامج التعليمي، تتعلم كيفية:
إنشاء مثيل خدمة Web PubSub
إنشاء عنوان URL الكامل لتأسيس اتصال WebSocket
نشر الرسائل والاشتراك فيها بين عملاء WebSocket باستخدام بروتوكول فرعي
إذا كنت تفضل تشغيل أوامر مرجع CLI محلياً قم بتثبيت CLI Azure. إذا كنت تعمل على نظام تشغيل Windows أو macOS، ففكر في تشغيل Azure CLI في حاوية Docker. لمزيد من المعلومات، راجع كيفية تشغيل Azure CLI في حاوية Docker.
إذا كنت تستخدم تثبيت محلي، يُرجى تسجيل الدخول إلى Azure CLI مستخدمًا أمر az login. لإنهاء عملية المصادقة، اتبع الخطوات المعروضة في جهازك. للحصول على خيارات أخرى لتسجيل دخول، راجع تسجيل الدخول باستخدام Azure CLI.
عندما يُطلب منك، قم بتثبيت ملحق Azure CLI عند الاستخدام لأول مرة. لمزيد من المعلومات بشأن الامتدادات، راجع استخدام امتدادات مع Azure CLI.
يُرجى تشغيل إصدار az للوصول إلى الإصدار والمكتبات التابعة التي تم تثبيتها. للتحديث لآخر إصدار، يُرجى تشغيل تحديث az.
يتطلب هذا الإعداد الإصدار 2.22.0 أو أعلى من Azure CLI. إذا كنت تستخدم Azure Cloud Shell، يتم تثبيت أحدث إصدار بالفعل.
إنشاء مثيل Azure Web PubSub
إنشاء مجموعة موارد
وتُعد مجموعة الموارد عبارة عن حاوية منطقية يتم فيها توزيع موارد Azure وإدارتها. استخدم الأمر az group create لإنشاء مجموعة موارد باسم myResourceGroup في eastus الموقع.
az group create --name myResourceGroup --location EastUS
إنشاء مثيل Web PubSub
قم بتشغيل ملحق az add لتثبيت أو ترقية ملحق webpubsub إلى الإصدار الحالي.
az extension add --upgrade --name webpubsub
استخدم الأمر Azure CLI az webpubsub create لإنشاء Web PubSub في مجموعة الموارد التي قمت بإنشائها. ينشئ الأمر التالي مورد Web PubSub مجاني ضمن مجموعة الموارد myResourceGroup في EastUS:
هام
يجب أن يكون لكل مورد Web PubSub ويب اسمًا فريدًا. استبدل <your-unique-resource-name> باسم Web PubSub في الأمثلة التالية.
يظهر إخراج هذا الأمر خصائص المورد المنشأ حديثًا. دوّن اثنتين من الخصائص المذكورة أدناه:
اسم المورد: الاسم الذي قدمته للمعلمة --name أعلاه.
اسم المضيف: في المثال، اسم المضيف هو <your-unique-resource-name>.webpubsub.azure.com/.
في هذه المرحلة، حساب Azure هو الوحيد المصرح به لتنفيذ أي عمليات على هذا المورد الجديد.
احصل على ConnectionString لاستخدامها في المستقبل
هام
سلسلة اتصال تتضمن معلومات التخويل المطلوبة لتطبيقك للوصول إلى خدمة Azure Web PubSub. مفتاح الوصول داخل سلسلة الاتصال يشبه كلمة مرور الجذر للخدمة الخاصة بك. في بيئات الإنتاج، كن حذرا دائما لحماية مفاتيح الوصول الخاصة بك. استخدم Azure Key Vault لإدارة المفاتيح وتدويرها بأمان. تجنب توزيع مفاتيح الوصول إلى مستخدمين آخرين، أو ترميزها ترميزًا ثابتًا، أو حفظها في أي مكان في نص عادي يمكن للآخرين الوصول إليه. قم بتدوير المفاتيح الخاصة بك إذا كنت تعتقد أنها قد تعرضت للخطر.
استخدم الأمر Azure CLI az webpubsub key للحصول على الاتصال ionString للخدمة. <your-unique-resource-name> استبدل العنصر النائب باسم مثيل Azure Web PubSub.
az webpubsub key show --resource-group myResourceGroup --name <your-unique-resource-name> --query primaryConnectionString --output tsv
انسخ سلسلة الاتصال لاستخدامها لاحقا.
انسخ الاتصال ionString التي تم إحضارها واستخدمها لاحقا في هذا البرنامج التعليمي كقيمة .<connection_string>
يمكن للعميل بدء اتصال WebSocket باستخدام البروتوكول الفرعي المحدد. تدعم خدمة Azure Web PubSub بروتوكول فرعي يسمى json.webpubsub.azure.v1 لتمكين العملاء من النشر/الاشتراك مباشرة من خلال خدمة Web PubSub بدلا من رحلة ذهابا وإيابا إلى الخادم المصدر. تحقق من البروتوكول الفرعي JSON WebSocket المدعوم من Azure Web PubSub للحصول على تفاصيل حول البروتوكول الفرعي.
في حال كنت تستخدم أسماء بروتوكول أخرى، سيتم تجاهلها من قبل الخدمة وتمريرها إلى الخادم في معالج أحداث الاتصال، حتى تتمكن من إنشاء البروتوكولات الخاصة بك.
الآن دعونا ننشئ تطبيق ويب باستخدام json.webpubsub.azure.v1 البروتوكول الفرعي.
نستخدم أداة Secret Manager ل .NET Core لتعيين سلسلة الاتصال. شغل الأمر أدناه، واستبدل <connection_string> بالأمر الذي تم جلبه في الخطوة السابقة، وافتح http://localhost:5000/index.html في المستعرض:
dotnet user-secrets init
dotnet user-secrets set Azure:WebPubSub:ConnectionString "<connection-string>"
dotnet run
الآن قم بتشغيل الأمر أدناه، واستبدل <connection-string>ب الاتصال ionString التي تم جلبها في الخطوة السابقة، وافتح http://localhost:8080 في المستعرض:
export WebPubSubConnectionString="<connection-string>"
node server
الآن قم بتشغيل الأمر أدناه، واستبدل <connection-string>ب الاتصال ionString التي تم جلبها في الخطوة السابقة، وافتح http://localhost:8080 في المستعرض:
python server.py "<connection-string>"
الآن قم بتشغيل الأمر أدناه، واستبدل <connection-string>ب الاتصال ionString التي تم جلبها في الخطوة السابقة، وافتح http://localhost:8080 في المستعرض:
إذا كنت تستخدم Chrome، فيمكنك الضغط على F12 أو النقر بزر الماوس الأيمن فوق ->Inspect ->Developer Tools، وتحديد علامة التبويب Network . قم بتحميل صفحة الويب، ويمكنك رؤية اتصال WebSocket تم تأسيسه. حدد لفحص اتصال WebSocket، يمكنك رؤية رسالة الحدث أدناه connected يتم تلقيها في العميل. يمكنك أن ترى أنه يمكنك الحصول على الذي connectionId تم إنشاؤه لهذا العميل.
يمكنك أن ترى أنه بمساعدة البروتوكول الفرعي، يمكنك الحصول على بعض بيانات التعريف للاتصال عندما يكون connectedالاتصال .
يتلقى العميل الآن رسالة JSON بدلا من نص عادي. تحتوي رسالة JSON على مزيد من المعلومات مثل نوع الرسالة ومصدرها. لذلك يمكنك استخدام هذه المعلومات لإجراء المزيد من المعالجة للرسالة (على سبيل المثال، عرض الرسالة بأسلوب مختلف إذا كانت من مصدر مختلف)، والتي يمكنك العثور عليها في الأقسام اللاحقة.
نشر رسائل من العميل
في البرنامج التعليمي إنشاء تطبيق دردشة، عندما يرسل العميل رسالة من خلال اتصال WebSocket بخدمة Web PubSub، تقوم الخدمة بتشغيل حدث مستخدم على جانب الخادم الخاص بك. باستخدام البروتوكول الفرعي، يتمتع العميل بمزيد من الوظائف عن طريق إرسال رسالة JSON. على سبيل المثال، يمكنك نشر الرسائل مباشرة من العميل من خلال خدمة Web PubSub إلى عملاء آخرين.
وهذا مفيد إذا كنت تريد دفق كمية كبيرة من البيانات إلى عملاء آخرين في الوقت الحقيقي. دعونا نستخدم هذه الميزة لإنشاء تطبيق تدفق سجل، والتي يمكن أن تيار سجلات وحدة التحكم إلى المتصفح في الوقت الحقيقي.
using System;
using System.Net.Http;
using System.Net.WebSockets;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace stream
{
class Program
{
private static readonly HttpClient http = new HttpClient();
static async Task Main(string[] args)
{
// Get client url from remote
var stream = await http.GetStreamAsync("http://localhost:5000/negotiate");
var url = (await JsonSerializer.DeserializeAsync<ClientToken>(stream)).url;
var client = new ClientWebSocket();
client.Options.AddSubProtocol("json.webpubsub.azure.v1");
await client.ConnectAsync(new Uri(url), default);
Console.WriteLine("Connected.");
var streaming = Console.ReadLine();
while (streaming != null)
{
if (!string.IsNullOrEmpty(streaming))
{
var message = JsonSerializer.Serialize(new
{
type = "sendToGroup",
group = "stream",
data = streaming + Environment.NewLine,
});
Console.WriteLine("Sending " + message);
await client.SendAsync(Encoding.UTF8.GetBytes(message), WebSocketMessageType.Text, true, default);
}
streaming = Console.ReadLine();
}
await client.CloseAsync(WebSocketCloseStatus.NormalClosure, null, default);
}
private sealed class ClientToken
{
public string url { get; set; }
}
}
}
stream.js إنشاء بالمحتوى التالي.
const WebSocket = require('ws');
const fetch = (...args) => import('node-fetch').then(({default: fetch}) => fetch(...args));
async function main() {
let res = await fetch(`http://localhost:8080/negotiate`);
let data = await res.json();
let ws = new WebSocket(data.url, 'json.webpubsub.azure.v1');
let ackId = 0;
ws.on('open', () => {
process.stdin.on('data', data => {
ws.send(JSON.stringify({
type: 'sendToGroup',
group: 'stream',
ackId: ++ackId,
dataType: 'text',
data: data.toString()
}));
});
});
ws.on('message', data => console.log("Received: %s", data));
process.stdin.on('close', () => ws.close());
}
main();
تنشئ التعليمات البرمجية أعلاه اتصال WebSocket بالخدمة ثم كلما تلقت بعض البيانات التي تستخدمها ws.send() لنشر البيانات. للنشر للآخرين، تحتاج فقط إلى تعيين type إلى sendToGroup وتحديد اسم مجموعة في الرسالة.
mkdir stream
cd stream
# Create venv
python -m venv env
# Active venv
source ./env/bin/activate
pip install websockets
stream.py إنشاء بالمحتوى التالي.
import asyncio
import sys
import threading
import time
import websockets
import requests
import json
async def connect(url):
async with websockets.connect(url, subprotocols=['json.webpubsub.azure.v1']) as ws:
print('connected')
id = 1
while True:
data = input()
payload = {
'type': 'sendToGroup',
'group': 'stream',
'dataType': 'text',
'data': str(data + '\n'),
'ackId': id
}
id = id + 1
await ws.send(json.dumps(payload))
await ws.recv()
if __name__ == '__main__':
res = requests.get('http://localhost:8080/negotiate').json()
try:
asyncio.get_event_loop().run_until_complete(connect(res['url']))
except KeyboardInterrupt:
pass
تنشئ التعليمات البرمجية أعلاه اتصال WebSocket بالخدمة ثم كلما تلقت بعض البيانات التي تستخدمها ws.send() لنشر البيانات. للنشر للآخرين، تحتاج فقط إلى تعيين type إلى sendToGroup وتحديد اسم مجموعة في الرسالة.
دعونا نستخدم محطة طرفية أخرى ونعود إلى المجلد الجذر لإنشاء تطبيق logstream-streaming وحدة تحكم دفق والتبديل إلى مجلد دفق السجل:
يمكنك أن ترى أن هناك مفهوما جديدا "مجموعة" هنا. المجموعة مفهوم منطقي في لوحة وصل حيث يمكنك نشر رسالة إلى مجموعة من الاتصالات. في لوحة الوصل، يمكنك الحصول على مجموعات متعددة، ويمكن لعميل واحد الاشتراك في مجموعات متعددة في نفس الوقت. عند استخدام بروتوكول فرعي، يمكنك النشر إلى مجموعة فقط بدلاً من البث إلى المحور بأكمله. للحصول على تفاصيل حول المصطلحات، تحقق من المفاهيم الأساسية.
نظرا لأننا نستخدم المجموعة هنا، نحتاج أيضا إلى تحديث صفحة index.html الويب للانضمام إلى المجموعة عند إنشاء اتصال WebSocket داخل ws.onopen رد الاتصال.