如何用WebSocket连接两个独立的Heroku前端与后端应用?
WebSocket连接Heroku上两个独立应用的问题排查
问题描述
我不确定这种架构是否常见,但我想通过WebSocket连接Heroku上的两个独立应用——一个是React前端,另一个是运行在Heroku上的Node应用,用来跑机器人、执行自动化流程之类的操作。需要让两者连通,这样就能从React前端发起需要服务器端处理的请求,比如用SendGrid发邮件。后端不用提供网页服务,只需要和前端做数据通信就行。我现在用的是socket.io,也可以换成ws库。
一开始碰到了CORS错误,调整代码后又出现503错误,再调整之后,前端控制台只显示“websocket connection failed”,没有错误代码。
服务器代码
const express = require('express'); const socket = require('socket.io'); const PORT = process.env.PORT || 3000; const server = express() .listen(PORT, () => console.log(`Listening on ${PORT}`)); const io = socket(server, { cors: { origin: "https://my-client-app.herokuapp.com/", methods: ["GET", "POST"], credentials: true } });
客户端代码
const io = require("socket.io-client"); var socket = io('https://my-server-app.herokuapp.com/', { transports : ['websocket', 'polling'] });
错误信息
websocket.js:58 WebSocket connection to 'wss://my-server-app.herokuapp.com/socket.io/?EIO=4&transport=websocket' failed: doOpen @ websocket.js:58 open @ transport.js:57 open @ socket.js:172 Socket @ socket.js:110 open @ manager.js:137 Manager @ manager.js:65 lookup @ index.js:41 ./src/App.js @ App.js:12 options.factory @ react refresh:6 __webpack_require__ @ bootstrap:24 fn @ hot module replacement:62 ./src/index.js @ App.js:1222 options.factory @ react refresh:6 __webpack_require__ @ bootstrap:24 (anonymous) @ startup:7 (anonymous) @ startup:7
排查和修复步骤
- 修正CORS origin配置:服务器CORS的origin末尾多了斜杠,改成
"https://my-client-app.herokuapp.com"(去掉最后一个/),Heroku的域名匹配会严格校验格式。 - 对齐socket.io版本:确保客户端和服务器端的socket.io版本完全一致,版本不兼容是连接失败的高频原因。
- 调整客户端传输顺序:把transports改成
['polling', 'websocket'],Heroku的反向代理通常需要先通过polling升级到websocket;或者直接去掉transports配置,让socket.io自动选择。 - 添加服务器连接日志:在服务器代码里加入连接监听,方便排查是否有请求到达:
io.on('connection', (socket) => { console.log('用户连接:', socket.id); socket.on('disconnect', () => console.log('用户断开:', socket.id)); }); - 检查Heroku应用状态:
- 用
heroku logs --tail查看服务器应用的实时日志,排查启动错误或请求报错。 - 确认服务器应用没有休眠(Heroku免费版长时间无请求会休眠,首次请求会有延迟)。
- 用
- 备选方案:改用ws库:如果socket.io问题持续,试试原生ws库,配置更简洁:
服务器端:
客户端(React组件中):const express = require('express'); const http = require('http'); const WebSocket = require('ws'); const PORT = process.env.PORT || 3000; const app = express(); const server = http.createServer(app); const wss = new WebSocket.Server({ server }); wss.on('connection', (ws) => { console.log('新WebSocket连接'); ws.on('message', (data) => { console.log('收到消息:', data); // 处理业务逻辑,比如调用SendGrid发邮件 ws.send('请求处理完成'); }); }); server.listen(PORT, () => console.log(`监听端口 ${PORT}`));import { useEffect } from 'react'; function App() { useEffect(() => { const ws = new WebSocket('wss://my-server-app.herokuapp.com'); ws.onopen = () => { console.log('连接成功'); ws.send('前端请求:发送邮件'); }; ws.onmessage = (event) => { console.log('服务器响应:', event.data); }; ws.onerror = (err) => console.error('连接错误:', err); ws.onclose = () => console.log('连接关闭'); return () => ws.close(); }, []); return <div>WebSocket测试</div>; } export default App;
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

