☰
Agones Rust 教程:使用 Rust SDK 构建、定制并部署一个简单 Game Server
2026/10/10 2:24:45 网站建设 项目流程
  • 游戏开发
  • 云原生

【免费下载链接】agones

Dedicated Game Server Hosting and Scaling for Multiplayer Games on Kubernetes

项目地址:https://gitcode.com/gh_mirrors/ag/agones
点击查看免费下载

本文基于 Agones 官方教程,完整演示如何在 Kubernetes 集群上运行、定制并重新部署一个基于 Agones Rust SDK 的简单 Game Server:从直接部署仓库自带的rust-simple示例镜像开始,逐步理解main.rs中 SDK 的每一个关键调用(ready、watch、健康心跳、reserve、shutdown),再到修改健康检查间隔、用多阶段 Dockerfile 构建自定义镜像并观察 Agones 健康控制器将其标记为Unhealthy的全过程,帮助读者掌握 Agones 多语言 SDK 的接入模式与 Game Server 生命周期管理要点。

教程目标

  • 运行一个简单 Game Server,并跟踪其完整生命周期日志;
  • 理解该示例如何使用 Agones Rust SDK(Sdk实例的创建、ready、health_check、watch_gameserver、shutdown等);
  • 构建一个自定义版本的简单 Game Server(调整健康心跳间隔);
  • 在你的集群中运行这个定制后的 Game Server,并理解 Agones 对Unhealthy状态的处理。

前置条件

  1. Docker;
  2. 在 GKE 上安装好 Agones(可参考 创建 GKE 集群文档 中的“创建集群”与“安装 Agones”两节);
  3. kubectl已正确配置;
  4. 本地有一份 Agones 仓库的副本(本仓库);
  5. 一个用于存放 Docker 镜像的镜像仓库,例如 Docker Hub 或 GCR/Artifact Registry。

可选建议:先阅读 创建 Game Server、创建 Game Server Fleet 和 编辑第一个 Game Server 这几个快速入门,并参考 Rust SDK 指南 了解各 SDK 函数的具体语义。


1. 运行预构建的 simple gameserver

在仓库中找到示例声明文件 examples/rust-simple/gameserver.yaml,其核心内容是:

apiVersion: agones.dev/v1 kind: GameServer metadata: # generate a unique name # will need to be created with `kubectl create` generateName: rust-simple- spec: ports: - name: default containerPort: 7654 template: spec: containers: - name: rust-simple image: us-docker.pkg.dev/agones-images/examples/rust-simple-server:0.14 imagePullPolicy: Always

注意两点:使用generateName: rust-simple-让 Agones 自动生成唯一名称(因此必须用kubectl create而不是apply);示例镜像当前版本为0.14,镜像标签与 Makefile 中的version := 0.14保持一致。

运行预构建版本并记下生成的 GameServer 名称(也可以直接用仓库内的examples/rust-simple/gameserver.yaml文件来创建):

kubectl create -f examples/rust-simple/gameserver.yaml GAMESERVER_NAME=$(kubectl get gs -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')

这个示例服务器在做什么

从源码看,examples/rust-simple/src/main.rs 的行为与教程描述一致:

  1. 创建 Agones SDK 实例并连接到 Pod 内的 SDK Server;
  2. 调用sdk.ready()通知 Agones 已准备好接收流量;
  3. 每 10 秒打印一条 “Running for N seconds” 日志;
  4. 运行约 60 秒后调用sdk.shutdown(),GameServer 自动退出。

此外,当前版本的示例还演示了set_label、set_annotation、reserve(预留 5 秒后自动回到Ready)和watch_gameserver(持续打印 GameServer 状态变化)等 SDK 能力。

你可以用下面的命令跟踪这个 GameServer 的完整生命周期:

kubectl logs ${GAMESERVER_NAME} rust-simple -f

预期输出与教程给出的样例类似(当前示例源码中新增的Reserve相关日志行会一并出现):

Rust Game Server has started! Creating SDK instance Setting a label Starting to watch GameServer updates... Health ping sent Setting an annotation Marking server as ready... ...marked Ready Setting as Reserved for 5 seconds ...Reserved Getting GameServer details... GameServer name: rust-simple-txsc6 Running for 0 seconds GameServer Update, name: rust-simple-txsc6 GameServer Update, state: Scheduled GameServer Update, name: rust-simple-txsc6 GameServer Update, state: Scheduled GameServer Update, name: rust-simple-txsc6 GameServer Update, state: RequestReady GameServer Update, name: rust-simple-txsc6 GameServer Update, state: Ready Health ping sent Health ping sent Health ping sent Health ping sent Health ping sent Running for 10 seconds GameServer Update, name: rust-simple-txsc6 GameServer Update, state: Ready ... Shutting down after 60 seconds... ...marked for Shutdown Running for 60 seconds Health ping sent GameServer Update, name: rust-simple-txsc6 GameServer Update, state: Shutdown GameServer Update, name: rust-simple-txsc6 GameServer Update, state: Shutdown ...

如果一切正常,GameServer 会在大约一分钟后自动退出。某些情况下它可能进入Unhealthy状态并被无限重启;如果发生这种情况,可以手动删除它:

kubectl delete gs ${GAMESERVER_NAME}

源码剖析:main.rs与 Rust SDK 的对应关系

main.rs基于tokio多线程运行时(#[tokio::main(flavor = "multi_thread", worker_threads = 4)]),核心调用链如下:

  • 创建 SDK 客户端:agones::Sdk::new(None, None)。查看 sdks/rust/src/sdk.rs 中Sdk::new的实现:端口参数为空时会回退到环境变量AGONES_SDK_GRPC_PORT,再回退到默认端口9357(这正是 Agones 注入到 Pod 的 SDK Server 端口)。随后new_internal使用connect_lazy懒连接,并以 100ms 间隔轮询get_game_server,在 30 秒内完成“握手”——即等待 SDK Server 就绪。因此游戏进程不需要担心与 SDK Server 的启动竞争。
  • 健康心跳:sdk.health_check()返回一个tokio::sync::mpsc::Sender<()>,示例中通过tokio::time::interval(Duration::from_secs(2))每 2 秒向该 channel 发送一个空消息。从 sdks/rust/src/sdk.rs 中health_check的实现可以看到,SDK 内部把收到的每个消息转换为 gRPChealth流式调用的一次 ping(async_stream逐条yield),日志中的 “Health ping sent” 即对应这些消息。
  • Watch GameServer:sdk.watch_gameserver()返回tonic::Streaming<GameServer>,示例中循环调用stream.message(),把每次 GameServer 资源变更的name与state打印出来——这就是日志中大量GameServer Update, state: Scheduled / RequestReady / Ready / Shutdown的来源。
  • 元数据与状态流转:sdk.set_label("test-label", "test-value")、sdk.set_annotation(...)、sdk.ready()、sdk.reserve(Duration::from_secs(5))(预留时长最小粒度为 1 秒)、sdk.get_gameserver()获取当前 GameServer 详情,最后在第 5 次 10 秒循环(即 60 秒处)调用sdk.shutdown()。

任何一步失败都会以非零退出码终止进程,main函数会把run()的错误直接打印并exit(1)。


2. 构建一个定制的 simple gameserver

进入本地仓库的examples/rust-simple目录,打开 src/main.rs,把健康心跳间隔从 2 秒改为 20 秒。教程原文给出的改动是

thread::sleep(Duration::from_secs(20));

对应的是早期基于线程的实现;在当前仓库的 tokio 版本中,等价修改是把健康检查任务里的间隔定时器

let mut interval = tokio::time::interval(Duration::from_secs(2));

改为

let mut interval = tokio::time::interval(Duration::from_secs(20));

然后构建新的 Docker 镜像:

cd examples/rust-simple REPOSITORY=<your-repository> # e.g. gcr.io/agones-images make build-image REPOSITORY=${REPOSITORY}

构建完成后,把镜像推送到你的仓库:

docker push ${REPOSITORY}/rust-simple-server:0.4

(教程原文镜像标签为0.4;以当前仓库 Makefile 为准,构建出的本地标签是rust-simple-server:0.14,docker push时请使用你实际打上的标签。)

构建过程解析:Makefile 与多阶段 Dockerfile

make build-image的完整流程在 examples/rust-simple/Makefile 中定义,关键一步是:

build-image: # Docker does not allow to copy outside files mkdir -p $(project_path)sdk cp -rf $(project_path)../../sdks/rust/* $(project_path)sdk docker build $(project_path) --tag=$(server_tag)

因为 Docker 构建上下文不允许拷贝上下文之外的文件,Makefile 会先把 Rust SDK 源码(sdks/rust)复制进examples/rust-simple/sdk目录,让 Dockerfile 能在上下文内访问它。镜像标签由server_tag := $(REPOSITORY)/rust-simple-server:$(version)生成,不传REPOSITORY时则为本地rust-simple-server:0.14。

Dockerfile 采用两阶段(multi-stage)构建:

FROM rust:1.92.0 as builder RUN useradd -m build RUN apt update && apt install -y protobuf-compiler # SDK COPY sdk /home/builder/agones/sdks/rust # Example COPY src /home/builder/agones/examples/rust-simple/src COPY Cargo.toml /home/builder/agones/examples/rust-simple/ COPY Makefile /home/builder/agones/examples/rust-simple/ WORKDIR /home/builder/agones/examples/rust-simple RUN make build-server FROM debian:trixie RUN useradd -u 1000 -m server COPY --from=builder --chown=server:server /home/builder/agones/examples/rust-simple/target/release/rust-simple /home/server/rust-simple USER 1000 ENTRYPOINT /home/server/rust-simple

即“拉取所有依赖并编译”发生在 builder 阶段(make build-server即cargo build --release,见 Cargo.toml 中agones = { path = "../../sdks/rust" }依赖声明),最终镜像只包含编译产物target/release/rust-simple,以非 root 用户(uid 1000)运行。首次构建需要下载并编译全部依赖,教程特别提示这通常需要数分钟,属正常现象。若使用 Google Cloud Build,可参考 examples/rust-simple/cloudbuild.yaml 中的make push流程。

本地不依赖 Docker 的替代验证方式

如果你已安装 Rust 工具链,也可以按 examples/rust-simple/README.md 的说法直接在本地跑:先在某处启动一个本地 SDK-server(仓库 build 目录提供make run-sdk-conformance-local TIMEOUT=120 TESTS=ready,watch,health,gameserver),然后:

make build # 即 cargo build --release make run # 运行 ./target/release/rust-simple

结束后用make clean清理sdk目录与target目录。


3. 运行定制的 gameserver

现在把新构建的容器部署到 Agones 集群。首先编辑examples/rust-simple/gameserver.yaml,让容器指向你的新镜像:

containers: - name: rust-simple image: $(REPOSITORY)/rust-simple-server:0.4 imagePullPolicy: Always

(记得把标签改成你实际推送的标签。)然后部署:

kubectl create -f gameserver.yaml GAMESERVER_NAME=$(kubectl get gs -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}')

同样跟踪生命周期:

kubectl logs ${GAMESERVER_NAME} rust-simple -f

预期输出类似教程给出的样例:

Rust Game Server has started! Creating SDK instance Setting a label Starting to watch GameServer updates... Health ping sent Setting an annotation Marking server as ready... ...marked Ready Getting GameServer details... GameServer name: rust-simple-z6lz8 Running for 0 seconds GameServer Update, name: rust-simple-z6lz8 GameServer Update, state: Scheduled GameServer Update, name: rust-simple-z6lz8 GameServer Update, state: RequestReady GameServer Update, name: rust-simple-z6lz8 GameServer Update, state: RequestReady GameServer Update, name: rust-simple-z6lz8 GameServer Update, state: Ready Running for 10 seconds GameServer Update, name: rust-simple-z6lz8 GameServer Update, state: Ready GameServer Update, name: rust-simple-z6lz8 GameServer Update, state: Unhealthy Health ping sent Running for 20 seconds Running for 30 seconds Health ping sent Running for 40 seconds GameServer Update, name: rust-simple-z6lz8 GameServer Update, state: Unhealthy Running for 50 seconds Health ping sent Shutting down after 60 seconds... ...marked for Shutdown Running for 60 seconds Running for 70 seconds GameServer Update, name: rust-simple-z6lz8 GameServer Update, state: Unhealthy Health ping sent Running for 80 seconds Running for 90 seconds Health ping sent Rust Game Server finished.

为什么会被标记为Unhealthy

心跳间隔放慢到 20 秒后,GameServer 会被 Agones 自动标记为Unhealthy。原因在于 Agones 的健康检查机制:健康检查默认启用,GameServer 必须以一个短于spec.health.periodSeconds(默认 20 秒)的间隔 ping SDK Server 才能维持健康——详见 健康检查文档。将心跳拉长到与默认值相同的 20 秒后,心跳就可能落在检查周期边界之外,Agones 判定心跳超时,由健康控制器把状态置为Unhealthy。从源码结构看,这一判定发生在 pkg/gameservers/health.go:HealthController监听 Pod 事件,当 GameServer 处于Ready状态且 Pod 被判定为不健康时,会把gs.Status.State更新为GameServerStateUnhealthy并记录事件;Unhealthy状态下容器不会再向外部提供流量。

这也解释了教程第 1 步中的提醒:如果心跳异常导致容器反复重启,restartPolicy(默认Always)会让 Pod 无限重启,需要时手动kubectl delete gs清理。

收尾清理

教程的最后一步是手动删除这个定制的 GameServer:

kubectl delete gs ${GAMESERVER_NAME}

小结

本教程通过rust-simple示例串起了 Agones Rust SDK 的核心用法:

  • Sdk::new自动回退到AGONES_SDK_GRPC_PORT(默认 9357)并在 30 秒内完成与 SDK Server 的握手;
  • ready()/shutdown()驱动 GameServer 在Ready与Shutdown之间流转,reserve(duration)提供临时占用能力;
  • health_check()返回的 mpsc Sender 是心跳的唯一通道,其间隔必须小于periodSeconds(默认 20 秒),否则会触发Unhealthy;
  • watch_gameserver()提供 GameServer 资源变更的 gRPC 流式监听,set_label/set_annotation/get_gameserver则用于读写底层 K8s 资源元数据。

构建侧的关键设施是 Makefile + 多阶段 Dockerfile 的组合:本地只需make build-image REPOSITORY=<your-repository>即可产出最终精简镜像,再用kubectl create -f gameserver.yaml部署验证。更完整的 SDK 函数说明可继续参考 Rust SDK 指南。

  • 游戏开发
  • 云原生

【免费下载链接】agones

Dedicated Game Server Hosting and Scaling for Multiplayer Games on Kubernetes

项目地址:https://gitcode.com/gh_mirrors/ag/agones
点击查看免费下载
上一篇:Go 儒略日计算指南:解析 ncruces/julianday 库的完整 API 与 SQLite 兼容性设计
下一篇:D3KeyHelper终极指南:5分钟掌握暗黑3技能连点器,彻底告别手动疲劳

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询