كيفية بناء نظام الدردشة الحقيقي لبدء التشغيل الخاص بك

أرى كل يوم مشاركة في مدونة حول كيفية إنشاء نظام دردشة باستخدام WebSockets أو كيفية استخدام سحر Firebase لبناء نظام مهيب ، على الرغم من أننا لنكن صادقين: بناء نظام دردشة قابل للتخصيص من REAL هو قصة مختلفة تمامًا.

الآن ، دعنا نفكر في حالة استخدام معقدة:
لدينا منتج يتكون من جزأين: 1) تطبيق جوال يقوم المستخدمون النهائيون بتثبيته و 2) لوحة تحكم ويب. يستخدم المسؤولون لوحة المعلومات لاستهداف مجموعة معينة من الجمهور وإرسال رسائل إليهم. سيتلقى الجمهور المحدد الرسائل على تطبيقات الجوال الخاصة بهم.

ضع في اعتبارك أننا بحاجة إلى تقديم حلول لحالات الاستخدام التالية:

  • 1-1 دردشة بين اثنين من المستخدمين
  • دردشات المجموعة بين المستخدمين
  • إرسال رسائل مجمعة (نشير إليها باسم "حملات") من لوحة القيادة إلى المستخدمين
  • إرسال رسائل فردية إلى مستخدم معين من لوحة القيادة

تنقسم رسائل الحملة إلى الفئات التالية:

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

والسؤال الآن هو كيفية تنفيذ هذا؟

محاليل

حل واحد هو إعادة اختراع العجلة. لقد سمعنا جميعا من Firebase وعظمته. يمكننا استخدام قاعدة بيانات Firebase في الوقت الفعلي لبناء بنية الدردشة الخاصة بنا.

دعونا نرى كيف يبدو التنفيذ:

في النهاية سوف ينتهي بك المطاف مع شجرة Firebase التالية:

  • campaignMessageQueue
  • campaignQueue
  • campaignStatus
  • chatMessages
  • chatReadReceipts
  • دردشات
  • chatTypingIndicators
  • اشعارات البريد الالكتروني
  • قائمة انتظار الرسائل
  • userChats
  • userPushTokens
  • nonChatSMSQueue
  • campaignMessageQueue

مخيفة! أليس كذلك؟
هل يعمل؟ نعم.
هل مقياس؟ نوع من.
هل من السهل التعامل معها؟ قطعا لا!
لدعم هذا الوحش ، تحتاج إلى تكريس الكثير من الوقت والطاقة.
يقوم هذا الحل بإعادة اختراع كل جانب من جوانب نظام الدردشة بما في ذلك: قراءة الإيصالات ، مؤشرات الكتابة ، الإخطارات ، وحالة حالة الدردشات.
يجب أن يكون لديك مجموعة مختلفة من العاملين في Node والتي تقرأ من قوائم انتظار مختلفة في Firebase Tree.

فيما يلي وصف لكل عامل:

campaignWorker

العامل يعمل على حملةQueue.
يتلقى العامل وظائف من واجهة مستخدم لوحة معلومات الويب ، ويقوم بجلب قائمة التوزيع ، ويقوم بإنشاء محادثات جديدة مع المستخدمين ، ثم يضع رسالة الحملة فيها. تتحمل أيضًا مسؤولية إنشاء وظائف في campaignMessageQueue.

messageWorker

العامل يعمل على messageQueue.
يتعامل مع جميع مهام الإعلام للرسائل العادية / غير المتعلقة بالحملات.

campaignMessageWorker

العامل يعمل على campaignMessageQueue. الوظيفة تشبه messageWorker تمامًا ، فهي تعمل فقط في قائمة انتظار مختلفة.

nonChatSMSWorker

العامل يعمل على nonChatSMSQueue.
يتعامل مع إرسال رسائل SMS فقط التي لا تنشئ رسالة داخل دردشة حقيقية.

campaignMessageWorker

العامل يعمل على campaignMessageQueue.
يتعامل مع إرسال رسائل غير حملة كبيرة للوحة القيادة.

يبدو وكأنه الكثير من العمل ، لا؟ إن تطبيق والحفاظ على كل هذا الرمز ليس هو المشكلة الوحيدة ، وأحيانًا يسد عمال Node وأحيانًا أخرى يتعطلون ويحتاجون إلى إعادة التشغيل.
تكلفة الصيانة باهظة جدًا ، مما يجعلك تبحث عن بديل قريبًا. سيكون هدفك هو القضاء على الاعتماد على Firebase كقاعدة بيانات الدردشة الخاصة بك ، والسؤال هو كيف يكون ذلك ممكنا؟

عندها يأتي Twilio للعب. وهي معروفة في الغالب بواجهة برمجة تطبيقات SMS الخاصة بهم ولكنها توفر أيضًا واجهة برمجة تطبيقات للدردشة.

Twilio's Programmable Chat API

تعد "البرمجة القابلة للبرمجة" أحد منتجات الدردشة المستندة إلى مجموعة النظراء والتي توفر عددًا من SDKs للعميل وواجهة برمجة تطبيقات REST للاستخدام في دمج إمكانيات الدردشة في التطبيقات ومواقع الويب. تم تصميمه على غرار بروتوكول الرسائل والتواجد القابل للتوسيع (XMPP) ويدور حول مفهوم مثيلات الخدمة. خدمات الدردشة هي حيث يتم بث جميع القنوات والرسائل والمستخدمين والموارد الأخرى داخل نشر الدردشة.

  • يمكن أن يكون لكل مثيل خدمة العديد من القنوات.
  • يمكن أن تحتوي كل قناة على العديد من الأعضاء.
  • يمكن لكل قناة لديها العديد من الرسائل.

مثيلات الخدمة عبارة عن صوامع معزولة ولا توجد وسيلة لاثنين من مثيلات الخدمة المختلفة للاتصال ببعضهما البعض. لإرسال رسالة بين كيانين ؛ أولاً ، يجب أن يكون هناك قناة موجودة بينهما. ثم يجب إضافة الكيانات كأعضاء في القناة. سيتم نشر كل رسالة تم إسقاطها في القناة على الأعضاء. باستخدام وحدات SDK للعميل (متوفرة للويب و iOS و Android) ، يمكننا استرداد قائمة القنوات المشتركة التي يكون المستخدم عضوًا فيها (أو تمت دعوته إليه) بمجرد تسجيل دخول المستخدم إلى العميل.
هذا النموذج مرن للغاية.

الآن دعنا نعود إلى المشكلة الأصلية التي حللناها مسبقًا عبر Firebase. سنحاول تنفيذه في Twilio:

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

باستخدام واجهة برمجة تطبيقات Chat القابلة للبرمجة ، يمكننا التخلص تمامًا من الاعتماد على Firebase. سنشرع في إزالة عمال العقدة المذكورة أعلاه وسنقوم بتبسيط هيكل مشروعنا.

الآن دعنا نتحدث عن Twilio’s Chat REST API. يمكننا استخدامه لتنفيذ جميع حالات الاستخدام التي تمت مناقشتها سابقًا. يتم استخدام واجهة برمجة التطبيقات عن طريق الواجهة الخلفية لدينا وهي مخصصة لاستخدام النظام. يمكن استخدام واجهة برمجة التطبيقات لتنظيم استخدام "الدردشة القابلة للبرمجة" ، ويمكنك إضافة أعضاء ، وإرسال رسائل عشوائية ، وتغيير دور المستخدمين ، وما إلى ذلك.

فيما يلي تفاصيل موجزة عن كيفية تنفيذ كل سيناريو:

  • دردشة من مستخدم إلى مستخدم (جوال): كلما احتاج المستخدم إلى بدء محادثة مع مستخدم آخر ، يرسل عميل الجوّال طلبًا إلى نقطة النهاية المتوفرة في الواجهة الخلفية. ستحاول الواجهة الخلفية لدينا العثور على قناة تحمل الاسم الفريد لـ [user1.uuid، user2.uuid] .sort.join (‘: ') في مثيل الخدمة الافتراضية. إذا لم يتم العثور على قناة بهذا الفريد ، فسيقوم REST Client بإنشاء قناة جديدة بهذا الاسم ويضيف كلا المستخدمين كأعضاء فيها. ستعيد نقطة النهاية معرف القناة المناسب إلى عميل الهاتف المحمول في حمولة العودة. من هناك ، يستطيع عميل الجوال إرسال رسائل على هذه القناة. باستخدام Twilio’s REST API ، نتأكد من أننا لا ننشئ قنوات مكررة بين مستخدمين ونحافظ على تاريخ المحادثات. في المرة القادمة ، يريد المستخدم إرسال رسالة إلى مستخدم زميل ، سيتم استخدام نفس القناة.
def create_1_to_1_chat (u1، u2)
 unique_name = [u1.uuid، u2.uuid] .sort.join (‘:’)
 name = User.where (uuid: [u1.uuid، u2.uuid] .sort) .map (&: name) .join (‘-‘)
 c = add_channel (unique_name ، الاسم ، channel_type:: public)
 c = update_attribute (c ، "الموضوع" ، الاسم)
 add_member (c، u1)
 add_member (c، u2)
 c.sid
النهاية

2. دردشة من المستخدم إلى لوحة القيادة (الجوال): تشبه العملية حالة الاستخدام السابقة. الفرق الأكبر هو أن الخلفية ستحاول إيجاد أو تهيئة القناة في مثيل خدمة لوحة القيادة (وليس مثيل الخدمة الافتراضي):

def create_user_to_dashboard_chat (u)
 c = add_channel (u.uuid، "# {@ dashboard.name"> @ dashboard.name "> @ dashboard.name"> u.name} - # {@ dashboard.name} # {u.uuid} ")
 c = update_attribute (c ، 'topic' ، @ dashboard.name)
 c = update_attribute (c ، 'dashboard_uuid' ، @ dashboard.uuid)
 add_member (c ، u)
 add_member (c ،dashboard ، role_sid:: channel_admin)
 الدقة = TwilioChannel.load_channel (dashboard ، ج)
 الدقة
النهاية

3. لوحة القيادة لمحادثة المستخدم (الويب): في بعض الأحيان ، نود إرسال رسالة إلى مستخدم فردي. المنطق المستخدم هنا هو نفسه بالضبط الذي استخدمناه للدردشة "من لوحة تحكم المستخدم".

4. لوحة القيادة إلى المستخدمين (تُعرف أيضًا باسم الحملات): كما ذُكر سابقًا ، نحتاج إلى دعم نوعين مختلفين من اتصالات لوحة القيادة للمستخدمين.
حالة الاستخدام الأولى هي عندما تحتاج لوحة القيادة إلى إنشاء دردشة جماعية مع بعض المستخدمين فيها. سيتم إرسال الطلب من لوحة القيادة إلى الواجهة الخلفية مع قائمة بارامترات البحث التي يجب استخدامها لتحديد الجمهور. سوف يتلقى Backend الطلب ويقوم بإنشاء قناة جديدة بشكل غير متزامن ويضيف الجمهور المختار كأعضاء في القناة.
حالة الاستخدام الثانية هي عندما تحتاج لوحة القيادة إلى فتح قنوات فردية بينها وبين مستخدمي المحمول. عادةً ما يستخدم المسؤول نوع الاتصال هذا لطلب استجابة من الجمهور. سيتم إرسال الطلب من لوحة القيادة إلى الواجهة الخلفية مع قائمة بارامترات البحث التي يجب استخدامها لتحديد هويات الجمهور. يتلقى Backend الطلب ويقوم بإنشاء قناة مختلفة لكل مستخدم ويضيف ذلك المستخدم كعضو فيه. نحن نستخدم Sidekiq لمعالجة خلفية فعالة.

Webhooks الأحداث

تتيح لك عمليات الاسترجاعات الخاصة بحدث المحادثة القابلة للبرمجة مراقبة أحداث معينة واعتراضها في خدمة الواجهة الخلفية. فئتا الأحداث هما "Pre-Event" (متزامن) و "Post-Event" (غير متزامن). عندما يتم تحديد رد اتصال ، سيقوم Twilio بتقديم طلب HTTP إلى عنوان URL الخاص بـ webhook المعين. يحتوي هذا الطلب على جميع البيانات المتغيرة ذات الصلة.
استخدمنا عمليات الاسترجاعات بعد الحدث لأغراض التحليل وأيضًا لإعادة إضافة لوحة معلومات مختلفة كأعضاء في القنوات. وفقًا للمستندات ، تعتبر "ويب ما بعد الحدث" من الويب "تُخطر فقط" وتوفر المعلومات بعد اكتمال الإجراء. على عكس ما قبل الحدث ، فإن هذه لا تمنع عمليات الاسترجاعات لأنها معلوماتية.
اعتمدنا بشكل خاص على معالجات الأحداث onMessageSent و onChannelided.

محددات

برمجة تطبيقات Chat API القابلة للبرمجة لا تزال شابة والعمل جار. بينما كنا نعمل على إنشاء تجربة دردشة جديدة تمامًا ، واجهنا القيود التالية:

  • في حالة الحملات (الرسائل المجمّعة التي تبدأ من لوحة المعلومات) ، لا نضيف مبدئيًا مدراء لوحة المعلومات كعضو في القناة. أحد القيود على Twilio Chat API الحالي هو أن الكيان يمكن أن يكون عضوًا في ما يصل إلى 1000 قناة. وفقًا لـ Twilio ، يعد هذا حدًا ضعيفًا يتيح لهم إمكانية التوسع بشكل أفضل ، لكن من ناحية أخرى ، إنه نوع من القيود. وبالتالي ، فإننا نضيف لوحة القيادة فقط كعضو إذا كانت هناك رسالة واردة من مستخدمي المحمول. يعني هذا القيد أيضًا أننا نحتاج إلى إزالة لوحة المعلومات من القناة ، عند انتهاء المشرف من معالجتها (مفهوم الفتح مقابل القنوات المغلقة المذكور سابقًا).
  • حاليًا ، يمكننا تعيين سمات مخصصة على القنوات والرسائل ؛ على الرغم من عدم وجود طريقة للاستعلام عن طريقهم. هذا هو الحد السوبر وفي رأيي هو أهم ميزة تفتقر.
  • يمكن أن تضم كل قناة ما يصل إلى 1000 عضو فقط. لكي نكون منصفين ، أعتقد أن أي دردشة جماعية مع أكثر من 20 عضوًا فيها هي مكان للفوضى المطلقة ، لذلك لا أعتبر ذلك قيدًا حقيقيًا.

خاتمة

بشكل عام ، أعتقد أن Twilio يوفر للمستخدمين تجربة أكثر سلاسة في بناء نظام دردشة مقارنة مع Firebase.
على المدى الطويل ، سيكون نظام الدردشة المدعوم من بروتوكول Pub-Sub هو الفائز الحقيقي من حيث قابلية التوسع والصيانة.
دعنا نعرف فقط أن هناك حلولًا مختلفة لبناء نظام الدردشة. عندما تحتاج إلى تحديد الحل الذي يناسبك بشكل أفضل ، حاول إعداد قائمة من إيجابيات وسلبيات. إعادة اختراع العجلة ليست دائمًا فكرة سيئة ، ولكن عليك أيضًا التفكير في الموارد المتاحة لك. كونك شركة ناشئة ، من الضروري التحرك بسرعة. يمكنك الآن التحرك بسرعة دون التضحية بالجودة من خلال استخدام الأداة الصحيحة فقط.

مصادر:
https://www.twilio.com/docs/api/chat/
https://firebase.google.com/