# 持久化

了解如何通过 24/7 始终在线部署来管理持久世界，基于 [私有舰队](/zh/learn/bian-pai/si-you-jian-dui.md).

许多类型（MMO、沙盒、社交游戏）利用持久世界，让玩家：

* 结识并与新朋友社交；培育自发形成的玩家社区，
* 探索一个充满由玩家放置的用户生成内容的生动开放世界，
* 与大型团队或整个公会进行持续数小时的史诗级突袭战斗。

探索以下策略，以 **尽可能提供最佳玩家体验，将成本控制在可接受范围内，并消除因宕机或回滚带来的玩家挫败感**。通过引入为游戏开发者便于使用而打包的边缘计算优势，增强传统服务器模型。

## ✔️ 准备工作

要实现持久、不中断的 24/7 始终在线部署：

* [使用我们的 API 创建一个新的（或更新现有的）应用版本](/zh/docs/api/ban-ben-kong-zhi.md#post-v1-app-app_name-version),
  * 指定 `"max_duration": -1`  以防止在 24 小时后自动终止，
* 使用 [私有舰队部署 API](/zh/docs/api/zhuan-yong-fu-wu-qi.md#post-private-fleets-deploy) 以启动 [待命服务器](/zh/learn/bian-pai/deployments.md#regional-standby) 使用 [持久化](/zh/learn/bian-pai/chi-jiu-hua.md).
  * 可在虚拟机（性能）或裸机（Overdrive）规格之间进行选择。

{% hint style="warning" %}
**测试你的服务器扩缩容和** [**终止流程**](https://docs.edgegap.com/zh/learn/bian-pai/pages/5e7e2169ca3822647d4607dfc1d3487ebcc0836c#id-5.-deployment-stopped) **以验证你的成本控制的可靠性。存储在内存中的服务器状态在部署停止后将丢失，参见** [#configuration-and-state](#configuration-and-state "mention").
{% endhint %}

## 🔑 服务器所有权

探索现代与传统所有权模型的优缺点，并加入边缘计算视角。

### 工作室托管

服务器托管传统上由工作室管理，托管成本由游戏收入承担。

👍 **优点**

* 透明的产品定价——托管成本由玩家的许可/订阅费用覆盖，
* 较强的客户端/服务器兼容性，客户端、服务和扩缩容之间松耦合，
* 由于服务器的闭源特性，对作弊和逆向工程更具韧性。

👎 **缺点**

* 为确保服务器完整性和稳定性，对社区模组支持有限。

### 社区服务器

让玩家托管并资助自己的服务器，摆脱对第三方租赁服务的需求。让收入通过你的工作室而不是缺乏对最终用户体验质量洞察的第三方流转。

👍 **优点**

* 通过精选的模组列表增强模组支持 [应用与版本](/zh/learn/bian-pai/application-and-versions.md),
* 由于与社区更紧密的协作，玩家反馈循环得到改善，
* 由于由玩家承担托管成本，财务风险降低。

👎 **缺点**

* 工作室需要更多运营工作——处理玩家请求并收款，
* 由于模组版本数量增加，客户端/服务器兼容性更弱，
* 由于代码库分散且可能被逆向工程，更容易受到作弊者影响。

## 🥛 容量与扩缩容

学习优化服务器可用性、托管成本和服务质量的高级技术。

### 容量

**部署不会跟踪或管理活跃玩家连接** 在你 [/pages/5e7e2169ca3822647d4607dfc1d3487ebcc0836c#id-1.-start-a-deployment](https://docs.edgegap.com/zh/learn/bian-pai/pages/5e7e2169ca3822647d4607dfc1d3487ebcc0836c#id-1.-start-a-deployment "mention") 以便让你拥有绝对控制权和自由来实现任何设计。

实现容量管理以确保你的服务器：

* 最大化成本节省 - [基准测试](/zh/learn/bian-pai/deployments.md#container-metrics) 并高效利用服务器资源，
* 提供流畅游戏体验——防止过多并发玩家导致服务器过载，
* 通过避免崩溃带来的差评——捕获并处理意外异常。

为确保高效的服务器容量管理：

* 如果 [与游戏服务器匹配的玩家](/zh/learn/pei-dui/matchmaker-in-depth.md#player-tickets) 在几秒内未连接，则释放玩家槽位，
* 频繁从客户端向服务器发送最小心跳消息，以跟踪活动，
* 如果几秒内未检测到活动，则断开客户端并释放玩家槽位，
* 防止玩家被加入到容量已满且没有可用玩家槽位的服务器中。

{% hint style="success" %}
参见 [服务器浏览器](/zh/learn/fu-wu-qi-liu-lan-qi.md) 用于通过我们的托管服务实现自动容量处理。
{% endhint %}

### 扩容

**扩展持久服务器并不需要“猜测”** 区域流量或服务器成本。预留 [私有舰队](/zh/learn/bian-pai/si-you-jian-dui.md) 容量用于 低潮[^1] 并在意外高峰时自动溢出到云端。

实现服务器扩缩容策略以：

* 支持大规模托管，同时谨慎防范滥用，
* 通过减少闲置待命服务器来最小化浪费的服务器成本，
* 通过快速响应增加的玩家需求来防止排队时间过长。

<figure><img src="/files/80451f0bf3ec4d6a3239a4f3bb5d75f970e134e9" alt=""><figcaption><p>自动扩缩容参考架构</p></figcaption></figure>

#### 集成要点

1. 客户端集成 Scaling Authority - [配对](/zh/learn/pei-dui.md), [服务器浏览器](/zh/learn/fu-wu-qi-liu-lan-qi.md)，或一个自定义解决方案。
   1. 发现其他玩家，在运行中的服务器中预留容量，或在需要时请求新的服务器。
2. Scaling Authority 分配运行中的服务器或启动新服务器来为玩家提供服务。
3. 服务器实时通知 Scaling Authority 服务器启动/停止以及玩家连接变更。
   1. Scaling Authority 删除（过期）无响应（崩溃）服务器的过时记录。
4. 客户端直接与服务器连接并建立游戏会话，然后进入游戏。

**我们强烈建议基于连接数而不是物理负载进行扩缩容** （CPU 和内存），因为物理负载的瞬时波动可能导致不可预测的可用性。

### 缩容

高效的缩容策略是优化成本的关键，但 [关闭服务器](/zh/docs/api/zhuan-yong-fu-wu-qi.md#v1-self-stop-request_id-access_point_id) 若不谨慎，可能会对玩家体验产生负面影响。 **在发布前请考虑这些因素并测试更改：**

**你对玩家活动/断开连接的检测是否可靠？**

* 没有输入是否可靠地表示玩家不活跃？玩家经常使用机器人、宏以及其他技术来伪造活动并保持连接，以避免排队时间。
* 活跃玩家经常执行的、难以伪造的操作有哪些？
* 使用机器人或宏是一个问题还是一项功能，针对 [#studio-hosting](#studio-hosting "mention") 服务器？

**关闭服务器是否容易且能快速回滚（重新扩容）？**

* 一旦达到 [/pages/5e7e2169ca3822647d4607dfc1d3487ebcc0836c#id-3.-deployment-ready](https://docs.edgegap.com/zh/learn/bian-pai/pages/5e7e2169ca3822647d4607dfc1d3487ebcc0836c#id-3.-deployment-ready "mention")，你的服务器可能需要额外时间来执行引擎初始化和 [#state-management](#state-management "mention") （状态恢复）。对于游戏服务，你是否会产生额外的计算或数据传输成本？这段等待时间是否会影响玩家体验？
* 你能否通过加载场景、小型游戏、大厅或其他方式隐藏服务器加载？

**玩家是否绑定到特定的服务器实例，还是可以轻松迁移？**

* 连接到不同服务器会如何影响玩家的账户、购买历史、社交体验、进度、库存以及其他游戏方面？
* 审查你的 [#recovery-objectives](#recovery-objectives "mention") 并确保关键数据不会丢失。
* 实现自动化方法或玩家工具以恢复关键数据。
* 提供人工支持，并就宕机和问题与你的社区沟通。

## 🔎 可发现性

要找到接受新玩家的活跃服务器，请实现一种或多种发现方法：

* 让玩家浏览服务器并从列表中选择 [服务器浏览器](/zh/learn/fu-wu-qi-liu-lan-qi.md).
* 当足够多的玩家加入时启动新游戏 [配对](/zh/learn/pei-dui.md).
  * 将玩家添加到 [使用回填替换现有对局中离开的玩家](/zh/learn/pei-dui/matchmaker-in-depth.md#backfill).
* [实现自定义或第三方游戏后端来发现服务器](/zh/learn/advanced-features/managed-clusters.md#nakama-by-heroic-labs).

## 💭 配置与状态

集成服务以定义初始服务器需求，并管理玩家和服务器状态。

### 配置管理

配置是指 **部署期间传递给服务器的初始数据：**

* [按环境注入的变量](/zh/learn/bian-pai/application-and-versions.md#other-parameters-optional):
  * 例如，客户端/服务器版本兼容性数据，
* [服务器位置](/zh/learn/bian-pai/deployments.md#arbitrium_deployment_location-detailed-information-about-deployment-location), [服务器端口](/zh/learn/bian-pai/deployments.md#arbitrium_ports_mapping-detailed-information-about-your-internal-and-external-ports) 和 [其他服务器信息](/zh/learn/bian-pai/deployments.md#injected-environment-variables),
* [匹配信息](/zh/learn/pei-dui/matchmaker-in-depth.md#injected-environment-variables) 或 [自定义部署变量](/zh/learn/bian-pai/deployments.md#custom-variables),
* 第三方集成参数、密钥和机密。

{% hint style="info" %}
**配置是不可变的** - 它在服务器启动后只读取一次，之后不会更改。
{% endhint %}

### 状态管理

状态是指描述以下内容的数据： **一系列先前玩家操作和服务器事件的结果：**

* 玩家连接、玩家控制的状态变化（例如 [Pawn](https://dev.epicgames.com/documentation/en-us/unreal-engine/pawn-in-unreal-engine)),
* 与关卡/场景中包含对象相关的更改（例如 [Actor](https://dev.epicgames.com/documentation/en-us/unreal-engine/actors-in-unreal-engine), [游戏对象](https://docs.unity3d.com/6000.0/Documentation/Manual/GameObjects.html)),
* 与以下内容相关的更改 [游戏模式](https://dev.epicgames.com/documentation/en-us/unreal-engine/game-mode-and-game-state-in-unreal-engine#gamemodes), [游戏状态](https://dev.epicgames.com/documentation/en-us/unreal-engine/game-mode-and-game-state-in-unreal-engine#gamestate)，或 [游戏场景](https://docs.unity3d.com/6000.0/Documentation/Manual/CreatingScenes.html) 信息。

{% hint style="info" %}
**状态数据会频繁变化。** 客户端仅由服务器权威选择性地更新相关信息。
{% endhint %}

{% hint style="success" %}
**频繁执行状态备份以防止数据丢失** ，以应对意外的客户端或服务器问题：

* 使用第三方服务异步实时进行，例如 [Heroic Labs 的 Nakama](/zh/learn/advanced-features/managed-clusters.md#nakama-by-heroic-labs),
* 在客户端/服务器启动或关闭时，以反序列化的状态文件形式存储在 [云对象存储中](https://www.linode.com/products/object-storage/).
  {% endhint %}

游戏对象通常会指定一个拥有者来控制它们，这个拥有者可以是服务器或玩家。&#x20;

#### 服务器拥有对象

服务器拥有的对象只能由服务器操作。已连接的玩家对服务器拥有的对象具有有限的读取权限。服务器拥有的对象通常不会与其他服务器共享。

{% hint style="success" %}
服务器拥有的对象可以在 **服务器意外崩溃时由替代服务器加载**。使用 [部署 ID](/zh/learn/bian-pai/deployments.md#basic-information) 在首次启动时标识你的新保存文件，并存储服务器拥有对象的状态。
{% endhint %}

#### 玩家拥有对象

玩家拥有的对象可由玩家和服务器双方操作。将持久对象的所有权分配给玩家，可使之后迁移到其他服务器更加容易。

{% hint style="success" %}
**在玩家设备或游戏后端中备份玩家拥有对象的状态** 在游戏会话之间。
{% endhint %}

{% hint style="info" %}
通过使用服务器权威验证更改来防止作弊。权威和所有权可以分离。
{% endhint %}

### 恢复目标

在出现问题时，某些类别的数据可能对数据丢失更敏感，例如：

* 账户、订阅、购买和微交易数据 - **关键**,
* 进度、成就、排行榜和库存数据 - **重要**,
* 作弊检测、审核、性能和错误跟踪数据 - **重要**,
* 玩家行为、社交、聊天数据 - **低重要性**.

{% hint style="success" %}
**实现从独立交易历史来源恢复购买** 以获得最佳体验。
{% endhint %}

我们强烈建议你的团队内部讨论以下内容：

* 你的游戏客户端和服务器处理的数据类别，
* 每个类别对你的业务和玩家的重要性与敏感性，
* 恢复点目标（RPO）——在造成严重损害前可接受的数据丢失量，
* 恢复时间目标（RTO）——在造成严重损害前可接受的停机时长。

## 👀 可观测性

长时间运行的持久服务器带来了新的可观测性挑战，尤其是在监控、日志和错误追踪中检测异常。

我们 **强烈建议为服务器重启设置告警** 以提高对问题的可见性。

我们的 [端点存储](/zh/docs/endpoint-storage.md) **日志集成** **仅传输日志** **在** [/pages/5e7e2169ca3822647d4607dfc1d3487ebcc0836c#id-5.-deployment-stopped](https://docs.edgegap.com/zh/learn/bian-pai/pages/5e7e2169ca3822647d4607dfc1d3487ebcc0836c#id-5.-deployment-stopped "mention")之后，添加自定义日志和错误追踪（例如 [Sentry](https://sentry.io/welcome/)）以排查部分故障和错误。

{% hint style="success" %}
考虑为具有可预测流量模式的游戏预留 [私有舰队](/zh/learn/bian-pai/si-you-jian-dui.md) 待命容量。
{% endhint %}

[^1]: 白天最低 CCU


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.edgegap.com/zh/learn/bian-pai/chi-jiu-hua.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
