繁体   English   中英

负载平衡与 socket.io 服务器与 nginx 使用 redis

[英]Load balancing with socket.io server with nginx using redis

我正在使用TypescriptNode.jsSocket.ioReact前端进行聊天项目。 我的应用程序在单个服务器实例上运行良好。 但是,当与多个服务器进行负载平衡时,聊天功能不起作用。 我使用 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM