如何正确实现AWS API Gateway WebSocket心跳并解决502错误?
问题分析与解决方案
1. 触发$default路由和502错误的原因
路由匹配失败
你的WebSocket API pong路由没有正确匹配客户端请求,核心问题是路由选择表达式与请求字段不匹配:
- API Gateway WebSocket默认用
$request.body.action作为路由选择表达式,只有当请求体中的action值和路由的routeKey完全一致时,才会匹配对应路由。 - 如果你的
pong路由routeKey设置为pong,但路由选择表达式被修改过,或者客户端请求格式有问题,就会匹配失败,请求落到$default路由。
Lambda返回格式错误
WebSocket API的Lambda集成不能直接返回{statusCode:200, body:"pong"}:这种格式不符合API Gateway的WebSocket响应规范,会导致网关无法解析,返回502错误。即使不需要给客户端返回消息,Lambda也必须返回符合要求的格式(如空的200响应)。
2. 正确实现WebSocket心跳保活的步骤
步骤1:修正路由配置
确保pong(或ping)路由的设置:
routeKey设为ping(建议和客户端发送的action值一致,逻辑更清晰)- 路由选择表达式保持默认的
$request.body.action - 集成目标绑定到你的Lambda函数
步骤2:修正Lambda函数代码
更新Lambda,要么返回极简成功响应(不需要客户端收到pong),要么用ApiGatewayManagementApi主动发送pong响应:
极简版(仅保活,不返回响应)
exports.handler = async (event) => { console.log("Ping received, connection kept alive"); // 返回空200响应,避免502错误 return { statusCode: 200 }; };
带pong响应版
const AWS = require('aws-sdk'); // 初始化ApiGatewayManagementApi,endpoint为你的WebSocket API域名+阶段 const apigwManagementApi = new AWS.ApiGatewayManagementApi({ endpoint: process.env.API_ENDPOINT // 示例:"xxxx.execute-api.ap-northeast-1.amazonaws.com/Prod" }); exports.handler = async (event) => { const connectionId = event.requestContext.connectionId; console.log("Ping received from:", connectionId); // 向客户端发送pong响应 try { await apigwManagementApi.postToConnection({ ConnectionId: connectionId, Data: JSON.stringify({ action: "pong" }) }).promise(); } catch (err) { console.error("Failed to send pong:", err); // 若连接已断开,可在此添加清理逻辑 } return { statusCode: 200 }; };
注意:需要给Lambda添加
execute-api:ManageConnections权限,允许调用postToConnection接口。
步骤3:优化客户端代码
调整心跳间隔(建议设为5分钟,小于10分钟的网关超时阈值),并增加连接状态判断:
const socket = new WebSocket('wss://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/Prod'); socket.addEventListener('error', (event) => { console.log('WebSocket error: ', event); }); socket.addEventListener('open', (event) => { console.log('Connection opened', event); // 每5分钟发送一次ping const pingInterval = setInterval(() => { if (socket.readyState === WebSocket.OPEN) { socket.send(JSON.stringify({ action: "ping" })); console.log("Ping sent"); } else { clearInterval(pingInterval); console.log("Connection closed, stop ping"); } }, 300000); }); socket.addEventListener('message', (event) => { console.log('Message from server: ', event.data); const data = JSON.parse(event.data); if (data.action === "pong") { console.log("Pong received, connection active"); } });
3. 关键注意事项
- 权限配置:Lambda必须拥有
execute-api:ManageConnections权限,否则调用postToConnection会失败。 - 心跳间隔:必须小于10分钟的网关连接超时时间,建议设为5分钟,避免连接意外断开。
- 路由一致性:客户端发送的
action值必须和路由的routeKey完全匹配,否则会落到$default路由。 - 异步处理:Lambda中必须用
async/await处理postToConnection的异步操作,避免回调导致的未处理错误。
内容的提问来源于stack exchange,提问作者K H
相关产品推荐
相关产品推荐

