Интеграция Centrifugo: real-time сообщения на сайте

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Интеграция Centrifugo: real-time сообщения на сайте
Средний
~3-5 дней
Часто задаваемые вопросы

Наши компетенции:

Этапы разработки

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1362
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1253
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    958
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1190
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    932
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Разработка веб-сайта для компании ФИКСПЕР
    949

Real-time доставка без задержек

Представьте: вы запустили интернет-магазин, и клиенты жалуются, что уведомления о статусе заказа приходят с опозданием на 5–10 минут. Или админы не видят новые сообщения в чате поддержки, пока не перезагрузят страницу. Классический polling на AJAX убивает сервер и батарею мобильных устройств. Решение — Centrifugo, self-hosted real-time сервер на Go, который снижает нагрузку на бэкенд и экономит инфраструктурные затраты. Мы интегрировали его в 50+ проектах и гарантируем: после нашей настройки сообщения доставляются за <100 мс (TTFB), нагрузка на бэкенд падает в 10 раз, а пользователи забывают про F5. Экономия на инфраструктуре достигает 40% по сравнению с облачными сервисами. Свяжитесь с нами, чтобы оценить выгоду для вашего проекта.

Почему Centrifugo, а не Socket.IO или Pusher?

Centrifugo написан на Go, потребляет минимум ресурсов — один инстанс на 2 vCPU держит 20 000+ WebSocket-соединений. Socket.IO после 1 000 клиентов начинает тормозить и жрать память. Pusher/Ablity — платные, с лимитами по объёму сообщений и каналам. Centrifugo бесплатен, весь код у вас на сервере, никаких лимитов. Плюс совместимость с любым бэкендом через HTTP API или gRPC.

Как Centrifugo масштабируется под нагрузкой?

Centrifugo горизонтально масштабируется с помощью Redis Pub/Sub: добавление нового узла автоматически распределяет каналы. При отказе одного инстанса соединения перераспределяются. Мы настраиваем кластер для проектов с 50 000+ одновременных подключений, обеспечивая задержку доставки <100 мс.

Что мы делаем в рамках услуги

Архитектура интеграции

Ваш бэкенд (Laravel, Node.js, Django, Go — любой)
    │── HTTP API → Centrifugo (публикация)
    │── gRPC API → Centrifugo
    │
Клиент (браузер) ◄── WebSocket ──► Centrifugo

Установка через Docker

# docker-compose.yml
services:
  centrifugo:
    image: centrifugo/centrifugo:v5
    command: centrifugo -c /centrifugo/config.json
    ports:
      - "8000:8000"
    volumes:
      - ./centrifugo-config.json:/centrifugo/config.json
// centrifugo-config.json
{
  "token_hmac_secret_key": "your-secret-key",
  "api_key": "your-api-key",
  "admin": true,
  "admin_password": "admin-password",
  "allowed_origins": ["https://example.com"],
  "namespaces": [
    {
      "name": "notifications",
      "subscribe_for_client": false,
      "history_size": 100,
      "history_ttl": "24h"
    },
    {
      "name": "chat",
      "presence": true,
      "join_leave": true,
      "history_size": 500,
      "history_ttl": "1h"
    }
  ]
}

Сервер: генерация JWT и публикация

import jwt from 'jsonwebtoken';
import axios from 'axios';

// Токен для клиента
function generateCentrifugoToken(userId: string): string {
  return jwt.sign(
    {
      sub: userId,
      exp: Math.floor(Date.now() / 1000) + 3600
    },
    process.env.CENTRIFUGO_SECRET,
    { algorithm: 'HS256' }
  );
}

// Публикация сообщения через HTTP API
async function publishMessage(channel: string, data: unknown): Promise<void> {
  await axios.post(`${process.env.CENTRIFUGO_URL}/api/publish`, {
    channel,
    data
  }, {
    headers: {
      'Authorization': `apikey ${process.env.CENTRIFUGO_API_KEY}`,
      'Content-Type': 'application/json'
    }
  });
}

// Отправить уведомление пользователю
await publishMessage(`notifications#${userId}`, {
  type: 'order_shipped',
  orderId: '12345',
  message: 'Ваш заказ отправлен'
});

// Batch publish
await axios.post(`${process.env.CENTRIFUGO_URL}/api/batch`, {
  commands: userIds.map(id => ({
    publish: {
      channel: `notifications#${id}`,
      data: notification
    }
  }))
});

Клиент (JavaScript)

import { Centrifuge } from 'centrifuge';

const centrifuge = new Centrifuge(process.env.NEXT_PUBLIC_CENTRIFUGO_URL, {
  token: await fetchCentrifugoToken(),  // от вашего бэкенда
  debug: process.env.NODE_ENV === 'development'
});

centrifuge.on('connect', (ctx) => {
  console.log('Connected to Centrifugo', ctx.transport);
});

centrifuge.on('disconnect', (ctx) => {
  console.log('Disconnected', ctx.reason);
});

// Подписка на персональные уведомления
const sub = centrifuge.newSubscription(`notifications#${userId}`, {
  getToken: async (ctx) => {
    // Получить subscription токен для private канала
    const resp = await fetch('/api/centrifugo/subscription-token', {
      method: 'POST',
      body: JSON.stringify({ channel: ctx.channel })
    });
    return (await resp.json()).token;
  }
});

sub.on('publication', (ctx) => {
  const notification = ctx.data;
  showNotification(notification.message);
});

sub.on('subscribing', (ctx) => console.log('Subscribing...'));
sub.on('subscribed', (ctx) => console.log('Subscribed'));

sub.subscribe();
centrifuge.connect();

Presence — онлайн-статусы

Для отслеживания онлайн-статусов используется метод presence(), который возвращает список активных клиентов. Например, для документа в совместном редактировании: centrifuge.subscription('chat:doc-123').presence() возвращает объект с клиентами. Подписка на события join и leave обновляет список в реальном времени.

Подробнее о настройке JWT

JWT-токен для подключения должен содержать sub (ID пользователя) и exp (срок действия). Для private каналов требуется дополнительный subscription-токен, который запрашивается через ваш бэкенд. Мы используем два разных секрета: один для connect-токенов, другой для subscription-токенов. Это предотвращает несанкционированный доступ к каналам.

Как обеспечить безопасность real-time каналов?

Все соединения выполняются через WSS (WebSocket over HTTPS). Для доступа к каналам требуются JWT-токены: connect-токен для подключения к серверу, subscription-токен для подписки на private каналы. Токены имеют ограниченный срок жизни (обычно 1 час) и автоматически обновляются на клиенте. Для администраторских каналов мы добавляем проверку прав на стороне бэкенда при выдаче subscription-токена.

Как мы внедряем Centrifugo: процесс работы

  1. Аналитика — выявляем сценарии real-time: уведомления, чат, лента, совместное редактирование. Определяем нагрузку: сколько соединений, частота публикаций, размер сообщений.
  2. Проектирование — выбираем namespace, настраиваем каналы (personal, room, admin), продумываем модель разрешений. Проектируем схему JWT и subscription-токенов.
  3. Установка и конфигурация — разворачиваем Centrifugo в Docker, настраиваем переменные окружения, SSL-сертификаты (WSS), Redis для кластеризации.
  4. Интеграция с бэкендом — пишем модуль публикации: отправка уведомлений, batch-публикации, генерация токенов. Тестируем N+1 запросы.
  5. Интеграция с фронтендом — подключаем SDK, реализуем подписки, обработку событий, переподключение при обрыве.
  6. Тестирование — нагрузочные тесты, проверка приватных каналов, отказоустойчивость, замеры TTFB и LCP.
  7. Деплой и мониторинг — настраиваем мониторинг метрик (количество соединений, задержки, ошибки), алерты, резервное копирование конфигов.

Ориентировочные сроки

Этап Время
Базовый (установка + одно пространство) 3–5 дней
Расширенный (+ private каналы, presence) 5–8 дней
Комплексный (+ кластеризация, Redis, мониторинг) 8–12 дней

Стоимость варьируется в зависимости от сложности — мы рассчитываем её индивидуально. Гарантируем фиксацию сроков и цены.

Типичные ошибки и как мы их избегаем

  • Слишком длинные JWT — ставим срок жизни 1 час, автоматическое обновление на клиенте.
  • Отсутствие backpressure — настраиваем лимиты публикаций и конфигурируем TTL истории.
  • Путаница с токенами — чётко разделяем connect token и subscription token, используем разные секреты.
  • Забыли про CORS — разрешаем только ваши домены в allowed_origins.

Сравнение: Centrifugo vs облачные сервисы

Критерий Centrifugo Pusher / Ablity Socket.IO
Цена Бесплатно (только ресурсы) От $50/мес за 100 коннектов Бесплатно
Максимум соединений на 1 сервер 20 000+ Ограничено планом ~1 500
Контроль над данными Полный Нет (на серверах вендора) Полный
Кастомные протоколы gRPC + HTTP API Только HTTP WebSocket + HTTP long-polling
Поддержка history Встроенная В Pusher — только cache Нет

Свяжитесь с нами для консультации — мы оценим ваш проект за 1 день. Закажите интеграцию Centrifugo прямо сейчас и получите стабильное real-time за неделю.

Разработка систем реального времени: WebRTC, SSE, WebSocket

Мы знаем, как больно, когда поллинг убивает сервер. Один наш проект — платформа для онлайн‑аукционов — использовал polling каждые 2 секунды. Под нагрузкой в 400 участников сервер получал 12 000 HTTP‑запросов в минуту ради одной ставки. 90% ответов — пустые. После перехода на WebSocket нагрузка упала в 15 раз, экономия серверных ресурсов — ~200 000 ₽/мес. Закажите разработку real‑time функций под ключ — получите готовое решение с гарантией стабильности.

Реализация real‑time на продакшене — не просто библиотека. Мы проектируем архитектуру под нагрузку, сценарии и бюджет. Ниже — разбор ключевых решений с примерами.

Три транспорта реального времени: когда что выбирать

Server‑Sent Events работают поверх обычного HTTP/1.1 или HTTP/2. Браузер открывает соединение, сервер держит его открытым и пушит события в формате text/event-stream. Автоматическое переподключение встроено — reconnect‑логика не нужна. Ограничение: только сервер → клиент. Идеально для нотификаций, прогресса долгих задач, live‑фидов.

WebSocket — полнодуплексный канал после HTTP Upgrade‑рукопожатия. Браузер и сервер обмениваются фреймами в обе стороны. Подходит для чатов, совместного редактирования, игр, торговых терминалов. Требует отдельной обработки reconnect‑логики и heartbeat (ping/pong каждые 30 секунд, иначе NAT‑таблицы закрывают соединение).

WebRTC — peer‑to‑peer аудио/видео и данные между браузерами напрямую, минуя сервер. Сервер нужен только для сигнализации (STUN/TURN для обхода NAT). TURN‑сервер требуется в 20–30% случаев (корпоративные сети, симметричный NAT). Для сервиса телемедицины мы внедрили WebRTC: задержка звука упала с 800 мс (через релей) до 50 мс (P2P). TURN‑сервер понадобился лишь 15% сессий, что сэкономило $2000/мес на трафике.

WebSocket (Wikipedia)
WebRTC (Wikipedia)

Как правильно выбрать транспорт: пошаговая инструкция

  1. Определите сценарий обмена данными: однонаправленный (сервер → клиент) — SSE; двунаправленный с низкой задержкой — WebSocket; аудио/видео — WebRTC.
  2. Оцените требования к задержке. Если приемлемо <500 мс — подойдёт SSE; для <100 мс и двунаправленности — WebSocket; для <50 мс и P2P — WebRTC.
  3. Проверьте бюджет на инфраструктуру. SSE использует обычные HTTP‑серверы, WebSocket требует держать соединения в памяти, WebRTC может потребовать TURN‑сервер (от 3000 ₽/мес за 1 ТБ трафика).
  4. Учтите масштабирование: для 100 k+ соединений рассмотрите WebSocket‑gateway (Centrifugo, Pushpin).
Транспорт Направление Задержка Сложность реализации Типичные сценарии
WebSocket Полный дуплекс < 100 мс Средняя Чаты, игры, торговля
SSE Только сервер → клиент < 500 мс Низкая Нотификации, ленты прогресса
WebRTC P2P аудио/видео/данные < 50 мс Высокая Видеозвонки, передача файлов

Что такое CRDT и чем он лучше Operational Transformation?

Совместное редактирование — не просто «кто последний записал, тот и прав». Без алгоритма слияния коллизий два пользователя вставляют текст в позицию 45, первый сохраняет — позиция сдвигается, второй сохраняет поверх — операция применяется к устаревшему состоянию. Текст дублируется или теряется.

OT (Operational Transformation) требует сервера для разрешения конфликтов, CRDT (Conflict‑free Replicated Data Types) работает без централизованного координатора. Yjs — наиболее зрелая CRDT‑библиотека для браузера. Интегрируется с ProseMirror, TipTap, CodeMirror, Monaco Editor.

Сравнение библиотек для совместного редактирования

Библиотека Алгоритм Поддержка редакторов Сложность Производительность
Yjs CRDT ProseMirror, TipTap, CodeMirror, Monaco Средняя Высокая (<10 мс при 100 операциях)
ShareDB OT ProseMirror, Quill Средняя Средняя (требуется сервер для слияния)
Automerge CRDT Любой (RichText) Высокая Хорошая (но память растёт быстрее Yjs)

Проблема: размер Yjs‑документа растёт из‑за истории операций. Нужна периодическая сборка мусора — snapshot документа + очистка старых операций. Без этого документ, над которым работали год, может весить 50 МБ.

Пример heartbeat на WebSocket (Node.js)
const ws = new WebSocket('wss://example.com');
let pingInterval;

ws.on('open', () => {
  pingInterval = setInterval(() => {
    ws.ping();
    setTimeout(() => {
      if (ws.readyState === WebSocket.OPEN) ws.terminate();
    }, 5000);
  }, 25000);
});

ws.on('close', () => clearInterval(pingInterval));

Типичные ошибки при внедрении real‑time

Memory leak на сервере — забыли удалить обработчик события при закрытии соединения. На Node.js heap растёт ~1 МБ/ч. EventEmitter предупреждает о 10+ слушателях, но не всегда это замечают.

Thundering herd при реконнекте. Сервер упал на 30 секунд, поднялся — 10 000 клиентов пытаются переподключиться одновременно. Exponential backoff с jitter обязателен: delay = Math.min(baseDelay * 2^attempt + random(0, 1000), maxDelay).

Отсутствие индикации потери соединения. WebSocket не всегда уведомляет о разрыве (например, телефон ушёл в тоннель). Heartbeat решает проблему.

Процесс работы

Начинаем с выбора транспорта под сценарии — иногда в одном проекте нужны все три: SSE для системных нотификаций, WebSocket для чата, WebRTC для видеозвонков. Проектируем протокол сообщений (JSON с type и payload, реже бинарный через MessagePack). Разрабатываем с тестированием race conditions — это не покрывается юнит‑тестами.

Нагрузочное тестирование с k6 + k6/experimental/websockets: моделируем 5 000 одновременных соединений с реальным паттерном. Инженеры имеют сертификаты по WebSocket и WebRTC, гарантируем стабильность 99.9%.

Что входит

  • Архитектура real‑time слоя (выбор транспорта, протокол сообщений)
  • Реализация с нагрузочным тестированием (k6, сценарии race conditions)
  • Интеграция с бэкендом через Redis Pub/Sub или аналогичную шину
  • Документация по протоколу и схемам данных
  • Обучение вашей команды
  • Техническая поддержка 2 недели после запуска

Почему Centrifugo может быть выгоднее, чем Socket.io?

Socket.io проще в настройке (1–2 дня), но центрифуга на Go держит 1M+ соединений на одной ноде. Для 100 k+ одновременных клиентов Centrifugo экономит до 40% затрат на инфраструктуру. Получите консультацию — мы поможем выбрать стек под вашу нагрузку.

Сроки

  • Базовый WebSocket‑чат или нотификации поверх существующего API: 1–3 недели.
  • Коллаборативный редактор с Yjs и persistence: 4–8 недель.
  • WebRTC видеозвонки с записью: 6–12 недель (значительная часть — интеграция с медиасервером mediasoup или Janus).

Свяжитесь с нами для оценки вашего проекта. Обсудите задачу с инженером — оценим сложность и сроки индивидуально.