跳至主要内容
版本: 4.x

水平扩展

现在我们的应用程序已经能够抵御暂时的网络中断,让我们看看如何水平扩展它,以便能够支持数千个并发客户端。

注意
  • 水平扩展(也称为“横向扩展”)意味着向您的基础设施添加新服务器以应对新的需求
  • 垂直扩展(也称为“纵向扩展”)意味着向您的现有基础设施添加更多资源(处理能力、内存、存储等)

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

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

The 'hello' event is forwarded to the other serversThe 'hello' event is forwarded to the other servers

所以让我们安装集群适配器

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();
// create one worker per available core
for (let i = 0; i < numCPUs; i++) {
cluster.fork({
PORT: 3000 + i
});
}

// set up the adapter on the primary thread
return setupPrimary();
}

async function main() {
const app = express();
const server = createServer(app);
const io = new Server(server, {
connectionStateRecovery: {},
// set up the adapter on each worker thread
adapter: createAdapter()
});

// [...]

// each worker will listen on a distinct port
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 提供的功能有更好的了解。现在轮到您构建自己的实时应用程序了!

信息

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