水平擴充
現在我們的應用程式已能彈性應對暫時的網路中斷,讓我們看看如何水平擴充它,以便能支援數千個同時連線的用戶端。
備註
- 水平擴充(又稱為「橫向擴充」)表示新增伺服器至您的基礎架構,以應付新需求
- 垂直擴充(又稱為「縱向擴充」)表示新增更多資源(處理能力、記憶體、儲存空間等)至您現有的基礎架構
第一步:讓我們使用主機的所有可用核心。預設情況下,Node.js 會在單一執行緒中執行您的 JavaScript 程式碼,這表示即使使用 32 核心 CPU,也只會使用一個核心。很幸運地,Node.js cluster
模組 提供了一個便利的方法,可以為每個核心建立一個工作執行緒。
我們也需要一個方法來轉發 Socket.IO 伺服器之間的事件。我們稱此元件為「適配器」。


因此,讓我們安裝叢集適配器
- NPM
- Yarn
- pnpm
npm install @socket.io/cluster-adapter
yarn add @socket.io/cluster-adapter
pnpm add @socket.io/cluster-adapter
現在,我們將其插入
- CommonJS
- ES 模組
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 https://127.0.0.1:${port}`);
});
}
main();
index.js
import express from 'express';
import { createServer } from 'node:http';
import { Server } from 'socket.io';
import sqlite3 from 'sqlite3';
import { open } from 'sqlite';
import { availableParallelism } from 'node:os';
import cluster from 'node:cluster';
import { createAdapter, setupPrimary } from '@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
setupPrimary();
} else {
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 https://127.0.0.1:${port}`);
});
}
就是這樣!這將為您的機器上每個可用的 CPU 產生一個工作執行緒。讓我們看看實際運作狀況
正如您在網址列中所見,每個瀏覽器分頁都連線至不同的 Socket.IO 伺服器,而適配器只是在它們之間轉發 chat message
事件。
提示
目前有 5 個官方適配器實作
- Redis 適配器
- the Redis Streams 適配器
- the MongoDB 適配器
- the Postgres 適配器
- the 叢集適配器
因此,您可以選擇最符合您需求的適配器。但是,請注意,有些實作不支援連線狀態復原功能,您可以在此處找到相容性矩陣。
備註
在大部分情況下,您還需要確保 Socket.IO 會話的所有 HTTP 要求都到達同一伺服器(也稱為「sticky session」)。不過,這裡不需要這樣做,因為每個 Socket.IO 伺服器都有自己的埠。
更多資訊請見此處。
最後,我們的聊天應用程式就完成了!在本教學課程中,我們已經看到如何
- 在用戶端和伺服器之間傳送事件
- 廣播事件給所有已連線用戶端或其中一部分用戶端
- 處理暫時斷線
- 擴充
現在您應該對 Socket.IO 所提供的功能有更深入的了解。現在輪到您建立自己的即時應用程式了!
資訊
- CommonJS
- ES 模組
您可以在以下位置直接在瀏覽器中執行此範例
您可以在以下位置直接在瀏覽器中執行此範例