वास्तविक समय की विशेषताएं – लाइव चैट, सूचनाएं, सहयोगी संपादन, लाइव डैशबोर्ड – क्लाइंट और सर्वर के बीच लगातार कनेक्शन की आवश्यकता होती है। 2026 में,Socket.io के माध्यम से WebSockets अधिकांश वास्तविक समय के अनुप्रयोगों के लिए यह सबसे व्यावहारिक और व्यापक रूप से तैनात समाधान बना हुआ है। यह ट्यूटोरियल रेडिस पब/सब के माध्यम से स्केलिंग के साथ एक संपूर्ण वास्तविक समय प्रणाली बनाता है।
📋 Table of Contents
- वेबसॉकेट बनाम एसएसई बनाम लॉन्ग पोलिंग
- सर्वर: एक्सप्रेस + सॉकेट.आईओ
- ग्राहक: प्रतिक्रिया + Socket.io
- रेडिस पब/सब के साथ स्केलिंग
- सर्वर कोड में रेडिस पब/सब पैटर्न क्षैतिज स्केलिंग की अनुमति देता है: जब कोई संदेश एक नोड.जेएस इंस्टेंस पर आता है, तो यह रेडिस पर प्रकाशित होता है। अन्य सभी उदाहरण (रेडिस की सदस्यता वाले) इसे प्राप्त करते हैं और अपने जुड़े हुए ग्राहकों को भेजते हैं। इसका मतलब है कि आप एक लोड बैलेंसर के पीछे 10 Node.js इंस्टेंसेस चला सकते हैं और संदेश सभी उपयोगकर्ताओं तक पहुंचते हैं, भले ही वे किसी भी इंस्टेंस से जुड़े हों।
- प्रश्न: सॉकेट.आईओ बनाम देशी वेबसॉकेट एपीआई?
- Socket.io और Redis Pub/Sub के साथ WebSockets 2026 में वास्तविक समय के अनुप्रयोगों के लिए सिद्ध, स्केलेबल आर्किटेक्चर है। इस ट्यूटोरियल में सर्वर कोड एक ही उदाहरण पर हजारों समवर्ती उपयोगकर्ताओं को संभालता है, और मांग बढ़ने पर Redis के माध्यम से क्षैतिज रूप से स्केल करता है। एक ही उदाहरण से शुरू करें, जब आपको एक सर्वर से आगे बढ़ने की आवश्यकता हो तो रेडिस जोड़ें, और केवल प्रबंधित वेबसॉकेट सेवाओं पर जाएं यदि परिचालन ओवरहेड एक समस्या बन जाए।
वेबसॉकेट बनाम एसएसई बनाम लॉन्ग पोलिंग
| विधि | द्विदिश | विलंबता | के लिए सर्वश्रेष्ठ वेबसॉकेट |
|---|---|---|---|
| हाँ | ~1ms | चैट, गेमिंग, सहयोगी उपकरण | सर्वर द्वारा भेजे गए इवेंट |
| नहीं (केवल सर्वर → क्लाइंट) | ~5ms | लाइव डैशबोर्ड, सूचनाएं | लंबा मतदान |
| नकली | 100-500ms | प्रतिबंधित नेटवर्क के लिए फ़ॉलबैक | प्रोजेक्ट सेटअप |
सर्वर: एक्सप्रेस + सॉकेट.आईओ
mkdir realtime-app && cd realtime-app
npm init -y
npm install express socket.io ioredis cors
# Frontend dependencies
npm install -D vite
ग्राहक: प्रतिक्रिया + Socket.io
// server.js
const express = require('express');
const { createServer } = require('http');
const { Server } = require('socket.io');
const Redis = require('ioredis');
const cors = require('cors');
const app = express();
const server = createServer(app);
const io = new Server(server, {
cors: {
origin: "http://localhost:5173", // Vite dev server
methods: ["GET", "POST"]
}
});
app.use(cors());
app.use(express.json());
// Redis Pub/Sub for multi-instance scaling
const pub = new Redis({ host: 'localhost', port: 6379 });
const sub = new Redis({ host: 'localhost', port: 6379 });
// ── Active users tracking ─────────────────────────────────
const activeUsers = new Map(); // socketId → { userId, username, room }
// ── Subscribe to Redis (messages from other server instances) ──
sub.subscribe('chat', 'notifications', (err, count) => {
console.log(`Subscribed to ${count} Redis channels`);
});
sub.on('message', (channel, message) => {
const data = JSON.parse(message);
if (channel === 'chat') {
io.to(data.room).emit('message', data);
}
if (channel === 'notifications') {
io.to(data.userId).emit('notification', data);
}
});
// ── Socket.io connection handler ──────────────────────────
io.on('connection', (socket) => {
console.log(`Client connected: ${socket.id}`);
// ── Authenticate ───────────────────────────────────────
socket.on('authenticate', ({ userId, username }) => {
activeUsers.set(socket.id, { userId, username });
socket.join(userId); // join personal room for direct notifications
socket.emit('authenticated', { userId, socketId: socket.id });
console.log(`User authenticated: ${username} (${userId})`);
});
// ── Join chat room ─────────────────────────────────────
socket.on('join_room', ({ roomId }) => {
const user = activeUsers.get(socket.id);
if (!user) return socket.emit('error', 'Not authenticated');
socket.join(roomId);
activeUsers.set(socket.id, { ...user, room: roomId });
// Notify others in room
socket.to(roomId).emit('user_joined', {
userId: user.userId,
username: user.username,
roomId,
timestamp: Date.now()
});
console.log(`${user.username} joined room: ${roomId}`);
});
// ── Send message ───────────────────────────────────────
socket.on('send_message', async ({ roomId, content }) => {
const user = activeUsers.get(socket.id);
if (!user) return socket.emit('error', 'Not authenticated');
const message = {
id: `msg_${Date.now()}_${Math.random().toString(36).slice(2)}`,
userId: user.userId,
username: user.username,
content,
room: roomId,
timestamp: Date.now()
};
// Publish to Redis so ALL server instances receive it
pub.publish('chat', JSON.stringify(message));
// TODO: persist to database here
// await db.messages.create({ data: message });
});
// ── Typing indicator ───────────────────────────────────
socket.on('typing', ({ roomId, isTyping }) => {
const user = activeUsers.get(socket.id);
if (!user) return;
socket.to(roomId).emit('user_typing', {
userId: user.userId,
username: user.username,
isTyping
});
});
// ── Disconnect ─────────────────────────────────────────
socket.on('disconnect', () => {
const user = activeUsers.get(socket.id);
if (user?.room) {
socket.to(user.room).emit('user_left', {
userId: user.userId,
username: user.username
});
}
activeUsers.delete(socket.id);
console.log(`Client disconnected: ${socket.id}`);
});
});
// ── REST API: send notification from backend ──────────────
app.post('/notify', (req, res) => {
const { userId, type, message } = req.body;
pub.publish('notifications', JSON.stringify({ userId, type, message, timestamp: Date.now() }));
res.json({ ok: true });
});
server.listen(3001, () => console.log('Server running on port 3001'));
रेडिस पब/सब के साथ स्केलिंग
// hooks/useSocket.ts
import { useEffect, useRef, useState } from 'react';
import { io, Socket } from 'socket.io-client';
export function useSocket(userId: string, username: string) {
const socket = useRef<Socket | null>(null);
const [connected, setConnected] = useState(false);
const [messages, setMessages] = useState<Message[]>([]);
const [notifications, setNotifications] = useState<Notification[]>([]);
const [typingUsers, setTypingUsers] = useState<Set<string>>(new Set());
useEffect(() => {
socket.current = io('http://localhost:3001');
socket.current.on('connect', () => {
setConnected(true);
socket.current!.emit('authenticate', { userId, username });
});
socket.current.on('message', (msg: Message) => {
setMessages(prev => [...prev, msg]);
});
socket.current.on('notification', (notif: Notification) => {
setNotifications(prev => [notif, ...prev]);
});
socket.current.on('user_typing', ({ username: typer, isTyping }) => {
setTypingUsers(prev => {
const next = new Set(prev);
isTyping ? next.add(typer) : next.delete(typer);
return next;
});
});
socket.current.on('disconnect', () => setConnected(false));
return () => { socket.current?.disconnect(); };
}, [userId, username]);
const joinRoom = (roomId: string) => socket.current?.emit('join_room', { roomId });
const sendMessage = (roomId: string, content: string) =>
socket.current?.emit('send_message', { roomId, content });
const setTyping = (roomId: string, isTyping: boolean) =>
socket.current?.emit('typing', { roomId, isTyping });
return { connected, messages, notifications, typingUsers, joinRoom, sendMessage, setTyping };
}
सर्वर कोड में रेडिस पब/सब पैटर्न क्षैतिज स्केलिंग की अनुमति देता है: जब कोई संदेश एक नोड.जेएस इंस्टेंस पर आता है, तो यह रेडिस पर प्रकाशित होता है। अन्य सभी उदाहरण (रेडिस की सदस्यता वाले) इसे प्राप्त करते हैं और अपने जुड़े हुए ग्राहकों को भेजते हैं। इसका मतलब है कि आप एक लोड बैलेंसर के पीछे 10 Node.js इंस्टेंसेस चला सकते हैं और संदेश सभी उपयोगकर्ताओं तक पहुंचते हैं, भले ही वे किसी भी इंस्टेंस से जुड़े हों।
अक्सर पूछे जाने वाले प्रश्न
# Run multiple instances
PORT=3001 node server.js &
PORT=3002 node server.js &
PORT=3003 node server.js &
# Nginx load balancer with sticky sessions (WebSocket requirement)
upstream websocket {
ip_hash; # sticky sessions - same client hits same server
server localhost:3001;
server localhost:3002;
server localhost:3003;
}
प्रश्न: सॉकेट.आईओ बनाम देशी वेबसॉकेट एपीआई?
A: Socket.io जोड़ता है: स्वचालित पुन: कनेक्शन, कमरे/नेमस्पेस, लॉन्ग-पोलिंग पर फ़ॉलबैक, और इवेंट-आधारित एपीआई। नेटिव वेबसॉकेट निचले स्तर का है। उत्पादन के लिए Socket.io का उपयोग करें – पुन: कनेक्शन तर्क अकेले काम के घंटे बचाता है।
प्रश्न: Node.js कितने समवर्ती WebSocket कनेक्शन संभाल सकता है?
उत्तर: 8 जीबी रैम वाले एकल 4-कोर सर्वर पर, संदेश आवृत्ति के आधार पर 10,000-50,000 समवर्ती कनेक्शन की अपेक्षा करें। Redis क्लस्टरिंग के साथ Socket.io कई सर्वरों पर लाखों तक पहुंच गया है।
प्रश्न: क्या वेबसॉकेट फ़ायरवॉल और प्रॉक्सी के माध्यम से काम करते हैं?
उत्तर: अधिकांश आधुनिक नेटवर्क पोर्ट 443 (HTTPS/WSS) पर वेबसॉकेट की अनुमति देते हैं। यदि WebSocket अवरुद्ध हो जाता है तो Socket.io लॉन्ग-पोलिंग पर वापस आ जाता है। उत्पादन में WSS (सुरक्षित वेबसॉकेट) का उपयोग करें।
प्रश्न: मैं चैट संदेशों को कैसे जारी रखूँ?
उत्तर: PostgreSQL या MongoDB में स्टोर करें। तेजी से पुनर्प्राप्ति के लिए (रूमआईडी, टाइमस्टैम्प) द्वारा अनुक्रमित करें। जब कोई उपयोगकर्ता REST API के माध्यम से किसी कमरे में शामिल होता है तो अंतिम 50 संदेश लोड करें; WebSocket के माध्यम से नए संदेश स्ट्रीम करें।
प्रश्न: क्या कोई प्रबंधित वेबसॉकेट सेवा विकल्प है?
ए: पुशर, एबली और एडब्ल्यूएस एपीआई गेटवे वेबसॉकेट प्रबंधित विकल्प हैं। ऊंची लागत लेकिन कोई बुनियादी ढांचा प्रबंधन नहीं। छोटे पैमाने के लिए या जब डेवलपर का समय बाधा हो तो अच्छा है।
निष्कर्ष
Socket.io और Redis Pub/Sub के साथ WebSockets 2026 में वास्तविक समय के अनुप्रयोगों के लिए सिद्ध, स्केलेबल आर्किटेक्चर है। इस ट्यूटोरियल में सर्वर कोड एक ही उदाहरण पर हजारों समवर्ती उपयोगकर्ताओं को संभालता है, और मांग बढ़ने पर Redis के माध्यम से क्षैतिज रूप से स्केल करता है। एक ही उदाहरण से शुरू करें, जब आपको एक सर्वर से आगे बढ़ने की आवश्यकता हो तो रेडिस जोड़ें, और केवल प्रबंधित वेबसॉकेट सेवाओं पर जाएं यदि परिचालन ओवरहेड एक समस्या बन जाए।
Socket.io और Redis Pub/Sub के साथ WebSockets 2026 में वास्तविक समय के अनुप्रयोगों के लिए सिद्ध, स्केलेबल आर्किटेक्चर है। इस ट्यूटोरियल में सर्वर कोड एक ही उदाहरण पर हजारों समवर्ती उपयोगकर्ताओं को संभालता है, और मांग बढ़ने पर Redis के माध्यम से क्षैतिज रूप से स्केल करता है। एक ही उदाहरण से शुरू करें, जब आपको एक सर्वर से आगे बढ़ने की आवश्यकता हो तो रेडिस जोड़ें, और केवल प्रबंधित वेबसॉकेट सेवाओं पर जाएं यदि परिचालन ओवरहेड एक समस्या बन जाए।
🔗 Share this article
✍️ Leave a Comment