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

如何在AWS Amplify服务端检测客户端断开连接?游戏场景方案咨询

解决方案:用AWS IoT PubSub实现玩家连接状态检测

首先可以明确说:AWS IoT PubSub完全可以实现你想要的玩家加入/断开检测功能,而且相比之前的定时更新lastSeen方案,体验和成本都会更优。下面我会一步步拆解具体实现思路和细节:

核心思路

利用IoT WebSocket的连接生命周期事件(主动连接/主动断开),结合IoT规则触发Lambda来实时更新DynamoDB中的玩家状态;同时通过IoT的内置断开检测机制,覆盖客户端异常断开的场景(比如崩溃、网络中断)。

具体实现步骤

1. 配置Amplify与IoT PubSub集成

首先在你的Amplify项目中添加IoT PubSub模块,配置对应的IoT端点和权限:

import { PubSub } from 'aws-amplify';
import { AWSIoTProvider } from '@aws-amplify/pubsub/lib/Providers';

// 初始化IoT Provider,替换成你的区域和IoT端点
PubSub.addPluggable(new AWSIoTProvider({
  aws_pubsub_region: 'us-east-1', // 你的AWS区域
  aws_pubsub_endpoint: 'wss://abc123def-ats.iot.us-east-1.amazonaws.com/mqtt', // 从IoT控制台获取的WebSocket端点
}));

2. 客户端处理连接/断开事件

在客户端完成初始化后,主动发布「玩家加入」消息;同时监听页面关闭/刷新事件,主动发布「玩家断开」消息:

// 玩家成功登录/进入游戏时,发布加入事件
async function handlePlayerJoin(playerId) {
  try {
    await PubSub.publish('game/player-status', {
      action: 'joined',
      playerId: playerId,
      timestamp: new Date().toISOString()
    });
    console.log('玩家加入事件已发送');
  } catch (err) {
    console.error('发送加入事件失败:', err);
  }
}

// 监听页面关闭/刷新,主动发送断开事件
window.addEventListener('beforeunload', async (e) => {
  e.preventDefault();
  const currentPlayerId = '你的当前玩家ID';
  await PubSub.publish('game/player-status', {
    action: 'disconnected',
    playerId: currentPlayerId,
    timestamp: new Date().toISOString()
  });
});

3. 后端用IoT规则+Lambda更新DynamoDB

在AWS IoT控制台创建规则,订阅主题game/player-status,触发Lambda函数来更新玩家状态:

  • IoT规则SQL语句:SELECT * FROM 'game/player-status'
  • 触发目标选择Lambda函数,这个函数负责更新DynamoDB:
const AWS = require('aws-sdk');
const docClient = new AWS.DynamoDB.DocumentClient();

exports.handler = async (event) => {
  const { action, playerId, timestamp } = event;
  
  const updateParams = {
    TableName: '你的游戏状态表名',
    Key: { playerId: playerId },
    UpdateExpression: 'SET isOnline = :isOnline, lastActivity = :timestamp',
    ExpressionAttributeValues: {
      ':isOnline': action === 'joined',
      ':timestamp': timestamp
    }
  };
  
  try {
    await docClient.update(updateParams).promise();
    return { statusCode: 200, body: '玩家状态更新成功' };
  } catch (err) {
    console.error('更新DynamoDB失败:', err);
    return { statusCode: 500, body: '更新失败' };
  }
};

4. 覆盖异常断开场景

如果客户端出现崩溃、网络中断等无法主动发送断开消息的情况,可以利用IoT Core的Presence Events:

  • 订阅IoT内置主题$aws/events/presence/disconnected/+(+匹配客户端ID)
  • 创建另一个IoT规则,当收到断开事件时,触发Lambda将对应玩家标记为离线(这里需要将客户端ID和玩家ID做关联,可以在客户端连接时把玩家ID作为客户端ID的一部分,或者在DynamoDB中存储客户端ID与玩家ID的映射)

成本对比

相比之前每30秒调用GraphQL更新lastSeen的方案,这个方案的成本会低很多:

  • IoT Core的费用按连接时长和消息数量计费,普通游戏场景下,玩家连接时长和消息量(仅加入/断开两次)远低于频繁的GraphQL请求
  • 避免了大量无意义的GraphQL API调用,减少了AppSync的费用支出

注意事项

  • 确保IoT政策允许客户端连接、发布/订阅指定主题
  • 客户端ID最好和玩家ID绑定,方便异常断开时准确识别玩家
  • 可以根据游戏需求调整IoT的会话超时时间,优化断开检测的及时性

内容的提问来源于stack exchange,提问作者5nefarious

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:36:31