Google Cloud上Node+Express+Socket.io服务的WebSocket连接失败问题
Google Cloud上Node+Express+Socket.io WebSocket连接被拒问题解决指南
问题场景
页面可正常加载,但WebSocket连接被立即拒绝,怀疑是环境配置或依赖问题导致。
相关代码
server.js
const express = require("express"); const app = express(); const http = require("http"); const server = http.createServer(app); const { Server } = require("socket.io"); const io = new Server(server); const fs = require("fs"); async function getCount() { return new Promise((resolve, reject) => { fs.readFile("count.json", (err, data) => { if (err) { reject(err); } else { const count = JSON.parse(data).count; resolve(count); } }); }); } async function writeCount(count) { const data = { count: count }; return new Promise((resolve, reject) => { fs.writeFile("count.json", JSON.stringify(data), (err) => { if (err) { reject(err); } else { resolve(); } }); }); } app.use(express.static("public")); io.on("connection", (socket) => { socket.on("error", console.error); getCount().then(count => { io.emit("init", count); }).catch(err => { console.log(err); }) socket.on("serversync", (receivedSync) => { console.log("received " + receivedSync); if (receivedSync >= 120) { console.log("not using " + receivedSync); return; } getCount().then(count => { let total = count + parseInt(receivedSync); io.emit("clientsync", total); writeCount(total); }).catch(err => { console.log(err); }) }); }); app.get("/init", (req, res) => { let files = fs.readdirSync("./public/audio"); res.json([files]); }) const PORT = process.env.PORT || 8080; server.listen(PORT, () => { console.log(`Listening on port ${PORT}.`); });
index.html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <script src="https://code.jquery.com/jquery-3.6.0.min.js" crossorigin="anonymous"></script> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Kalam:wght@700&display=swap" rel="stylesheet"> <script src="https://cdn.socket.io/4.5.4/socket.io.min.js"></script> <link rel="stylesheet" href="css/index.css"> </head> <body class="center"> <div> <h1 id="global"></h1> <h2 id="globalText">Global Pikas</h2> </div> <div> <img id="buttonImg" src="images/button.gif" alt="Pika" onclick="onClick()"> </div> <div id="counterDiv"> <h3 id="counter">0</h3> <h4 id="counterText">Times Pika'd</h4> </div> <script src="js/index.js"></script> <script src="js/animator.js"></script> </body> </html>
报错截图

排查与解决步骤
版本兼容性校验
前端用的是4.5.4版本的Socket.io CDN,后端必须安装同大版本的socket.io包,执行命令:npm install socket.io@4.x版本不匹配是WebSocket连接失败的常见原因,无需本地下载替换CDN,只要前后端版本兼容即可。
Google Cloud环境配置调整
- 端口与绑定地址:代码中
server.listen(PORT)默认绑定0.0.0.0,符合Google Cloud要求,无需修改;端口使用process.env.PORT || 8080也正确,平台会自动分配端口。 - 防火墙规则(Compute Engine):如果用Compute Engine,需在VPC防火墙添加规则,允许目标端口(如8080)的TCP流量,来源设为
0.0.0.0/0。 - App Engine会话亲和性:若使用App Engine灵活环境,需在
app.yaml中添加会话亲和性配置,确保WebSocket长连接不被中断:runtime: nodejs env: flex manual_scaling: instances: 1 network: session_affinity: true
- 端口与绑定地址:代码中
前端Socket初始化检查
确认js/index.js中的Socket初始化代码为const socket = io();,因页面由后端提供,相对路径可自动匹配;若配置了错误的绝对URL,会直接导致连接被拒。文件存储替代方案
Google Cloud多数环境(如App Engine)的本地文件系统是临时且可能无写权限,代码中读写count.json可能引发异常,间接影响WebSocket服务。建议替换为Google Cloud Storage或Firestore存储计数数据。
内容的提问来源于stack exchange,提问作者LazyBeast
相关产品推荐
相关产品推荐

