在远程服务器上使用docker、nestjs gateway、react、vite时为socket.io配置NGINX

问题描述 投票:0回答:1

我正在尝试弄清楚如何获取 nginx 配置设置,以允许 socket.io 从我的 React 客户端连接到使用 NestJS 网关的节点后端。 客户端和后端都在临时/生产服务器上自己的 docker 容器内运行。 当在我的本地计算机上测试东西时,使用 vite 运行客户端和节点运行后端(不在 docker 中运行)我可以毫无问题地连接两者。所以我知道我已经配置了后端和前端并且工作正常。 当我部署到临时服务器时,我无法使 socket.io 连接正常工作。我 99% 确定这与我的 nginx 配置有关。

这是我的设置:

  1. 在我的后端
    docker
    文件中,我暴露了端口8889(这是我的套接字网关端口)
EXPOSE 8889
  1. 在我的后端中,使用NestJS,我创建了一个
    ws.gateway.ts
    文件。就是这个:
@WebSocketGateway(8889, { cors: { origin: "*" }, path: "/socket", namespace: "/api/frontend" })
export class EventsGateway implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect {
  @WebSocketServer()
  server: Server;

  afterInit(server: Server) {
    console.log("Websocket initialized.");
  }

  handleDisconnect(client: Socket) {
    console.log(`Client disconnected: ${client.id}`);
  }

  handleConnection(client: Socket, ...args: any[]) {
    console.log(`Client connected: ${client.id}`);
  }

}

该类在模块中设置并连接到 NestJS 模块系统。

  1. 在我的客户端应用程序中,这是一个使用 vite 在本地提供服务的 React 应用程序。我知道 vite 在临时服务器上运行时不会对客户端产生任何影响,因为 nginx 正在为客户端提供服务并记下 vite,但我在这里指出以防万一。我有以下文件和代码:

vite.config.mjs

export default defineConfig({
   ...
   server: {
    host: "127.0.0.1",
    port: 3000,
    proxy: {
      "/api": {
        target: "http://127.0.0.1:8888/",   // <-- this is for the backend api's.
        changeOrigin: true,
        secure: false,
        ws: true,
        rewrite: path => path.replace(/^\/api/, ""),
      },
      "/socket": {
        target: "http://127.0.0.1:8889/",   // <-- This is for the socket connections.
        changeOrigin: true,
        secure: false,
        ws: true,
        // rewrite: path => path.replace(/^\/socket/, ""),
      },
    },
  },
  ...
})

这是我的

socket.tsx
文件的一部分,该文件已添加到我的 app.tsx 文件中,我尝试在其中进行测试套接字连接:

const WSClient: React.FC<WSClientProps> = props => {
   const uri = `${import.meta.env.VITE_APP_WS}/api/frontend`; // <-- this translates to https://stage.mycompany.io/api/frontend

   useEffect(() => {
      console.log("Attempting to open socket to:", uri);
      const options: Partial<ManagerOptions & SocketOptions> = {
        reconnection: true,
        reconnectionDelay: 100,
        reconnectionAttempts: 3,
        path: "/socket",
      };
      const newSocket = io(uri, options);
      setSocket(newSocket);
      newSocket.on("connect", () => {
        console.log("Socket connected to backend server. Socket id:", newSocket.id, "on uri:", uri);
      });
      newSocket.on("disconnect", () => {
        console.log(`Socket id ${newSocket.id} has disconnected.`);
      });
      newSocket.io.on("reconnect_attempt", attempt => {
        console.log(`Socket reconnect_attempt ${attempt}.`); 
        if (attempt > 2) {
          console.log("Failed to disconnect the socket.");
        }
      });
   }, []);

   ...
}
  1. 这是我的 nginx
    default.conf
    文件。我承认,这不是我的强项,我不太确定如何正确设置它以及哪里需要帮助。
server {
    listen       80;
    server_name  localhost;
    root   /usr/share/nginx/html;
    index  index.html index.htm;
    resolver 127.0.0.11 ipv6=off valid=10s;
    access_log  /etc/nginx/conf.d/access.log;
    error_log  /etc/nginx/conf.d/errors.log debug;

    location @index {
        root   /usr/share/nginx/html;
        add_header Cache-Control 'private, no-cache, no-store, must-revalidate';
        add_header Expires 'Sat, 01 Jan 2000 00:00:00 GMT';
        add_header Pragma no-cache;
        try_files $uri $uri/ /index.html;
    }

    ##### SETUP FOR SOCKET.IO ######
    location /socket {
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_pass http://127.0.0.1:8889/;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
    }
    #### END SETUP FOR SOCKET.IO ######

    location / {
        try_files $uri @index;
    }

    error_page   500 502 503 504  /50x.html;

    location = /50x.html {
        root   /usr/share/nginx/html;
    }

}

客户端的 React 部分以及与后端 api 的通信与以前一样完美。为了访问任何 api,我需要对 https://stage.mycompany.io/api/https://stage.mycompany.io/api/graphql/ 执行 axios 或 fetch 调用我的疑问。一切都按其应有的方式进行。

在我的控制台中,我看到套接字正在尝试连接到网关命名空间中定义的https://stage.mycompany.io/api/frontend。老实说,我不确定故障在哪里,我在 nginx 配置文件中尝试了很多不同的东西,但我似乎无法弄清楚。

认为这可能是proxy_pass,因为后端位于另一个docker容器中,因此使用本地主机或家庭IP是行不通的。我尝试过使用服务器 url 和其他一些东西但无济于事。

这几天我一直在用头撞键盘,试图解决这个问题。任何帮助将不胜感激。

node.js docker nginx socket.io nestjs
1个回答
0
投票

假设容器之间相互链接并连接,并且您可以访问两者。

基于您的配置:‘ proxy_pass http://127.0.0.1:8889/;’您正在尝试连接到 nginx 容器的本地主机,这里您应该使用另一个容器的 IP 或其别名(哈希)

© www.soinside.com 2019 - 2024. All rights reserved.