![](/img/trans.png)
[英]AWS ELB -> nginx -> socket.io node.js sticky load balancing
[英]Load balancing with socket.io server with nginx using redis
我正在使用Typescript 、 Node.js 、 Socket.io和React前端进行聊天项目。 我的应用程序在单个服务器实例上运行良好。 但是,当与多个服务器进行负载平衡时,聊天功能不起作用。 我使用 Redis 和 @socket.io/redis-adapter 来解决这个问题。 但它仍然无法正常工作。 我在哪里做错了?
这是我的 nginx conf
upstream backend {
server 127.0.0.1:8000;
server 127.0.0.1:8001;
}
server {
listen 80;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
这是我在 server.js 中的 socket.io 实现
const server = http.createServer(app);
const io = new Server<ClientToServerEvents, ServerToClientEvents>(server, {
cors: {
origin: process.env.NODE_ENV === "production" ? process.env.ALLOWED_HOST: "http://localhost:3000",
methods: ["GET", "POST"],
credentials: true
},
transports: ['websocket']
});
// redis config
const pubClient = createClient({ url: 'redis://localhost:6379'});
const subClient = pubClient.duplicate();
Promise.all([pubClient.connect(), subClient.connect()]).then(() => {
io.adapter(createAdapter(pubClient, subClient));
});
// routes
app.get("/", (req, res) => {
res.send("Welcome to Node.js Server. 🚀 Server running on port 8000.");
});
app.use("/api/v1", apiRoutes);
// ********** Socket Start *********** //
// array of objects that stores online users
let users: { socketId: string; userId: string; username: string }[] = [];
// method for adding new user into users array
const addUser = (userId: string, socketId: string, username: string) => {
if (
userId &&
!users.some((user) => user.socketId === socketId && user.userId === userId)
) {
if (users.some((user) => user.socketId === socketId)) {
users = users.filter((user) => user.socketId !== socketId);
}
users.push({ userId, socketId, username });
}
};
// method for removing disconnected user from users array
const removeUser = (socketId: string) => {
users = users.filter((user) => user.socketId !== socketId);
};
// method for getting user from users array
const getReceiver = (
receiverId: string,
senderId: string,
socketId: string
) => {
return users.filter(
(user) =>
user.userId === receiverId ||
(user.userId === senderId && user.socketId !== socketId)
);
};
// starting socket connection
io.on("connection", (socket) => {
// establishing connection with client
console.log(`a client connected on websocket.SocketId:${socket.id}`);
//taking userId and username from client and pushing to users array along with socket id
socket.on("addUser", ({ userId, username }) => {
addUser(userId, socket.id, username);
io.emit(SocketEvents.GET_USERS, users); // sending online users to client side
});
//receiving message from sender and sending to the receiver
socket.on("sendMessage", (message, receiverId) => {
const user = getReceiver(receiverId, message.senderId, socket.id);
if (user.length > 0) {
user.forEach((u) => {
io.to(u.socketId).emit("receiveMessage", message);
socket.broadcast.emit('test' , {username: 'test'});
});
} else {
io.to(socket.id).emit("error", "message not sent. receiver is offline");
}
});
// disconnection of a client
socket.on("disconnect", () => {
console.log(`a client disconnected from websocket.SocketId:${socket.id}`);
removeUser(socket.id);
});
});
// 404 not found handler
app.use(notFoundHandler);
// common error handler
app.use(errorHandler);
// ********** Socket End *********** //
server.listen(port,
() => console.log(`🚀 Server running on port ${port}`));
Socket.io 需要粘性会话,不确定 nginx 的免费版本是否支持它。
另一种选择是从 Socket.io 文档中禁用 HTTP 长轮询传输:
如果您禁用 HTTP 长轮询传输(这是 2021 年完全有效的选择),您将不需要粘性会话:
您可以像这样禁用它:
io("https://example.com", {
transports: ["websocket"]
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.