转到主要内容
版本:4.x

水平扩展

现在我们的应用程序已经能够应对临时的网络中断,让我们看看如何通过水平扩展来支持数千个并发客户端。

备注
  • 水平扩展(也称为“扩展出”)是指向基础设施中添加新的服务器以应对新的需求
  • 垂直扩展(也称为“扩展上”)是指为现有基础设施添加更多资源(处理能力、内存、存储等)

第一步:利用主机的所有可用核心。默认情况下,Node.js 在单线程中运行 JavaScript 代码,这意味着即使有 32 核 CPU,也只会使用一个核心。幸运的是,Node.js 的 cluster 模块 提供了一种方便的方法来为每个核心创建一个工作线程。

我们还需要一种方法在 Socket.IO 服务器之间转发事件。我们称这个组件为“适配器”。

‘hello’ 事件被转发到其他服务器‘hello’ 事件被转发到其他服务器

现在安装集群适配器:

npm install @socket.io/cluster-adapter

现在我们将其接入:

index.js
const express = require('express');
const { createServer } = require('node:http');
const { join } = require('node:path');
const { Server } = require('socket.io');
const sqlite3 = require('sqlite3');
const { open } = require('sqlite');
const { availableParallelism } = require('node:os');
const cluster = require('node:cluster');
const { createAdapter, setupPrimary } = require('@socket.io/cluster-adapter');

if (cluster.isPrimary) {
const numCPUs = availableParallelism();
// 为每个可用核心创建一个工作线程
for (let i = 0; i < numCPUs; i++) {
cluster.fork({
PORT: 3000 + i
});
}

// 在主线程上设置适配器
return setupPrimary();
}

async function main() {
const app = express();
const server = createServer(app);
const io = new Server(server, {
connectionStateRecovery: {},
// 在每个工作线程上设置适配器
adapter: createAdapter()
});

// [...]

// 每个工作线程将监听不同的端口
const port = process.env.PORT;

server.listen(port, () => {
console.log(`server running at http://localhost:${port}`);
});
}

main();

完成了!这将在您的机器上为每个可用的 CPU 生成一个工作线程。让我们看看它的实际效果:

如您在地址栏中所见,每个浏览器标签页连接到不同的 Socket.IO 服务器,适配器只是简单地在它们之间转发 chat message 事件。

提示

目前有 5 种官方适配器实现:

您可以选择最适合您需求的那个。不过,请注意某些实现不支持连接状态恢复功能,您可以在这里找到兼容性矩阵。

备注

在大多数情况下,您还需要确保 Socket.IO 会话的所有 HTTP 请求都到达同一服务器(也称为“粘性会话”)。不过这里不需要这样,因为每个 Socket.IO 服务器都有自己的端口。

更多信息请查看这里

这就完成了我们的聊天应用程序!在本教程中,我们学习了如何:

  • 在客户端和服务器之间发送事件
  • 向所有或部分连接的客户端广播事件
  • 处理临时断线
  • 扩展

您现在应该对 Socket.IO 提供的功能有更好的了解。现在是您构建自己的实时应用程序的时候了!

信息

您可以在浏览器中直接运行此示例: