亚马逊AWS官方博客
Gamelift 的游戏会话日志可视化方案
Amazon GameLift 可以为基于会话的多人游戏管理云上部署和扩展,如服务器的扩展,游戏会话的放置,玩家匹配等。在游戏运行过程中,我们通常需要根据游戏会话中的日志来定位线上问题。GameLift 提供了远程访问游戏主机方式(https://docs.aws.amazon.com/zh_cn/gamelift/latest/developerguide/fleets-remote-access.html),可以通过SSH登陆服务器查看日志,但当实例较多时,登陆服务器查看日志并不是一种便捷的方法,并且当服务器上的游戏会话结束后,实例可能被自动回收,实例上的日志也随之丢失。本文将以 Amazon Linux2 系统和 Unity 引擎为基础,讨论几种 Gamelift 游戏服务端会话日志可视化方案。
在收集日志之前,我们需要将游戏运行的日志持久化到日志文件中,我们将通过在服务端以 端口+时间戳 的命名方式存储日志文件,然后分别实现通过CloudWatch Agent, FluentBit, 上传S3 等三种方式收集服务端日志并进行可视化分析。在Unity中我们可以通过以下方式生成日志文件:
关于 Unity 与 GameLift 的集成,可以参考 https://docs.aws.amazon.com/gamelift/latest/developerguide/integration-engines-unity-using.html
上述代码中,我们通过 Application.logMessageReceived 扩展 Debug.Log ,添加自定义的 Log 方法,将 json 格式的日志输出到日志文件中,接下来我们将从日志文件中采集日志数据。
方案一:基于 CloudWatchLogs 的日志可视化方案
为了将游戏日志采集到CloudWatch Logs,我们需要在游戏服务器启动的时候,为主机安装Cloud Watch Agent,GameLift 支持运行自定义脚本 (https://docs.aws.amazon.com/zh_cn/gamelift/latest/developerguide/gamelift-build-cli-uploading.html) 在游戏服务器启动时进行环境初始化,因此我们可以利用此方式部署CloudWatchAgent.
1.1 首先我们需要让 GameLift 具备访问 CloudWatch Logs 的权限,GameLift 通过AssumeRole 来访问外部资源(https://docs.amazonaws.cn/gamelift/latest/developerguide/gamelift-sdk-server-resources.html), 我们需要创建该角色,并与GameLift 队组关联,角色需要以下托管权限【CloudWatchAgentServerPolicy】【GameLiftGameServerGroupPolicy】【CloudWatchFullAccess】, 角色信任关系如下:
创建角色可以参考(https://docs.aws.amazon.com/zh_cn/IAM/latest/UserGuide/id_roles_create.html),我们将角色命名为 gamelift-role,创建完成后,在控制台获取角色ARN “arn:aws:iam:::role/gamelift-role”
1.2 创建用于运行 CloudWatch Agent 的配置文件 amazon-cloudwatch-agent.json ,关于 CloudWatch Agent 配置文件的详细配置可以参考(https://docs.aws.amazon.com/zh_cn/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-Configuration-File-Details.html),注意修改配置文件中的 role_arn 和 file_path :
注意,file_path 的统配符路径,每次只能取到最新修改的文件,如果一台服务器多个游戏进程,需要将多个日志文件区分开,并添加到 collect_list 中
1.3 在创建队组时也需要将ARN加入到实例角色ARN中,与队组关联,如下图:
1.4 在 install.sh 中通过脚本安装 CloudWatch Agent 并指定我们创建的配置文件
1.5 将 amazon-cloudwatch-agent.json,install.sh 与游戏打包文件放在同一目录中,通过 upload build, 创建队组,创建session,即可启动游戏应用,启动后我们在Cloud Watch Logs 中可以看到以下效果:
通过 CloudWatch Logs Insight 我们可以实时查询日志:
方案二:基于 Fluentbit + S3 + Athena 的日志可视化方案
通过Fluentbit可以将日志文件中的内容近实时的采集到 S3 中,当我们的游戏日志量较多的时候,S3可以提供更加低廉的存储成本,利用Athena,可以通过 SQL 的形式从海量的 S3 日志文件中查询结果,并以按需的方式计算成本。
2.1 首先需要创建用于存储日志的 S3 存储桶,我们命名为 gamelift-logs,并为 gamelift-role 添加此存储桶的读写权限,IAM Policy 如下:
2.2 准备 Fluent-bit 的配置文件 fluent-bit.conf, 注意修改配置文件中的日志文件路径 Path ,存储日志文件的存储桶 bukcet , 以及 role_arn。为了方便查询,我们通过 Filter 添加 EC2 的元数据信息,包括 az, ec2_instance_id 等信息。
2.3 同样,我们在 install.sh 中安装 fluent-bit 代理
2.4 为了优化查询效率,我们对 S3 中的日志按照天为单位进行了分区( fluent-bit.conf 文件中 s3_key_format ), 在S3中我们可以看到S3中的目录如下:
通过 Amazon Glue 爬取 S3 目录,并可以利用 Athena 快速查询日志数据,Athena 与 Glue 的配置可以参考 https://docs.aws.amazon.com/zh_cn/athena/latest/ug/data-sources-glue.html, 最终日志查询效果如下,我们可以通过SQL的方式实时查询游戏会话的日志:
方案三:Game Session 会话日志上传
以上基于Agent的日志方案将所有会话日志集中收集和管理,在实际的游戏运维过程中,我们可能希望集中分析某个session的日志,我们可以在 game session 结束之前,调用 SDK,将 game session 的日志文件上传到S3中, 在 Unity 中的实现如下:
在游戏会话结束时通过 sessionId 命名日志文件,最终我们可以直接在 S3 中下载每一个 Game Session 的日志
因为我们在日志上传的时候做了目录分区,因此我们也可以通过 Athena 来快速查询分区数据。
此方案在游戏会话结束之后统一收集日志,对游戏本身的性能没有影响,利用S3存储日志文件,节省存储成本。但是无法查询实时日志,只能在游戏结束之后进行分析。
与其他平台的集成
对于 Fluent-bit 也可以支持直接将日志文件收集到 Amazon Opensearch 中,通过在 fluen-bit.conf 文件中增加如下输出即可
对于已经使用 Log Hub (https://www.amazonaws.cn/solutions/log-hub/?nc1=h_ls) 的用户,我们也可以通过将日志上传S3之后,与 LogHub 对接,实现统一的日志管理。https://awslabs.github.io/log-hub/zh/implementation-guide/applications/