[英]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.