分布式状态管理
探索使用外部消息代理(例如 Redis Pub/Sub、Kafka)在多个 WebSocket 服务器之间同步状态。
分布式状态管理 是 CoddyKit 上的免费 WebSockets & Realtime Systems Programming 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 WebSockets & Realtime Systems Programming 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 WebSockets & Realtime Systems Programming 课程共包含 4 节课。
本课时的部分内容尚未翻译,以英文显示。
Scaling Challenges: Shared State
You've learned about scaling WebSocket applications by running multiple server instances behind a load balancer. But what happens when a client connects to Server A, and another client connected to Server B needs to send a message to the first client?
This is the challenge of distributed state management: how do your servers share information and coordinate?
Why Centralize State?
Imagine a chat application. If Client 1 is on Server A and Client 2 is on Server B, and Client 1 sends a message, how does Server A tell Server B to deliver it to Client 2?
Without a way for servers to communicate, messages or updates might only reach clients connected to the same server, breaking the real-time experience.
Introducing Message Brokers
To solve this, we use a message broker. Think of it as a central post office for your servers.
- Servers send messages to the broker.
- Other servers can then receive messages from the broker.
This allows all your WebSocket servers to communicate indirectly, without needing to know about each other's existence.
The Pub/Sub Pattern
Many message brokers use a Publisher-Subscriber (Pub/Sub) pattern. It works like this:
- Publishers send messages to specific channels or topics.
- Subscribers express interest in one or more channels and receive all messages published to them.
This pattern is perfect for broadcasting data across multiple server instances.
Redis Pub/Sub Example
Redis is a popular, open-source, in-memory data store that's often used as a message broker. Its Pub/Sub feature is fast and simple to use.
You can have multiple Node.js WebSocket servers, all connected to a single Redis instance, using it to exchange messages.
Redis Pub/Sub Basics
Let's say you have two WebSocket servers, Server A and Server B, both connected to Redis.
- When
Server Areceives a message it needs to share, it publishes that message to a Redis channel (e.g.,'global_chat'). Server Bhas subscribed to'global_chat', so it instantly receives the message from Redis.
Then, Server B can forward that message to its own connected clients.
Server Publishes to Redis
Here's a simplified Node.js example for a WebSocket server publishing messages to a Redis channel. We'll use the ws library for WebSockets and ioredis for Redis.
Make sure you have Redis running and ws and ioredis installed (`npm i ws ioredis`).
const WebSocket = require('ws');
const Redis = require('ioredis');
const wss = new WebSocket.Server({ port: 8080 });
const publisher = new Redis(); // Connects to localhost:6379
wss.on('connection', ws => {
console.log('Client connected to Server 1');
ws.on('message', message => {
const msg = message.toString();
console.log(`Server 1 received: ${msg}`);
// Publish message to 'chat_messages' channel
publisher.publish('chat_messages', msg);
ws.send(`You said: ${msg}`); // Echo back to sender
});
});
console.log('Server 1 listening on ws://localhost:8080');Server Subscribes & Relays
Now, here's another Node.js WebSocket server (running on a different port) that subscribes to the same Redis channel. When it gets a message from Redis, it broadcasts it to its own connected clients.
You would run this in a separate terminal from server1.js.
const WebSocket = require('ws');
const Redis = require('ioredis');
const wss = new WebSocket.Server({ port: 8081 });
const subscriber = new Redis(); // Connects to localhost:6379
// Subscribe to the 'chat_messages' channel
subscriber.subscribe('chat_messages', (err, count) => {
if (err) console.error('Failed to subscribe:', err.message);
else console.log(`Subscribed to ${count} channel(s)`);
});
// Handle messages received from Redis
subscriber.on('message', (channel, message) => {
console.log(`Server 2 received from Redis [${channel}]: ${message}`);
// Broadcast to all connected clients on Server 2
wss.clients.forEach(client => {
if (client.readyState === WebSocket.OPEN) {
client.send(`Global Chat: ${message}`);
}
});
});
wss.on('connection', ws => {
console.log('Client connected to Server 2');
ws.send('Welcome to Server 2!');
});
console.log('Server 2 listening on ws://localhost:8081');Benefits for Scaling
Using a message broker like Redis Pub/Sub offers significant advantages for scaling WebSocket applications:
- Decoupling: Servers don't need direct knowledge of each other. They only interact with the broker.
- Horizontal Scalability: You can easily add more WebSocket servers as traffic grows, and they'll all connect to the same broker.
- Global Broadcasts: Messages can be efficiently broadcast to all clients, regardless of which server they are connected to.
Beyond Broadcasts: Presence
Message brokers aren't just for broadcasting chat messages. They are vital for synchronizing other types of distributed state, like user presence.
For example, when a user logs in, their connected server can publish an 'online' status to a Redis channel. Other servers subscribe to this to keep their lists of online users updated.
Message Broker Check
Consider a scenario where you have multiple WebSocket servers, and a message sent to one server needs to reach a client connected to another server. Which pattern best addresses this?
Recap: Distributed State
We learned that scaling WebSocket applications requires managing distributed state. Message brokers like Redis, using the Pub/Sub pattern, are crucial for allowing multiple WebSocket servers to communicate and synchronize data, ensuring all clients receive relevant updates regardless of which server they're connected to.
This makes your application more resilient and scalable as you add more server instances.
常见问题解答
「分布式状态管理」课时是免费的吗?
是的 — 「分布式状态管理」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 WebSockets & Realtime Systems Programming 课程的其余内容,请升级到 CoddyKit PRO。 WebSockets & Realtime Systems Programming 课程共包含 4 节课。
「分布式状态管理」这节课中我会学到什么?
探索使用外部消息代理(例如 Redis Pub/Sub、Kafka)在多个 WebSocket 服务器之间同步状态。 你通过在浏览器中直接运行的动手代码来练习 WebSockets & Realtime Systems Programming,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 WebSockets & Realtime Systems Programming 需要有经验吗?
无需任何先前经验。CoddyKit 上的 WebSockets & Realtime Systems Programming 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「分布式状态管理」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 WebSockets & Realtime Systems Programming 课中编写并运行代码吗?
能。每节 WebSockets & Realtime Systems Programming 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。