دليل النشر

Centrifugo على VPS: خادم زمن حقيقي مستضاف ذاتيًا

انشر على VPS Cloud ←

دليل عملي

Centrifugo على VPS: خادم زمن حقيقي مستضاف ذاتيًا

الاستضافة الذاتية7 دقائق للقراءةعدد الخطوات: 3

عرض إشعار لحظة دفع الطلب، أو تشغيل دردشة، أو تحديث لوحة متابعة دون إعادة تحميل الصفحة: كل ذلك يتطلب اتصالًا مفتوحًا باستمرار بين الخادم والمتصفح. تؤدي خدمات مثل Pusher أو Ably هذا العمل جيدًا، لكنها تفوتر كل اتصال وكل رسالة، وتمر بياناتك عبرها. ‏Centrifugo خادم مراسلة فورية مفتوح المصدر (رخصة Apache-2.0) مكتوب بلغة Go، يؤدي العمل نفسه على خادمك الافتراضي. يثبّته هذا الدليل باستخدام Docker Compose، ويضعه خلف nginx عبر HTTPS، ثم يشرح كيف تنشر من الخادم الخلفي وتربط متصفحًا برمز JWT.

المحتويات· كيف يعمل Centrifugo1/13
  1. 01كيف يعمل Centrifugo
  2. 02ما يقدّمه Centrifugo
  3. 03Centrifugo مقارنة بخدمة مستضافة
  4. 04المتطلبات
  5. 05تثبيت Centrifugo باستخدام Docker Compose
  6. 06لا تنشر المنفذ 8000 على العنوان العام أبدًا
  7. 07وضع Centrifugo خلف nginx
  8. 08النشر من الخادم الخلفي
  9. 09توقيع رموز الاتصال
  10. 10ما المسموح به للعميل
  11. 11ربط متصفح
  12. 12لوحة الإدارة
  13. 13التوسّع والتحديثات

كيف يعمل Centrifugo

يقع Centrifugo بين تطبيقك ومستخدميه. لا يُبقي خادمك الخلفي — Laravel أو Django أو Express أو Rails أو غيرها — أي اتصال مفتوحًا: يوقّع رمزًا لكل مستخدم، ثم ينشر الرسائل بطلب HTTP بسيط. أما Centrifugo فيحافظ على اتصالات WebSocket للمتصفحات وتطبيقات الجوال، ويوصل كل رسالة إلى مشتركي القناة المعنية.

لهذا الفصل فائدة ملموسة: يبقى تطبيقك بلا حالة وسهل النشر، ويتسع جزء الزمن الحقيقي في ملف Go تنفيذي واحد يستهلك بضع عشرات من الميغابايت من الذاكرة في وضع الخمول.

ما يقدّمه Centrifugo

  • اتصالات WebSocket — مع حزم رسمية للعملاء بلغات JavaScript وDart/Flutter وSwift وJava/Android وGo وPython.
  • واجهة نشر — طلب HTTP POST مع الترويسة X-API-Key، من أي لغة.
  • رموز JWT — يقرر خادمك الخلفي من يتصل وبأي قنوات، ويتحقق Centrifugo من التوقيع.
  • اشتراكات من جهة الخادم — تنتقل قائمة قنوات المستخدم داخل رمزه.
  • لوحة إدارة — حالة العقدة والعملاء المتصلون وأوامر الواجهة من المتصفح.
  • إعدادات افتراضية حذرة — لا اتصال مجهول، ولا نشر من المتصفح دون إذن صريح.

Centrifugo مقارنة بخدمة مستضافة

مرّر الجدول أفقيًا

Centrifugo على VPSPusher وAbly
الفوترةسعر الخادم دون حد للرسائلحسب الاتصالات والرسائل
مسار البياناتعلى خادمكعبر المزوّد
بروتوكول العميلWebSocket وحزم رسميةWebSocket وحزم مملوكة
المصادقةJWT يوقّعه خادمك الخلفيتوقيع خاص بالخدمة
التشغيلعلى عاتقكيتولاه المزوّد

المتطلبات

خادم افتراضي بنظام Ubuntu 24.04 بذاكرة 1 غيغابايت ومساحة 10 غيغابايت، مع Docker وإضافة Compose، ونطاق فرعي يشير إلى الخادم، مثل rt.example.com. ‏HTTPS ليس اختياريًا: لا يستطيع موقع يُقدَّم عبر HTTPS فتح اتصالات غير wss://، ويجب ألا يمر مفتاح الواجهة بنص واضح أبدًا.

تثبيت Centrifugo باستخدام Docker Compose

  1. توليد الأسرار

    أنشئ مجلد التطبيق وملف .env يحمل أربعة أسرار مختلفة: كلمة مرور اللوحة، والمفتاح الذي يوقّع جلساتها، ومفتاح واجهة الخادم، ومفتاح HMAC لرموز العملاء.

    mkdir -p /opt/centrifugo && cd /opt/centrifugo
    {
      echo "ADMIN_PASSWORD=$(openssl rand -hex 12)"
      echo "SECRET_KEY=$(openssl rand -hex 24)"
      echo "ENCRYPTION_KEY=$(openssl rand -hex 16)"
      echo "ENCRYPTION_KEY_HEX64=$(openssl rand -hex 32)"
    } > .env
    chmod 600 .env
  2. كتابة ملف docker-compose.yml

    يُنشر المنفذ على الواجهة المحلية فقط: لا يصل إليه إلا nginx. استبدل https://app.example.com بعنوان موقعك.

    services:
      centrifugo:
        image: centrifugo/centrifugo:v6.10.2
        restart: unless-stopped
        command: ["centrifugo"]
        ports:
          - "127.0.0.1:8000:8000"
        environment:
          CENTRIFUGO_ADMIN_ENABLED: "true"
          CENTRIFUGO_ADMIN_PASSWORD: "${ADMIN_PASSWORD}"
          CENTRIFUGO_ADMIN_SECRET: "${SECRET_KEY}"
          CENTRIFUGO_HTTP_API_KEY: "${ENCRYPTION_KEY}"
          CENTRIFUGO_CLIENT_TOKEN_HMAC_SECRET_KEY: "${ENCRYPTION_KEY_HEX64}"
          CENTRIFUGO_CLIENT_ALLOWED_ORIGINS: "https://app.example.com"
          CENTRIFUGO_HEALTH_ENABLED: "true"
        ulimits:
          nofile:
            soft: 65535
            hard: 65535
  3. التشغيل والتحقق

    شغّل الحاوية واستعلم نقطة الصحة؛ يجب أن تجيب بـ {}.

    docker compose up -d
    curl -fsS http://127.0.0.1:8000/health

لا تنشر المنفذ 8000 على العنوان العام أبدًا

يخدم المنفذ نفسه اتصالات العملاء وواجهة الخادم ولوحة الإدارة. أبقه على 127.0.0.1 ومرّ دائمًا عبر الوكيل العكسي HTTPS. ولا تضع أبدًا ENCRYPTION_KEY أو ENCRYPTION_KEY_HEX64 في شيفرة تُرسل إلى المتصفح: الأول يسمح بالنشر على أي قناة، والثاني بصنع رموز لأي مستخدم.

وضع Centrifugo خلف nginx

يبدأ اتصال WebSocket بطلب HTTP يطلب تبديل البروتوكول. يجب أن يمرر nginx هذا الطلب، وألا يقطع اتصالًا يبقى صامتًا بضع دقائق. في كتلة server الخاصة بنطاقك الفرعي، مع شهادة Let's Encrypt:

location / {
    proxy_pass http://127.0.0.1:8000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_read_timeout 3600s;
}

بعد nginx -t وإعادة التحميل، يعرض https://rt.example.com شاشة الدخول إلى اللوحة.

النشر من الخادم الخلفي

النشر هو إرسال كائن JSON إلى قناة. تصلح لذلك أي لغة قادرة على إرسال طلب HTTP:

curl -X POST https://rt.example.com/api/publish \
  -H "X-API-Key: $ENCRYPTION_KEY" \
  -d '{"channel": "commandes", "data": {"id": 1042, "statut": "payee"}}'

يؤكد الرد {"result":{}} قبول الرسالة. دون الترويسة X-API-Key، أو بمفتاح خاطئ، يجيب Centrifugo بـ 401.

توقيع رموز الاتصال

لا يتصل المتصفح إلا برمز JWT يوقّعه خادمك الخلفي بـ ENCRYPTION_KEY_HEX64. تحمل المطالبة sub معرّف المستخدم، وexp تاريخ الانتهاء، وchannels قائمة القنوات التي يُشترك فيها تلقائيًا. مثال بلغة Python:

import time, jwt  # pip install pyjwt

def centrifugo_token(user_id: str) -> str:
    claims = {"sub": user_id, "exp": int(time.time()) + 3600, "channels": ["commandes"]}
    return jwt.encode(claims, ENCRYPTION_KEY_HEX64, algorithm="HS256")

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

ما المسموح به للعميل

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

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

وأخيرًا، اجعل مدة صلاحية الرموز قصيرة، ساعة مثلًا. بدل تمرير رمز ثابت، دع الحزمة تطلب رمزًا جديدًا من تطبيقك عند انتهاء صلاحيته:

const client = new Centrifuge('wss://rt.example.com/connection/websocket', {
  getToken: async () => {
    const res = await fetch('/realtime/token', { credentials: 'include' });
    return (await res.json()).token;
  },
});

المسار /realtime/token خاص بتطبيقك، ويتحقق من جلسة المستخدم قبل توقيع أي شيء.

ربط متصفح

من جهة العميل، تفتح الحزمة الرسمية centrifuge ‏(npm) الاتصال وتسلّم الرسائل:

import { Centrifuge } from 'centrifuge';

const client = new Centrifuge('wss://rt.example.com/connection/websocket', {
  token: tokenFromYourBackend,
});
client.on('publication', (ctx) => console.log(ctx.channel, ctx.data));
client.connect();

إذا فشل الاتصال، فابدأ بالسجلات (docker compose logs centrifugo). تعني الرسالة «request Origin is not authorized» أن أصل موقعك غائب عن CENTRIFUGO_CLIENT_ALLOWED_ORIGINS، وتشير «invalid token» إلى رمز موقّع بشكل خاطئ أو منتهي الصلاحية.

لوحة الإدارة

افتح https://rt.example.com وأدخل ADMIN_PASSWORD: لا تطلب اللوحة اسم مستخدم. تعرض إصدار العقدة وعدد العملاء والمستخدمين المتصلين، وتتيح إرسال أوامر الواجهة — نشر رسالة تجريبية أو سرد القنوات النشطة — دون كتابة شيفرة. إنها أسرع وسيلة للتحقق من خروج الرسالة قبل البحث عن الخلل في المتصفح.

التوسّع والتحديثات

يستخدم هذا الدليل محرك الذاكرة: عقدة واحدة دون أي اعتماد. يناسب معظم التطبيقات، ويتحمل خادم متواضع عددًا كبيرًا من الاتصالات المتزامنة، ولذلك رُفع حد الملفات المفتوحة في docker-compose.yml. وحين لا تكفي عقدة واحدة، يستطيع Centrifugo توزيع الحمل على عدة عقد مرتبطة عبر Redis. للتحديث، غيّر وسم الصورة بعد قراءة ملاحظات الإصدار، ثم شغّل docker compose pull && docker compose up -d؛ تعود الاتصالات تلقائيًا لأن حزم العملاء تعيد الاتصال من تلقاء نفسها.

خادم الزمن الحقيقي على خادمك

يكفي خادم ServOrbit بنظام Ubuntu 24.04 وذاكرة 1 غيغابايت لتشغيل Centrifugo. تثبيت بنقرة واحدة من المتجر، وHTTPS وWebSocket على نطاقك أو على النطاق الفرعي المجاني للخادم، مع توليد كلمة المرور والمفاتيح لك.

بحاجة إلى مساعدة؟

تصفّح مركز المساعدة والأسئلة الشائعة، أو تواصل مع فريقنا — معاودة اتصال أو WhatsApp أو بريد إلكتروني. الدعم بـالعربية والفرنسية والإنجليزية.

راسلنا على WhatsAppيُفتح في علامة تبويب جديدة