البروتوكول الفرعي ل Azure Web PubSub Reliable JSON WebSocket

يتيح البروتوكول الفرعي JSON WebSocket التبادل json.reliable.webpubsub.azure.v1الموثوق به للغاية لرسائل النشر/الاشتراك مباشرة بين العملاء من خلال الخدمة دون رحلة ذهابا وإيابا إلى الخادم المصدر.

يصف هذا المستند البروتوكول json.reliable.webpubsub.azure.v1الفرعي .

عند انخفاض اتصالات عميل WebSocket بسبب مشكلات متقطعة في الشبكة، يمكن فقدان الرسائل. في نظام pub/sub، يتم فصل الناشرين عن المشتركين وقد لا يكتشفون انقطاع الاتصال أو فقدان الرسائل للمشتركين.

للتغلب على مشكلات الشبكة المتقطعة والحفاظ على تسليم الرسائل الموثوق به، يمكنك استخدام البروتوكول الفرعي Azure WebPubSub json.reliable.webpubsub.azure.v1 لإنشاء عميل PubSub WebSocket موثوق به.

يمكن لعميل PubSub WebSocket الموثوق به:

  • استرداد اتصال من مشكلات شبكة متقطعة.
  • استرداد من فقدان الرسالة.
  • الانضمام إلى مجموعة باستخدام طلبات الانضمام.
  • اترك مجموعة باستخدام طلبات المغادرة.
  • نشر الرسائل مباشرة إلى مجموعة باستخدام طلبات النشر.
  • يبث الرسائل مباشرة إلى مجموعة باستخدام طلبات البث.
  • توجيه الرسائل مباشرة إلى معالجات الأحداث الأولية باستخدام طلبات الأحداث.

على سبيل المثال، يمكنك إنشاء عميل PubSub WebSocket موثوق به باستخدام التعليمات البرمجية JavaScript التالية:

var pubsub = new WebSocket('wss://test.webpubsub.azure.com/client/hubs/hub1', 'json.reliable.webpubsub.azure.v1');

راجع كيفية إنشاء عملاء موثوقين لتنفيذ إعادة الاتصال وموثوقية الرسائل لعملاء الناشر والمشترك.

عندما يستخدم العميل هذا البروتوكول الفرعي، يجب أن تحتوي كل من إطارات البيانات الصادرة والواردة على حمولات JSON.

الأذونات

يمكن لعميل PubSub WebSocket النشر فقط للعملاء الآخرين عندما يكون مصرحا به. roles يحدد المعين للعميل الأذونات الممنوحة للعميل:

الدور الإذن
غير محدد يمكن للعميل إرسال طلبات الحدث.
webpubsub.joinLeaveGroup يمكن للعميل الانضمام إلى/مغادرة أي مجموعة.
webpubsub.sendToGroup يمكن للعميل نشر الرسائل إلى أي مجموعة.
webpubsub.joinLeaveGroup.<group> يمكن للعميل الانضمام إلى المجموعة <group>أو مغادرتها .
webpubsub.sendToGroup.<group> يمكن للعميل نشر رسائل إلى المجموعة <group>.
webpubsub.joinLeaveGroups.<pattern> يمكن للعميل الانضمام/المغادرة لأي مجموعة يتطابق <pattern> اسمها (انظر أنماط أدوار المجموعات البرية).
webpubsub.sendToGroups.<pattern> يمكن للعميل نشر رسائل لأي مجموعة يتطابق <pattern> اسمها (انظر أنماط أدوار المجموعات البرية).

يمكن للخادم منح أذونات العميل أو إبطالها ديناميكيا من خلال واجهات برمجة تطبيقات REST أو SDKs للخادم.

ملحوظة

أدوار حرف البدل (على سبيل المثال، webpubsub.sendToGroups.<pattern>) غير مدعومة في واجهات برمجة تطبيقات REST أو SDKs للخادم أثناء وقت التشغيل حتى الآن.

الطلبات

الانضمام إلى المجموعات

التنسيق:

{
    "type": "joinGroup",
    "group": "<group_name>",
    "ackId" : 1
}
  • ackId هوية كل طلب ويجب أن يكون فريدا. ترسل الخدمة رسالة استجابة ack لإعلام نتيجة العملية بالطلب. للحصول على التفاصيل، راجع استجابة AckId وAck

مغادرة المجموعات

التنسيق:

{
    "type": "leaveGroup",
    "group": "<group_name>",
    "ackId" : 1
}
  • ackId هوية كل طلب ويجب أن يكون فريدا. ترسل الخدمة رسالة استجابة ack لإعلام نتيجة العملية بالطلب. للحصول على التفاصيل، راجع استجابة AckId وAck

انشر الرسائل

التنسيق:

{
    "type": "sendToGroup",
    "group": "<group_name>",
    "ackId" : 1,
    "noEcho": true|false,
    "dataType" : "json|text|binary",
    "data": {}, // data can be string or valid json token depending on the dataType 
}
  • ackId هوية كل طلب ويجب أن يكون فريدا. ترسل الخدمة رسالة استجابة ack لإعلام نتيجة العملية بالطلب. للحصول على التفاصيل، راجع استجابة AckId وAck
  • noEcho اختياري. إذا تم تعيينها إلى true، فلن يتم تكرار هذه الرسالة مرة أخرى إلى نفس الاتصال. إذا لم يتم تعيينها، تكون القيمة الافتراضية خاطئة.
  • dataType يمكن تعيين إلى jsonأو textأو binary:
    • json: data يمكن أن يكون أي نوع يدعمه JSON وسيتم نشره كما هو؛ إذا dataType لم يتم تحديده، تعيينه افتراضيا إلى json.
    • text: data يجب أن تكون بتنسيق سلسلة، وسيتم نشر بيانات السلسلة؛
    • binary: data يجب أن تكون بتنسيق base64، وسيتم نشر البيانات الثنائية؛

الحالة 1: نشر البيانات النصية:

{
    "type": "sendToGroup",
    "group": "<group_name>",
    "dataType" : "text",
    "data": "text data",
    "ackId": 1
}
  • يتلقى عملاء <group_name> البروتوكول الفرعي:
{
    "type": "message",
    "from": "group",
    "group": "<group_name>",
    "dataType" : "text",
    "data" : "text data"
}
  • يتلقى عملاء WebSocket البسيطون في <group_name> السلسلة text data.

الحالة 2: نشر بيانات JSON:

{
    "type": "sendToGroup",
    "group": "<group_name>",
    "dataType" : "json",
    "data": {
        "hello": "world"
    }
}
  • يتلقى عملاء <group_name> البروتوكول الفرعي:
{
    "type": "message",
    "from": "group",
    "group": "<group_name>",
    "dataType" : "json",
    "data" : {
        "hello": "world"
    }
}
  • يتلقى عملاء WebSocket البسيطون في <group_name> السلسلة {"hello": "world"}المتسلسلة .

الحالة 3: نشر البيانات الثنائية:

{
    "type": "sendToGroup",
    "group": "<group_name>",
    "dataType" : "binary",
    "data": "<base64_binary>",
    "ackId": 1
}
  • يتلقى عملاء <group_name> البروتوكول الفرعي:
{
    "type": "message",
    "from": "group",
    "group": "<group_name>",
    "dataType" : "binary",
    "data" : "<base64_binary>", 
}
  • يتلقى عملاء WebSocket البسيطون البيانات <group_name> الثنائيةفي الإطار الثنائي.

ابدأ بث الرسائل

لبدء بث جماعي، أرسل طلبا sendToGroup مع stream الخاصية. طلب بدء التدفق لا يحتوي dataعلى ، dataType، أو ackId.

التنسيق:

{
    "type": "sendToGroup",
    "group": "<group_name>",
    "noEcho": true|false,
    "stream": {
        "streamId": "<stream_id>",
        "idleTimeoutMs": 300000
    }
}
  • stream.streamId هو معرف التيار المنطقي. يجب أن تكون سلسلة غير فارغة ويجب أن تكون فريدة بين التدفقات النشطة على نفس اتصال العميل. ينصح بإنشاء مكتبات العملاء لتوليد قيمة فريدة عالميا، مثل واجهة المستخدم الرسومية (GUID) أو UUID.
  • stream.idleTimeoutMs اختياري. إذا تم تحديده، يجب أن يكون أكبر من 0. إذا تم حذفها، يكون الإعداد الافتراضي للخدمة هو 300000 ميلي ثانية. القيمة هي انتهاء فترة الخمول، وليست مدة البث الكاملة. إرسال بيانات التدفق، أو إرسال تدفق يبقى حيا، أو أنهى التدفق قبل انتهاء هذا الوقت الذي يحتاج فيه التطبيق إلى إبقاء التدفق مفتوحا.
  • noEcho اختياري. إذا تم ضبطها على true، فإن رسائل البث لا تعاد إلى نفس الاتصال. إذا لم يتم تعيينها، تكون القيمة الافتراضية خاطئة.

عند قبول التدفق، يتلقى العميل استجابة ACK للتدفق مع expectedSequenceId تعيين على 1.

إرسال بيانات البث

لإرسال بيانات التدفق، أرسل طلبا streamData باستخدام streamId، streamSequenceId، dataType، و data.

التنسيق:

{
    "type": "streamData",
    "streamId": "<stream_id>",
    "streamSequenceId": 1,
    "dataType" : "json|text|binary",
    "data": {}
}
  • streamId يحدد تدفقا نشطا على نفس اتصال العميل.
  • streamSequenceId هو رقم موجب ل uint64. أول جزء بيانات في التدفق يستخدم 1، وكل جزء بيانات تالي لنفس streamId العدد يزداد بالضبط 1بمقدار .
  • dataType يمكن تعيينها على json، text، أو binary، بنفس قواعد ترميز البيانات مثل نشر الرسائل.

للحفاظ على نشاط البث دون تسليم البيانات للمشتركين، أرسل طلبا streamData باستخدام و streamId.type

{
    "type": "streamData",
    "streamId": "<stream_id>"
}

رسائل نهاية البث

لإنهاء البث، أرسل طلبا streamEnd .

التنسيق:

{
    "type": "streamEnd",
    "streamId": "<stream_id>"
}

لإنهاء التدفق بخطأ معرف من قبل التطبيق، قم بتضمين الخاصية الاختيارية error .

{
    "type": "streamEnd",
    "streamId": "<stream_id>",
    "error": {
        "message": "<error_detail>",
        "userErrorCode": "<application_error_code>"
    }
}
  • error.message هي رسالة خطأ اختيارية يمكن للبشر.
  • error.userErrorCode هو رمز خطأ اختياري معرف من قبل التطبيق.

عند إغلاق البث، يتلقى الناشر استجابة إغلاق البث.

إرسال أحداث مخصصة

التنسيق:

{
    "type": "event",
    "event": "<event_name>",
    "ackId": 1,
    "dataType" : "json|text|binary",
    "data": {}, // data can be string or valid json token depending on the dataType 
}
  • ackId هوية كل طلب ويجب أن يكون فريدا. ترسل الخدمة رسالة استجابة ack لإعلام نتيجة العملية بالطلب. للحصول على التفاصيل، راجع استجابة AckId وAck

dataType يمكن أن يكون واحدا من textأو binaryأو json:

  • json: يمكن أن تكون البيانات أي نوع يدعمه json وسيتم نشره على أنه ما هو عليه؛ الإعداد الافتراضي هو json.
  • text: البيانات بتنسيق سلسلة، وسيتم نشر بيانات السلسلة؛
  • binary: البيانات بتنسيق base64، وسيتم نشر البيانات الثنائية؛

الحالة 1: إرسال حدث مع بيانات نصية:

{
    "type": "event",
    "event": "<event_name>",
    "ackId": 1,
    "dataType" : "text",
    "data": "text data", 
}

يتلقى معالج الأحداث المصدر بيانات مشابهة ل:

POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.com
Content-Type: text/plain
Content-Length: nnnn
ce-specversion: 1.0
ce-type: azure.webpubsub.user.<event_name>
ce-source: /client/{connectionId}
ce-id: {eventId}
ce-time: 2021-01-01T00:00:00Z
ce-signature: sha256={connection-id-hash-primary},sha256={connection-id-hash-secondary}
ce-userId: {userId}
ce-connectionId: {connectionId}
ce-hub: {hub_name}
ce-eventName: <event_name>

text data

Content-Type لطلب CLOUDEvents HTTP هو text/plain عندما dataType يكون .text

الحالة 2: إرسال حدث مع بيانات JSON:

{
    "type": "event",
    "event": "<event_name>",
    "ackId": 1,
    "dataType" : "json",
    "data": {
        "hello": "world"
    }, 
}

يتلقى معالج الأحداث المصدر بيانات مشابهة ل:

POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.com
Content-Type: application/json
Content-Length: nnnn
ce-specversion: 1.0
ce-type: azure.webpubsub.user.<event_name>
ce-source: /client/{connectionId}
ce-id: {eventId}
ce-time: 2021-01-01T00:00:00Z
ce-signature: sha256={connection-id-hash-primary},sha256={connection-id-hash-secondary}
ce-userId: {userId}
ce-connectionId: {connectionId}
ce-hub: {hub_name}
ce-eventName: <event_name>

{
    "hello": "world"
}

Content-Type لطلب CloudEvents HTTP هو عندما application/json يكون dataTypejson

الحالة 3: إرسال حدث مع بيانات ثنائية:

{
    "type": "event",
    "event": "<event_name>",
    "ackId": 1,
    "dataType" : "binary",
    "data": "base64_binary", 
}

يتلقى معالج الأحداث المصدر بيانات مشابهة ل:

POST /upstream HTTP/1.1
Host: xxxxxx
WebHook-Request-Origin: xxx.webpubsub.azure.com
Content-Type: application/octet-stream
Content-Length: nnnn
ce-specversion: 1.0
ce-type: azure.webpubsub.user.<event_name>
ce-source: /client/{connectionId}
ce-id: {eventId}
ce-time: 2021-01-01T00:00:00Z
ce-signature: sha256={connection-id-hash-primary},sha256={connection-id-hash-secondary}
ce-userId: {userId}
ce-connectionId: {connectionId}
ce-hub: {hub_name}
ce-eventName: <event_name>

binary

Content-Type لطلب CLOUDEvents HTTP هو application/octet-stream عندما dataType يكون .binary يمكن أن يكون text إطار WebSocket تنسيقا لإطارات الرسائل النصية أو ثنائيات UTF8 المشفرة لإطارات binary الرسائل.

تقوم خدمة Web PubSub برفض العميل إذا لم تتطابق الرسالة مع التنسيق الموضح.

أداة اختبار الاتصال

التنسيق:

{
    "type": "ping",
}

يمكن للعميل إرسال رسالة ping إلى الخدمة لتمكين خدمة Web PubSub للكشف عن فعالية العميل.

سلسلة Ack

التنسيق:

{
    "type": "sequenceAck",
    "sequenceId": "<sequenceId>",
}

يجب أن يرسل عميل PubSub WebSocket الموثوق به رسالة تسلسل ack بمجرد تلقيه رسالة من الخدمة. لمزيد من المعلومات، راجع كيفية إنشاء عملاء موثوقين

  • sequenceId هو رقم uint64 تزايدي من الرسالة المستلمة.

الاستجابات

يمكن أن تكون الرسائل التي يستقبلها العميل عدة أنواع: ack، message، system، pong، streamAckstreamNack، و streamClosed. تحتوي الرسائل ذات النوع message على sequenceId خاصية . يجب على العميل إرسال Sequence Ack إلى الخدمة بمجرد تلقيه رسالة.

استجابة Ack

عندما يحتوي الطلب على ackId، سترجع الخدمة استجابة ack لهذا الطلب. يجب أن يعالج تنفيذ العميل آلية ack هذه، بما في ذلك انتظار استجابة ack باستخدام asyncawait عملية، وأن يكون له معالج مهلة عند عدم تلقي استجابة ack خلال فترة معينة.

التنسيق:

{
    "type": "ack",
    "ackId": 1, // The ack id for the request to ack
    "success": false, // true or false
    "error": {
        "name": "Forbidden|InternalServerError|Duplicate",
        "message": "<error_detail>"
    }
}

يجب أن يتحقق تنفيذ العميل دائما مما إذا كان success هو true أو false الأول. فقط عندما success يقرأ false العميل من error.

استجابة الرسالة

يمكن للعملاء تلقي الرسائل المنشورة من مجموعة انضم إليها العميل أو من الخادم، والتي، تعمل في دور إدارة الخادم، ترسل رسائل إلى عملاء أو مستخدمين محددين.

  1. رسالة الاستجابة من مجموعة:

    {
        "sequenceId": 1,
        "type": "message",
        "from": "group",
        "group": "<group_name>",
        "dataType": "json|text|binary",
        "data" : {} // The data format is based on the dataType
        "fromUserId": "abc"
    }
    
  2. رسالة الاستجابة من الخادم:

    {
        "sequenceId": 1,
        "type": "message",
        "from": "server",
        "dataType": "json|text|binary",
        "data" : {} // The data format is based on the dataType
    }
    

الحالة 1: إرسال البيانات مرحبًا بالعالم إلى الاتصال من خلال واجهة برمجة تطبيقات REST باستخدام Content-Type=text/plain

  • يتلقى عميل WebSocket البسيط إطار WebSocket نصيا مع البيانات: مرحبًا بالعالم؛

  • يتلقى عميل PubSub WebSocket الرسالة في JSON:

    {
        "sequenceId": 1,
        "type": "message",
        "from": "server",
        "dataType" : "text",
        "data": "Hello World", 
    }
    

الحالة 2: إرسال البيانات { "Hello" : "World"} إلى الاتصال من خلال واجهة برمجة تطبيقات REST باستخدام Content-Type=application/json

  • يتلقى عميل WebSocket البسيط إطار WebSocket نصيا مع بيانات سلسلة: { "Hello" : "World"}؛

  • يتلقى عميل PubSub WebSocket الرسالة في JSON:

    {
        "sequenceId": 1,
        "type": "message",
        "from": "server",
        "dataType" : "json",
        "data": {
            "Hello": "World"
        }
    }
    

إذا كانت واجهة برمجة تطبيقات REST ترسل سلسلة مرحبًا بالعالم باستخدام application/json نوع المحتوى، يتلقى عميل WebSocket البسيط سلسلة "مرحبًا بالعالم" JSON مغلفة في ".

الحالة 3: إرسال البيانات الثنائية إلى الاتصال من خلال واجهة برمجة تطبيقات REST باستخدام Content-Type=application/octet-stream

  • يتلقى عميل WebSocket بسيط إطار WebSocket ثنائي مع البيانات الثنائية.

  • يتلقى عميل PubSub WebSocket الرسالة في JSON:

    {
        "sequenceId": 1,
        "type": "message",
        "from": "server",
        "dataType" : "binary",
        "data": "<base64_binary>"
    }
    

استجابة الرسائل المتدفقة

عندما تنتمي رسالة إلى تدفق، تحتوي رسالة المجموعة على stream خاصية. الموثوق sequenceId يبقى معتمدا على نطاق الاتصال ويختلف عن stream.streamSequenceId.

{
    "sequenceId": 1,
    "type": "message",
    "from": "group",
    "group": "<group_name>",
    "dataType": "json|text|binary",
    "data": {},
    "fromUserId": "abc",
    "stream": {
        "streamId": "<stream_id>",
        "streamSequenceId": 1,
        "endOfStream": true,
        "error": {
            "name": "IdleTimeout|InternalServerError|Forbidden|Cancelled|UserError",
            "message": "<error_detail>",
            "userErrorCode": "<application_error_code>"
        }
    }
}
  • stream.streamId هو معرف التدفق المنطقي.
  • stream.streamSequenceId هو رقم التسلسل للرسالة في التدفق.
  • stream.endOfStream اختياري. عند تعيينها على true، تكون الرسالة هي الرسالة النهائية للتدفق.
  • stream.error اختياري ويظهر فقط عندما ينتهي التدفق بخطأ. userErrorCode موجود فقط ل UserError.

استجابة البث

ترسل الخدمة ردا streamAck للتأكيد على بيانات التدفق المقبولة والإبلاغ عن معرف تسلسل التدفق التالي الذي تتوقعه.

التنسيق:

{
    "type": "streamAck",
    "streamId": "<stream_id>",
    "expectedSequenceId": 2
}

استجابة التيار السريع

ترسل الخدمة ردا streamNack على خطأ في التدفق القابل للاسترجاع.

التنسيق:

{
    "type": "streamNack",
    "streamId": "<stream_id>",
    "expectedSequenceId": 2,
    "name": "InvalidSequenceId|TransientError",
    "message": "<error_detail>"
}

استجابة مغلقة للتيار

ترسل الخدمة ردا streamClosed عندما يغلق بث الناشر.

التنسيق:

{
    "type": "streamClosed",
    "streamId": "<stream_id>",
    "error": {
        "name": "StreamNotFound|Forbidden|BadRequest|InternalServerError|IdleTimeout",
        "message": "<error_detail>"
    }
}

يتم حذف الخاصية error عندما يغلق التيار بشكل طبيعي.

استجابة النظام

يمكن لخدمة Web PubSub إرجاع الاستجابات المتعلقة بالنظام إلى العميل.

استجابة بونغ

ترسل خدمة Web PubSub رسالة pong إلى العميل عندما تتلقى رسالة ping من العميل.

التنسيق:

{
    "type": "pong",
}

Connected

الاستجابة لطلب اتصال العميل:

{
    "type": "system",
    "event": "connected",
    "userId": "user1",
    "connectionId": "abcdefghijklmnop",
    "reconnectionToken": "<token>"
}

connectionId reconnectionToken وتستخدم لإعادة الاتصال. قم بإجراء طلب اتصال باستخدام uri لإعادة الاتصال:

wss://<service-endpoint>/client/hubs/<hub>?awps_connection_id=<connectionId>&awps_reconnection_token=<reconnectionToken>

العثور على مزيد من التفاصيل في استرداد الاتصال

غير متصل

الاستجابة عندما يغلق الخادم الاتصال أو عندما تقوم الخدمة برفض اتصال العميل:

{
    "type": "system",
    "event": "disconnected",
    "message": "reason"
}

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

استخدم هذه الموارد لبدء إنشاء التطبيق الخاص بك: