You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确实现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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 20:20:05