WebSockets مقابل SSE مقابل التصويت الطويل — اختر النمط الحقيقي للوقت قبل أن ينهار تطبيق الدردشة الخاص بك

تحديث في

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

ويب سوكيتز مقابل سى إس إس مقابل بوليينغ - اختر النمط الحقيقي للوقت قبل أن ينهار تطبيق محادثتك  1
إعلان · حذف؟

لقد أنشأت لوحة تحكم. يحتاج المستخدمون إلى تحديثات بيانات حية. اتجهت إلى WebSockets - لأن هذا ما يفعله الجميع. الآن تُحلل مشاكل الجلسات المتماسكة في الساعة 2 صباحًا لأن موزع الحمل يُرسل العملاء إلى القواعد الخاطئة. البيانات التي تُرسل؟ رقم واحد في صيغة JSON كل 10 ثوانٍ. كان استخدام WebSockets مفرطًا.

هذا يحدث باستمرار. يُعامل المطورون WebSockets كالحل الافتراضي للحلول الحقيقية الزمنية، بينما كان من الممكن أن يُطرح الحل باستخدام SSE أو التصويت الطويل بشكل أسرع، ويسهل التوسع، ويُقلل التكلفة التشغيلية. إليك كيفية اختيار الحل المناسب.

جدول القرار

قبل التعمق، إليك المقارنة الكاملة. استخدم هذا للإجابة، ثم قراءة الأقسام التالية إذا كنت بحاجة إلى التبرير.

ميزةالتصويت الطويلأحداث مُرسلة من الخادمWebSockets
البروتوكولHTTP/1.1HTTP/1.1+ (مُقسّم)الاتصالات عبر الوسائط (مُحدثة عبر HTTP)
اتجاهالعميل يُسحب فقطالخادم إلى العميل فقطمُتوازٍ كامل
دعم المتصفحجميع المتصفحاتجميع المتصفحات الحديثة (بدون IE11)جميع المعاصر
إعادة الاتصال تلقائيًايجب تدوينه يدويًا - تكتب الحلقةمُدمج عبر EventSourceيدوي أو عبر مكتبة
مُناسب للـ CDN أو المُستضيفنعمبشكل عام (ملاحظة التوقيت)لا
التوسع الأفقيمُستقل، بسيطمُستقل، بسيطيتطلب جلسات متماسكة أو نظام مُوزع للإشعارات
تعقيد البنية التحتيةمنخفض - بسيط HTTPمنخفض - بسيط HTTPعالي - اتصالات مُستندة إلى الحالة، تكوين موزع الحمل، نظام مُوزع
التأخيرمدة التحقق + الاتجاه العكسيمُقارب للواقعمُقارب للواقع
الواجهات، الخدمات الصغيرة، التحقق عبر الحدودتحديثات منخفضة التكرار، بنية تحتية قديمةلوحات تحكم، مصادر معلومات، إشعاراتالدردشة، تحرير متوازي، الألعاب

التصويت الطويل: العامل غير المُلهم

التصويت الطويل ليس "قديمًا" أو "خاطئًا" - بل هو مجرد HTTP. يُرسل العميل طلبًا، ويُحتفظ به من قبل الخادم حتى يُقال شيء (أو يُنفَذ وقت انتظار)، ثم يحصل العميل على الاستجابة ويُرسل طلبًا فوريًا للطلب التالي. يُكرر.

كان موجودًا قبل أن تُنشأ WebSockets، ويُستخدم في ملايين التطبيقات في البيئة الإنتاجية. السبب: إنه مجرد HTTP. كل مُستضيف عكسي، مُوزع الحمل، مُحَوّل مُتَوَسِّط، ونظام المراقبة يفهمه دون تكوين. لا حاجة لجلسات متماسكة، ولا حاجة لتصحيح البروتوكول، ولا حاجة لبنية تحتية مُخصصة للـ WS.

العيوب حقيقية. كل "تحديث" هو دورة طلب HTTP كاملة - عناوين الرسائل، التكلفة المترتبة على TCP (إلا إذا كان HTTP/2)، تراكم الطلبات في الجانب الخادم. تحت الضغط العالي، يصبح هذا مكلفًا على الخادم. والحد الأدنى للتأخير هو وقت الاتصال العكسي لكل تحقق، وليس تأخير الحدث نفسه. إذا كان التحقق كل 5 ثوانٍ وحدث في الثانية 1، فإن المستخدم ينتظر 4 ثوانٍ إضافية.

متى تُستخدم؟: أنظمة قديمة حيث لا يُعتبر إضافة طبقة اتصال مستمر مُبررًا. تحديثات منخفضة التكرار (أقل من دقيقة واحدة). بيئات حيث تُقتل SSE من قبل مُستضيفات مُفرطة. التحقق من التحديثات التي يتحكم بها العميل - مراقبة المهام، نتائج المهام المُؤجلة.

أحداث مُرسلة من الخادم: ما يُنسى من الجميع

SSE هي معيار (مُعيار HTML المُتحرك) يسمح للخادم بدفع سلسلة من أحداث النص عبر اتصال HTTP طويل. يُدير المتصفح إعادة الاتصال تلقائيًا. لا تحتاج إلى دورة إعادة الاتصال - يُعيد EventSource الواجهة الافتراضية الاتصال مع رقم الأحداث الأخير الذي رآه، لذا يمكنك استئناف السير بعد انقطاع الشبكة.

صيغة الاتصال بسيطة جدًا:

HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache

id: 1
event: price-update
data: {"symbol":"BTC","price":67420}

id: 2
event: price-update
data: {"symbol":"ETH","price":3521}

كل حدث نصي بسيط مع مُدخلات اختيارية id, event, dataو، و retry مُفصّلة بخطوط فارغة. يمكنك اختبار نقاط الاتصال باستخدام cURL - استخدم منشئ أوامر cURL لإنشاء الطلب مع الرأس المناسب (text/event-stream) وتدفق الاستجابة.

من جانب العميل:

const es = new EventSource('/api/events');

es.addEventListener('price-update', (e) => {
  const payload = JSON.parse(e.data);
  updateDashboard(payload);
});

es.onerror = () => {
  // EventSource will auto-reconnect. You don't need to do anything here
  // unless you want to log or update UI state.
};

يوجد حدود واقعية لـ SSE: هو فقط من الخادم إلى العميل. لا يمكن للعميل إرسال بيانات عكسية عبر نفس الاتصال - أي إجراءات مُبادر من جانب العميل تُرسل عبر طلبات HTTP عادية. في معظم حالات لوحة التحكم، مصادر المعلومات، والسجلات، هذا يكفي. لم تكن تستخدم الاتجاه من العميل إلى الخادم.

النقطة الأخرى: بعض المُستضيفات تُخزن جزء الاستجابة وتحاول تمريرها بعد إغلاق الاتصال، مما يُوقف التدفق تمامًا. يحتاج NGINX إلى proxy_buffering off. يُخزن مُستضيفات سحاب مثل Cloudflare في الوضع المجاني. إذا كان لديك مُستضيف يُخزن في المنتصف ولا يمكنك تكوينه، فلن يعمل SSE وسوف تحتاج إلى WebSockets أو التصويت الطويل.

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

WebSockets: متى يُعتبر مُبررًا حقًا

تُعطي WebSockets اتصالًا متماسكًا مُزدوج الاتجاه عبر اتصال واحد على طبقة TCP. بعد تبادل الاتصال عبر HTTP، يمكن للطرفين إرسال رسائل مُفرّقة في أي وقت. التأخير هو أدنى مستوى ممكن على الشبكة - لا يوجد طلب جديد لكل رسالة، ولا عناوين رأس لكل إطار.

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

لا شيء من هذا غير ممكن، لكنه يمثل عملًا حقيقيًا. عند بدء مشروع وتحليل الخيارات، "هو مجرد HTTP" مقابل "اتصالات مُستندة إلى الحالة باستخدام طبقة Redis مُوزعة" هو فرق كبير في التعقيد.

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

عندما تُستخدم: تطبيقات الدردشة (مُتوازية من الطرفين - كل رسالة مُبادر من العميل). تحرير متوازي (مثل Figma، Google Docs - عدة عمال يكتبون على حالة مشتركة). ألعاب متعددة اللاعبين (مُتوازية عالية التردد، منخفضة التأخير في التحديث). مراكز تداول (تأخير أقل من 100 مللي ثانية على سجلات الأوامر). ببساطة: أي شيء يتطلب من العميل إرسال بيانات بانتظام، وليس فقط استقبالها.

النقطة المهمة في التوسع التي لا يُذكرها حتى يصبح الأمر متأخرًا

التصويت الطويل وSSE مُستقلان على مستوى HTTP. يمكن أن يُصل كل طلب إلى أي خادم. قصة التوسع بسيطة وذات ميزة: أضف مزيدًا من الخوادم، وتم. تُحتفظ حالة الاتصال فقط لفترة مفتوحة للاتصال، ويُمكن أن يُوجه الموزع بحرية.

WebSockets مُستندة إلى الحالة. اتصال العميل A يُحتفظ على الخادم 1. عندما ترغب في إرسال رسالة إلى العميل A من الخادم 2 (لأن الحدث بدأ هناك)، يجب على الخادم 2 أن يعلم عن هذا الاتصال. الحل القياسي هو نظام مُوزع للإشعارات - مثل Redis pub/sub، أو خدمات مُدارة مثل Pusher أو Ably التي تُخفف كل هذا. إما أن تُبني هذه الطبقة بنفسك أو أن تدفع لها.

يُدفع Pusher $49/شهر لـ 500 اتصال متوازي. Ably مُكلف بشكل مماثل. إذا كان "الوظيفة الحقيقية للوقت الحقيقي" هو ترقية شعار عند تفضيل متابعة محتواك، فإن هذا يُمثل تكلفة كبيرة لـ SSE يمكنك تشغيلها مجانًا مع واجهة الخدمة الحالية.

تغييرات HTTP/2 تغيّر حساب التصويت الطويل

التصويت الطويل الكلاسيكي هو طلب واحد لكل اتصال لكل توقف مُستند. تحت HTTP/2، يُمكن تعدد الاتجاهات عبر اتصال TCP واحد. التكلفة المترتبة أقل. هذا ليس سببًا لاختيار التصويت الطويل على SSE، لكنه يعني أن الانتقاد "الإجهاد من الاتصالات HTTP" ينطبق أقل في 2024 مقارنة بالعام 2012 عندما كُتبت هذه المقارنات.

إذا كنت على HTTP/2 من الطرف إلى الطرف (من العميل إلى الخادم، بدون مُستضيف مُتدخل يُقلل)، فإن التصويت الطويل يتوسع بشكل أفضل من معظم المراجع القديمة.

مُرشد سريعة للقرار

إذا كان استخدامك يناسب أحد هذه الحالات بوضوح، فتوقف عن القراءة هنا:

  • تكرار التحديثات < 1/دقيقة، بنية تحتية قديمة، مفاهيم تحقق بسيطة: التصويت الطويل. لا تُضيّعه.
  • الخادم يُرسل البيانات، العميل يُستقبل بشكل أساسي، بنية تحتية HTTP معيارية: SSE. هذا يغطي 80% من "الوظائف الحقيقية للوقت الحقيقي".
  • العميل يُرسل بيانات بانتظام، التأخير < 100 مللي ثانية مهم، مُتوازٍ حقًا: WebSockets. الآن أصبح التكلفة مبررة.
  • أنت تستخدم تدفق الذكاء الاصطناعي (مثل OpenAI، Anthropic، إلخ): SSE - هذا بالضبط ما يستخدمه بروتوكولات التدفق الخاصة بهم.
  • مُتعدّد اللاعبين أو محرر متوازي: WebSockets، أو إطار مُخصص (مثل Liveblocks، PartyKit، إلخ).

الإجابة الافتراضية ليست WebSockets. هي SSE - حتى أن تملك سببًا محددًا يجعلها غير كافية. عدد التطبيقات الإنتاجية التي تحتاج حقًا إلى تدفق حقيقي مزدوج الاتجاه أقل بكثير من عدد التطبيقات التي استخدم استخدمت WebSockets. هذا الفجوة هي ديناميكية في التصميم التي تُنفَّذ في الساعة 2 صباحًا أمام تكوين موزع الحمل.

هل تريد حذف الإعلانات؟ تخلص من الإعلانات اليوم

تثبيت ملحقاتنا

أضف أدوات IO إلى متصفحك المفضل للوصول الفوري والبحث بشكل أسرع

أضف لـ إضافة كروم أضف لـ امتداد الحافة أضف لـ إضافة فايرفوكس أضف لـ ملحق الأوبرا

وصلت لوحة النتائج!

لوحة النتائج هي طريقة ممتعة لتتبع ألعابك، يتم تخزين جميع البيانات في متصفحك. المزيد من الميزات قريبا!

إعلان · حذف؟
إعلان · حذف؟
إعلان · حذف؟

ركن الأخبار مع أبرز التقنيات

شارك

ساعدنا على الاستمرار في تقديم أدوات مجانية قيمة

اشتري لي قهوة
إعلان · حذف؟