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

如何应对谷歌云功能突发高流量?游戏云存档加载卡顿问题咨询

游戏大版本更新后谷歌云存档拉取卡顿故障排查

问题背景

游戏支持玩家通过谷歌云存储保存游戏进度,近期推送大型内容更新后大量玩家回流,集中拉取个人存档导致流量过载,大量用户卡在存档加载流程,无法读取进度进入游戏。相关佐证材料包括近4天云API控制面板截图、更早的12小时周期云API控制面板截图。

项目基础信息

  • 游戏会在部分玩法节点后台调用云存档功能,为玩家提供多设备进度互通能力
  • 基于Unity 2019.3.9f1开发,游戏服务功能通过资源包Easy Mobile Pro 2.17.3实现
  • 使用的Google Play Games Plugin版本为0.10.12

云服务配置情况

  • OAuth用户类型为External,无法修改
  • OAuth用户上限显示为0/100
  • OAuth速率限制页面的令牌授予速率数据显示,最高平均令牌授予速率为3.33,上限为10000
  • 所有已使用配额均未超出限制,项目配额使用情况如下:
    • 每日查询量使用量为上限的1/10(上限1000000000次)
    • 每100秒查询量使用量为上限的1/2(上限20000次)

云API错误追踪情况

  • 为获取更详细的错误日志,尝试在Google Cloud Platform控制台查找Cloud Logging工具,所有板块均无数据显示:
    • 运维工具Logging为空
    • Cloud Logging API提示“所选时间段无可用数据”
    • Cloud Debugger API提示“所选时间段无可用数据”
  • 能找到的最详细错误信息仅来自Google Drive API的Metrics板块
  • 目前不确定是否遗漏了相关配置,导致无法获取更详细的错误洞察

核心代码逻辑说明

  • 使用EasyMobilePro实现云存档功能,定义了1个SaveGame变量,以及分别适配谷歌和苹果的8个调用,已联系EasyMobile官方支持,对方确认这些调用不可修改且非常稳定,问题不会出在他们的代码上,若我方无问题建议联系谷歌咨询
  • EasyMobile提供的云存档调用共5个:
    • bool GameServices.IsInitialized()
    • void GameServices.OpenWithAutomaticConflictResolution
    • void GameServices.WriteSavedGameData
    • void GameServices.ReadSavedGameData
    • void GameServices.DeleteSavedGame
  • EasyMobile提供的云登录调用共3个:
    • void GameServices.Init()
    • 委托 GameServices.UserLoginSucceeded
    • 委托 GameServices.UserLoginFailed
  • 触发问题的流程:
    • 调用GameService.Init(),用户登录无异常
    • 在LoginSuccess回调中调用自定义函数HandleFirstCloudOpening
  • 核心精简代码如下(已移除大部分错误处理逻辑,可提供完整复杂版本):
//This Method is Called, after the player Pressed "Save/ Load" on the StartScreen
//The button is disabled imidiately (and will be re-enabled if an error/fail happens)
public void TryCallUserLogin() {
    if (!IsLoginInit) {
        EasyMobile.GameServices.UserLoginFailed += HandleLoginFail;
        EasyMobile.GameServices.UserLoginSucceeded += HandleFirstCloudOpening;
        IsLoginInit = true;
    }
    if (!IsGameServiceInitialized) { 
        EasyMobile.GameServices.Init();
    } else { //This "else" is only be called, if the "Init" was successfull, but the player don't have a connected savegame
        HandleFirstCloudOpening();
    }
}
private void HandleLoginFail() {
    //(...) Show ErrorPopup, let the player try to login again
}
private void HandleFirstCloudOpening() {
    if (currentSaveState != CloudSaveState.NONE) {
        CloudStateConflictDebug(CloudSaveState.OPENING);
        return;
    }
    currentSaveState = CloudSaveState.OPENING;
    EasyMobile.GameServices.SavedGames.OpenWithAutomaticConflictResolution(cloudSaveNameReference, UseFirstTimeOpenedSavedGame);
}

private void UseFirstTimeOpenedSavedGame(EasyMobile.SavedGame _savedGame, string _error) {
    currentSaveState = CloudSaveState.NONE;
    if (string.IsNullOrEmpty(_error)) {
        cloudSaveGame = _savedGame;
        ReadDataFromCloud(cloudSaveGame); 
    } else {
        ErrorPopupWithCloseButton("cloud_open", "failed with error: " + _error);
    }
}

private void ReadDataFromCloud(EasyMobile.SavedGame _savedGame) {
    if (_savedGame.IsOpen) {
        currentSaveState = CloudSaveState.LOADING;
        EasyMobile.GameServices.SavedGames.ReadSavedGameData(_savedGame, UseSucessfullLoadedCloudSaveGame);
    } else { //backup function if the fresh-opened savegame is "closed" for some reason (can happen later while "saving" ingame)
        HandleFirstCloudOpening();
    }
}

private void UseSucessfullLoadedCloudSaveGame(EasyMobile.SavedGame _game, byte[] _cloudData, string error) {
    if (!string.IsNullOrEmpty(error)) {
        ErrorPopupWithCloseButton("cloud_read", "Reading saved game data failed: " + error);
        return;
    }
    if (_cloudData.Length > 0) {
        //A function, that converts the saved bytes to my useable Savegame-Data
        //having a "try&catch": if it fails, it useses the callback with the param "null"
        SaveGameToByteConverter.LoadFromBytes<CoreSaveData>(_cloudData, UseSucessfullConvertedSavegameData);
    } else {
        //this will "fail", causing the use of the callback with the param "null"
        SaveGameToByteConverter.LoadFromBytes<CoreSaveData>(null, UseSucessfullConvertedSavegameData);
    }
            
}

private void UseSucessfullConvertedSavegameData(CoreSaveData _convertedSaveGame) {
    //Has a Loaded & normal SaveGame in his cloud
    if (_convertedSaveGame != null) {
        //Loaded Save matches verify-conditions
        if (CheckLoadedSaveIsVerified(_convertedSaveGame)) {
            OverrideGameSaveDatawithLoaded(_convertedSaveGame);
            ReloadCurrentScene();
            return;
        } else { //This happens if the cloud-save doesn't pass my verification-process
            ErrorPopupWithCloseButton("cloud_loadedSave", "Couldn't find a compatible Savegame!");
            return;
        }
    } else { //User uses Cloud-save for the frist Time or has an unusable savegame and gets a "new" (lost his old data)
        TrySaveGameToCloud((bool _saved) => {
            SaveAllGameFilesLocally();
        });
    }
}

当前排查结论

未在业务侧发现任何无法通过重启游戏修复、或未被用户端错误弹窗覆盖的问题。目前的表现类似用户因数量过多被加入队列,需要等待极长时间才能得到响应:部分用户反馈等待2-36小时后可成功读取进度进入游戏,也有部分玩家表示第二天仍然无法进入游戏,疑似access-token有效期仅为1天导致问题复现。

编辑历史:

  • (1)更新第一张控制面板截图,匹配当前的情况
  • (1)补充了云服务相关情况板块内容
  • (1)补充无法获取更详细错误日志的相关说明
  • (2)移除了大部分可直接展示的图片,保留相关内容说明
  • (2)补充了云API错误追踪相关信息板块内容
  • (2)补充了核心代码相关信息板块和可复现示例
  • (2)补充了当前结论板块内容

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 12:06:03