我正在尝试弄清楚如何获取 nginx 配置设置,以允许 socket.io 从我的 React 客户端连接到使用 NestJS 网关的节点后端。 客户端和后端都在临时/生产服务器上自己的 docker 容器内运行。 当在我的本地计算机上测试东西时,使用 vite 运行客户端和节点运行后端(不在 docker 中运行)我可以毫无问题地连接两者。所以我知道我已经配置了后端和前端并且工作正常。 当我部署到临时服务器时,我无法使 socket.io 连接正常工作。我 99% 确定这与我的 nginx 配置有关。
这是我的设置:
docker
文件中,我暴露了端口8889(这是我的套接字网关端口)EXPOSE 8889
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 模块系统。
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.");
}
});
}, []);
...
}
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 和其他一些东西但无济于事。
这几天我一直在用头撞键盘,试图解决这个问题。任何帮助将不胜感激。
假设容器之间相互链接并连接,并且您可以访问两者。
基于您的配置:‘ proxy_pass http://127.0.0.1:8889/;’您正在尝试连接到 nginx 容器的本地主机,这里您应该使用另一个容器的 IP 或其别名(哈希)