Ответ
В моем последнем Node.js проекте с реальным временем обновления данных, инициация WebSocket соединений была распределенной:
Клиентская инициация:
- Первичное подключение всегда инициировалось клиентом при загрузке SPA
- Подписка на конкретные каналы данных (например,
/stocks/AAPL)
// Клиентский код (браузер)
const socket = new WebSocket('wss://api.example.com/ws');
socket.onopen = () => {
socket.send(JSON.stringify({
type: 'subscribe',
channel: 'user-notifications',
userId: currentUser.id
}));
};
Серверная инициация:
- Push-уведомления о системных событиях (новые сообщения, обновления статусов)
- Рассылка обновлений при изменении данных в Redis pub/sub
- Heartbeat-сообщения для поддержания соединения
// Серверный код (Node.js + ws)
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
const redis = require('redis');
const redisClient = redis.createClient();
// Подписка на Redis канал
redisClient.subscribe('system-alerts');
redisClient.on('message', (channel, message) => {
// Рассылка всем подключенным клиентам
wss.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify({
type: 'alert',
channel: channel,
data: JSON.parse(message)
}));
}
});
});
// Сервер инициирует отправку по таймеру
setInterval(() => {
wss.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify({ type: 'ping', timestamp: Date.now() }));
}
});
}, 30000);
Архитектурное решение: Мы использовали гибридный подход. Клиенты подписывались на интересующие их каналы, а сервер инициировал отправку при наступлении событий. Это позволило снизить нагрузку и дать клиентам контроль над получаемыми данными.