> For the complete documentation index, see [llms.txt](https://docs.edgegap.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.edgegap.com/zh/learn/server-browser.md).

# Server Browser

快速上手 Server Browser，并探索适用于各种类型的示例场景。

Server Browser 是一项托管服务，用于 [部署](/zh/learn/bian-pai/deployments.md#match-bound) 和 [持久化](/zh/learn/bian-pai/chi-jiu-hua.md) 服务器：

* **帮助玩家搜索并加入合适的服务器** 基于容量、延迟或游戏参数；
* **预热新服务器** 以大规模服务全球玩家，并避免令人沮丧的排队；
* **简化服务器运维** 包括更新、重启、持久化、网格化等。

{% hint style="success" %}
想要在不允许服务器选择的情况下，基于严格规则匹配玩家？可考虑 [匹配](/zh/learn/pi-pei.md).
{% endhint %}

## ✔️ 准备

### 功能与流程

<figure><img src="/files/f0ec3b2982968b574e907b650e12ae4068dce02b" alt=""><figcaption><p>Server Browser：流程与层级</p></figcaption></figure>

Server Browser 提供两项主要功能：

[#start-browsing](#start-browsing "mention") 与游戏客户端配合，以：

* 发现并找到合适的服务器实例，查看槽位，并预留可用容量。
* 在实例槽位中预留席位，获取连接详情，并连接到服务器。
* 使用以下方式在部署中验证玩家连接 联合身份[^1].
* 更新实例槽位的可用容量和/或元数据，以修改发现条件。

[#automated-scaling](#automated-scaling "mention") （可选）与扩缩容策略配合，以：

* 监控可用的服务器实例、槽位、容量——按区域和/或其他条件。
* 通过预热或即时扩缩容部署服务器，以增加容量。
* 使用针对演示、更新、测试、QA、锦标赛等的特殊策略自动化运维。

{% hint style="info" %}
发布后， **你的服务器浏览器需要全天候运行** 以确保全球各地的玩家都能加入服务器。
{% endhint %}

## ▶️ 开始浏览

了解服务器/玩家生命周期及其职责，以确保高效使用服务器。

### 验证

Server Browser 会自动生成两类令牌：

* **服务器令牌** - 用于 [服务器 API](#server-lifecycle) 方法，可 [作为应用版本变量注入](/zh/learn/bian-pai/application-and-versions.md#injected-variables).
  * 授予对所有 API 方法的访问权限，适合测试、DevOps 或自定义编排。
* **客户端令牌** - 用于 [监控 API 和席位预留 API](#player-lifecycle) 由游戏客户端使用。
  * 我们建议将此令牌存储在第三方密钥存储中，以便更轻松地轮换令牌。

### 发现实例

{% hint style="warning" %}
**新建** [部署](/zh/learn/bian-pai/deployments.md) **必须创建一个新实例** 在初始化时，用于跟踪新增容量。
{% endhint %}

{% hint style="info" %}
参见 [#automated-scaling](#automated-scaling "mention") 以了解扩缩容策略并自动启动部署。
{% endhint %}

**所需信息** 对于每个服务器实例，包括：

* 初始化实例时至少定义一个槽位，
* 服务器连接详情——URL、IP、端口信息和位置。

**可选的自定义元数据参数** 用于玩家筛选、排序和浏览；例如：

* 槽位信息——队伍容量和队伍特定元数据（例如队伍名称），
* 名称和标签——可自定义、唯一、可读且可搜索的标识；
* 兼容性数据——服务器版本或支持的客户端版本；
* 延迟标识——城市和地区标识符，以及分配的 [Ping Beacons](/zh/learn/bian-pai/ping-beacons.md) 详情；
* 游戏参数——关卡/场景/地图、游戏模式、难度、所用模组；
* 以及任何其他自定义参数，帮助玩家筛选并找到合适的服务器。

{% hint style="info" %}
以上元数据参数仅为示例，你可以根据需要定义任意数量的参数。
{% endhint %}

{% hint style="success" %}
要序列化嵌套对象，可尝试将其访问路径编码到键中，例如 `"object.child.property"`.
{% endhint %}

服务器可以 **随时更新实例或槽位元数据** 以修改其可发现性条件。更新元数据时，所有索引键都必须提供有效值（即使未修改）。

**服务器实例必须定期发送保活心跳** 以验证其持续可用性，并防止玩家加入已崩溃或离线的服务器。在配置的过期时间内未收到心跳，将自动删除实例及任何待处理的席位预留。

{% hint style="info" %}
参见 [持久化](/zh/learn/bian-pai/chi-jiu-hua.md) 用于管理持久化世界状态，并 [应用与版本](/zh/learn/bian-pai/application-and-versions.md#active-caching) 以加快部署。
{% endhint %}

### 分配容量

实例和槽位容量可通过两种方式分配，单独使用或组合使用：

* [#auto-assigned-reservation](#auto-assigned-reservation "mention") 用于选择通过特定扩缩容策略启动的服务器，
* [#search-and-browse](#search-and-browse "mention") 让玩家定义筛选条件并浏览可选的合适服务器。

{% hint style="success" %}
我们建议从 [#auto-assigned-reservation](#auto-assigned-reservation "mention") 作为更简单的选项开始。
{% endhint %}

#### 自动分配预留

{% hint style="info" %}
如果你希望 **自动选择服务器**，基于区域容量。
{% endhint %}

玩家可以创建自动分配的预留，只需提供玩家 ID 和扩缩容策略名称。Server Browser 会自动找到一个具有足够可加入容量的槽位的实例并预留席位，并立即返回实例连接详情。

如果没有适合此预留的实例槽位，则响应：

* **状态码指示该策略是否正在扩容** 并将增加更多容量，
* **标头 `Retry-After`  指示重试前的等待时间（秒）**，如果可重试。

预留完成后，你可以跳到 [#connect-to-server](#connect-to-server "mention").

#### 搜索与浏览

{% hint style="info" %}
如果你希望 **向用户显示服务器列表并允许自定义预留**.
{% endhint %}

玩家可以列出服务器实例并 [对结果进行分页浏览](#pagination) 以找到他们想加入的服务器。

实例和槽位可通过内置参数或 [索引元数据](#configuration):

<table><thead><tr><th width="400">属性</th><th width="140">数据类型</th><th width="105">实例</th><th width="105">槽位</th></tr></thead><tbody><tr><td><code>request_id</code></td><td><code>字符串</code></td><td>✅</td><td>❌</td></tr><tr><td><code>total_joinable_seats</code>, <code>total_available_seats</code></td><td><code>整数</code></td><td>✅</td><td>❌</td></tr><tr><td><code>名称</code></td><td><code>字符串</code></td><td>❌</td><td>✅</td></tr><tr><td><code>可用席位</code>, <code>已预留席位</code></td><td><code>整数</code></td><td>❌</td><td>✅</td></tr><tr><td><code>created_at</code>, <code>updated_at</code></td><td><code>字符串</code></td><td>✅</td><td>✅</td></tr><tr><td><code>metadata.{index}</code> （自定义）</td><td><code>字符串</code>, <code>整数</code>, <code>浮点数</code>, <code>布尔值</code></td><td>✅</td><td>✅</td></tr></tbody></table>

可用的筛选运算符取决于被筛选属性的数据类型：

<table><thead><tr><th width="125">参数</th><th width="135">运算符</th><th>示例筛选器（基于简单示例）</th></tr></thead><tbody><tr><td><code>字符串</code></td><td><p><a data-footnote-ref href="#user-content-fn-2"><code>eq</code></a>  或 <a data-footnote-ref href="#user-content-fn-3"><code>ne</code></a> 或 </p><p><a data-footnote-ref href="#user-content-fn-4"><code>lt</code></a>  或 <a data-footnote-ref href="#user-content-fn-5"><code>le</code></a> 或 </p><p><a data-footnote-ref href="#user-content-fn-6"><code>gt</code></a>  或 <a data-footnote-ref href="#user-content-fn-7"><code>ge</code></a>  或<br><code>包含</code></p></td><td><pre><code>?$filter=metadata.custom_name 包含 'my game'
并且 metadata.server_version le '1.1.0'
并且 metadata.server_version ge '1.0.0'
&#x26;$order=metadata.custom_name asc
</code></pre></td></tr><tr><td><code>整数</code>, <code>浮点数</code></td><td><p><a data-footnote-ref href="#user-content-fn-2"><code>eq</code></a>  或 <a data-footnote-ref href="#user-content-fn-3"><code>ne</code></a> 或 </p><p><a data-footnote-ref href="#user-content-fn-4"><code>lt</code></a>  或 <a data-footnote-ref href="#user-content-fn-5"><code>le</code></a> 或 </p><p><a data-footnote-ref href="#user-content-fn-6"><code>gt</code></a>  或 <a data-footnote-ref href="#user-content-fn-7"><code>ge</code></a>  </p></td><td><pre><code>?$filter=metadata.xp_multiplier gt 1.0
&#x26;$order=metadata.xp_multiplier desc
</code></pre></td></tr><tr><td><code>布尔值</code></td><td><a data-footnote-ref href="#user-content-fn-2"><code>eq</code></a>  或 <a data-footnote-ref href="#user-content-fn-3"><code>ne</code></a></td><td><pre><code>?$filter=metadata.allows_new_connections eq true
</code></pre></td></tr></tbody></table>

{% hint style="success" %}
通过按区域和/或城市的元数据筛选，在测量与服务器的延迟前缩小选择范围。
{% endhint %}

{% hint style="info" %}
了解基于游标的 [#pagination](#pagination "mention") 以便让用户获取更多结果。
{% endhint %}

#### 预留席位

在加入服务器之前，需要进行席位预留，以确保实例提供足够的可用容量。预留可以包括一组玩家或单个玩家。

联合身份：玩家必须在预留中提供唯一的第三方玩家 ID。一旦他们发送相同的 ID [#connect-to-server](#connect-to-server "mention") ，服务器即可验证其身份。

预留成功后（[200 OK](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/200)），玩家应立即尝试连接。待处理的 **预留会在 30 秒后过期（可配置），除非已确认** 由你的服务器确认。

**超过槽位可加入席位容量的预留将被自动拒绝** ([409 Conflict](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/409)）。可加入席位是尚未被其他玩家预留的任何可用席位。

{% hint style="info" %}
服务器可强制更改任何槽位的容量，并添加、删除或更新任意槽位。 **如果任何待处理预留超过新的槽位可用容量，则该槽位的所有预留都将被移除。**
{% endhint %}

### 连接到服务器

一旦玩家找到合适的实例，他们 **从中获取所需的连接详情** （URL 或 IP， [外部端口](/zh/learn/bian-pai/application-and-versions.md#port-mapping)）。一旦完成席位预留， **玩家即可连接到你的部署中的游戏服务器，并传递其玩家 ID**.

{% tabs %}
{% tab title="Unreal Engine" %}
要 **从 PIE（编辑器）连接** 在开发和测试期间，按波浪号键 `~`  并输入 `open {URL}:{port}` 并等待编辑器加载地图。

{% hint style="success" %}
如果连接失败或出现黑屏，请查阅我们的 [故障排除指南](/zh/unreal-engine.md#troubleshooting-and-faq-1).
{% endhint %}
{% endtab %}

{% tab title="Unity" %}
要 **连接你的 Unity 编辑器** 或 **游戏客户端** 到你的云端部署中，请输入：

* **部署** **URL** 指向服务器 IP，通常在 `NetworkManager`  组件中。
* **外部端口** 映射到 [服务器的内部监听端口](https://docs.edgegap.com/learn/advanced-features/application-and-versions#port-mapping)，通常在 Transport 组件中。

{% hint style="success" %}
如果连接超时或有其他问题，请查阅我们的 [故障排除指南](/zh/unity.md#troubleshooting-and-faq-4).
{% endhint %}
{% endtab %}
{% endtabs %}

要验证新连接， **你的服务器必须发送批量预留确认** 请求，携带所有新玩家的 ID，并在确认响应中接收信息：

* 将已接受的玩家预留分配到其首选槽位，
* 将已过期的玩家预留分配到其首选槽位，
* 未知玩家 ID 列表。

你的 **服务器可以决定如何处理每一组玩家** 以及是否允许或踢出/封禁过期或被拒绝的用户。每个 **实例的槽位都必须立即更新为新的可用席位数量** 以确保未来的预留不会超过槽位容量。

### 放弃服务器

当玩家离开时，你的服务器必须增加所分配槽位的可用席位容量。

{% hint style="success" %}
如果你的游戏设计允许重连期，服务器可以在更新槽位之前等待。
{% endhint %}

了解 [持久化](/zh/learn/bian-pai/chi-jiu-hua.md#recovery-objectives) 以防止令人沮丧的持久服务器回滚。

## 🚀 自动扩缩容

Server Browser 兼容多种不同的自动扩缩容方法：

* **预热方法** - 严格通过 Server Browser 扩缩容策略启动服务器，
* **即时方法** - 通过……启动 [匹配](/zh/learn/pi-pei.md) 和 [通过 Server Browser 填充](#allocate-capacity),
* **自定义自动扩缩器** - 通过自定义游戏后端启动，并 [通过 Server Browser 填充](#allocate-capacity).

以下指南将重点介绍 **使用扩缩容策略进行预热** 作为主要方法。

{% hint style="success" %}
了解如何在 [Unreal Engine](/zh/unreal-engine.md#stop-deployments), [Unity](/zh/unity.md#stop-deployments)，或 [通过 API](/zh/docs/api/zhuan-yong-fu-wu-qi.md#delete-v1-self-stop-request_id-access_point_id) 以可靠地管理生命周期。
{% endhint %}

### 监控容量

扩缩容策略会持续刷新你的服务器实例列表（已发现的部署），并每隔 [`monitoring_interval`](#user-content-fn-8)[^8] 。每个策略都需要使用相同的 [筛选语法](#search-and-browse) 与玩家搜索实例时相同——按区域、容量或其他条件。

你配置的 [`minimum_active_instances`](#user-content-fn-9)[^9]  数量可被视为以下之一：

* **固定容量** 你希望始终保持运行的部署数量，
* **预热待机** 部署缓冲，以隐藏初始化延迟。

#### 固定容量

为以下类型的游戏保持固定数量的活动服务器： [持久化](/zh/learn/bian-pai/chi-jiu-hua.md)，尤其是当这类游戏允许玩家自行配置 [持久化](/zh/learn/bian-pai/chi-jiu-hua.md#community-servers).

这种策略配置有时也用于质量保证、锦标赛、封闭 Alpha、发行商演示，或其他各类有限容量的活动和运维。

{% hint style="info" %}
扩缩容策略可帮助你在运行时自动重启并回收崩溃的服务器。
{% endhint %}

#### 预热待机

如果符合以下情况，可在玩家需求到来之前启动服务器：

* 你正在发布重大版本，并预计在短时间内大量玩家涌入，
* 或者服务器初始化需要超过 30 秒（不包括部署时间[^10]),
* 或者游戏实现了需要分层或循环网络依赖的网格化策略。

### 部署服务器

当受监控的服务器实例数量*s* 降至配置的活动实例最小值以下。所有部署都会立即发起请求，并在每个监控间隔后无限重试，直到 [`deployment_registration_period`](#user-content-fn-8)[^8]  已过去。

{% hint style="warning" %}
请确认新部署 [会自动发现并创建实例](#discover-instance) 正确匹配你的策略筛选条件，或者 **否则你的策略可能会无限循环并创建大量未使用的部署**!&#x20;
{% endhint %}

策略会使用以下方式启动部署： [私有舰队](/zh/learn/bian-pai/si-you-jian-dui.md) （通过溢出到云端），或直接到云端。

可用参数包括（[参见 API 规范](/zh/docs/api/zhuan-yong-fu-wu-qi.md#private-fleets)):

* [**应用和版本**](/zh/learn/bian-pai/application-and-versions.md) - 构建版本、资源和其他编排参数，
* **用户** - 一组用于首选的地理坐标 [服务器放置](/zh/learn/bian-pai/deployments.md#regional-standby),
* [**私有主机 ID**](/zh/learn/bian-pai/si-you-jian-dui.md) - 云端可留空，或指定目标区域内的主机，
* [**标签**](/zh/learn/bian-pai/deployments.md#dashboard-monitoring) - 使用策略名称标记，以便后续查找通过此策略启动的部署，
* [**环境变量**](/zh/learn/bian-pai/deployments.md#custom-variables) - 向服务器传递自定义参数和密钥，
* [**Webhook**](/zh/learn/bian-pai/deployments.md#webhooks-and-postbacks) - 将部署生命周期事件通知你的游戏后端（或匹配器），
* [**需要缓存位置**](/zh/learn/bian-pai/application-and-versions.md#active-caching) - 如果你只希望在缓存位置获得更快的部署。

### 示例策略

你可以根据需要测试和修改这些策略。大多数游戏会使用多个策略。

{% tabs %}
{% tab title="🍀 QA 池" %}
一个简单的策略，用于始终保留一台服务器用于测试。

<pre class="language-json" data-title=""><code class="lang-json">{
  "name": "sb-qa-pool",
<strong>  <a data-footnote-ref href="#user-content-fn-11">"filter"</a>: "metadata.policy_name eq 'sb-qa-pool'",
</strong>  "deployment_request": {
    "private_host_ids": [],
    "application": <a data-footnote-ref href="#user-content-fn-12">"my-game-server"</a>,
    "version": <a data-footnote-ref href="#user-content-fn-13">"2024.01.30-16.23.00-UTC"</a>,
    "users": [
      {
        "user_type": "geo_coordinates",
        "<a data-footnote-ref href="#user-content-fn-14">用户数据</a>": {
<strong>          "latitude": 41.881832,
</strong><strong>          "longitude": -87.623177
</strong>        }
      }
    ],
<strong>    "tags": ["sb-qa-pool"],
</strong>    "environment_variables": [
      {
<strong>        "key": "SB_SCALING_POLICY_NAME",
</strong><strong>        "value": "sb-qa-pool",
</strong>        "is_hidden": false
      }
    ]
  },
<strong>  "minimum_active_instances": 1
</strong>}
</code></pre>

{% endtab %}

{% tab title="🌡️ 预热" %}
在发布前启动 10 倍部署，以应对需求。每个区域都要复制。

<pre class="language-json" data-title=""><code class="lang-json">{
  "name": "sb-v1.0.0-chicago",
<strong>  <a data-footnote-ref href="#user-content-fn-15">"filter"</a>: "total_joinable_seats gt 0 and metadata.policy_name eq 'sb-v1.0.0-chicago'",
</strong>  "deployment_request": {
    "private_host_ids": [],
    "application": <a data-footnote-ref href="#user-content-fn-12">"my-game-server"</a>,
    "version": <a data-footnote-ref href="#user-content-fn-13">"2024.01.30-16.23.00-UTC"</a>,
    "users": [
      {
        "user_type": "geo_coordinates",
        "<a data-footnote-ref href="#user-content-fn-14">用户数据</a>": {
<strong>          "latitude": 41.881832,
</strong><strong>          "longitude": -87.623177
</strong>        }
      }
    ],
<strong>    "tags": ["sb-v1.0.0-chicago"],
</strong>    "environment_variables": [
      {
<strong>        "key": "SB_SCALING_POLICY_NAME",
</strong><strong>        "value": "sb-v1.0.0-chicago",
</strong>        "is_hidden": false
      }
    ]
  },
<strong>  <a data-footnote-ref href="#user-content-fn-16">"minimum_active_instances"</a>: 10
</strong>}
</code></pre>

{% endtab %}

{% tab title="🔒 MMO" %}
随着可用容量低于阈值，每个区域都会增加部署。

<pre class="language-json" data-title=""><code class="lang-json">{
<strong>  "name": "sb-mmo-chicago",
</strong><strong>  <a data-footnote-ref href="#user-content-fn-17">"filter"</a>: "total_joinable_seats gt 5 and metadata.policy_name eq 'sb-mmo-chicago'",
</strong>  "deployment_request": {
<strong>    <a data-footnote-ref href="#user-content-fn-18">"private_host_ids"</a>: ["alpha-north-america-95fab093"],
</strong>    "application": <a data-footnote-ref href="#user-content-fn-12">"my-game-server"</a>,
    "version": <a data-footnote-ref href="#user-content-fn-13">"2024.01.30-16.23.00-UTC"</a>,
    "users": [
      {
        "user_type": "geo_coordinates",
        "<a data-footnote-ref href="#user-content-fn-14">用户数据</a>": {
<strong>          "latitude": 41.881832,
</strong><strong>          "longitude": -87.623177
</strong>        }
      }
    ],
<strong>    "tags": ["sb-mmo-chicago"],
</strong>    "environment_variables": [
      {
<strong>        "key": "SB_SCALING_POLICY_NAME",
</strong><strong>        "value": "sb-mmo-chicago",
</strong>        "is_hidden": false
      }
    ],
<strong>    <a data-footnote-ref href="#user-content-fn-19">"webhook_on_terminated"</a>: {
</strong>      "url": "https://my-webhook.com"
    }
  },
<strong>  "minimum_active_instances": 3
</strong>}
</code></pre>

{% endtab %}

{% tab title="🔑 社区" %}
每个服务器所有者一个策略，传入用于服务器身份验证的自定义密码。

<pre class="language-json" data-title=""><code class="lang-json">{
<strong>  "name": "sb-owner-jnjnc8mid",
</strong><strong>  <a data-footnote-ref href="#user-content-fn-20">"filter"</a>: "metadata.policy_name eq 'sb-owner-jnjnc8mid'",
</strong>  "deployment_request": {
<strong>    <a data-footnote-ref href="#user-content-fn-18">"private_host_ids"</a>: ["alpha-north-america-95fab093"],
</strong>    "application": <a data-footnote-ref href="#user-content-fn-12">"my-game-server"</a>,
    "version": <a data-footnote-ref href="#user-content-fn-13">"2024.01.30-16.23.00-UTC"</a>,
    "users": [
      {
        "user_type": "geo_coordinates",
        "<a data-footnote-ref href="#user-content-fn-14">用户数据</a>": {
<strong>          "latitude": 41.881832,
</strong><strong>          "longitude": -87.623177
</strong>        }
      }
    ],
<strong>    "tags": ["community", "sb-owner-jnjnc8mid"],
</strong>    "environment_variables": [
      {
<strong>        "key": "SB_SCALING_POLICY_NAME",
</strong><strong>        "value": "sb-owner-jnjnc8mid",
</strong>        "is_hidden": false
      },
      {
<strong>        "key": "SB_SERVER_PASSWORD",
</strong><strong>        "value": "password1234",
</strong>        "is_hidden": false
      }
    ],
<strong>    <a data-footnote-ref href="#user-content-fn-21">"webhook_on_ready"</a>: {
</strong>      "url": "https://my-webhook.com"
    },
<strong>    <a data-footnote-ref href="#user-content-fn-22">"webhook_on_error"</a>: {
</strong>      "url": "https://my-webhook.com"
    },
<strong>    <a data-footnote-ref href="#user-content-fn-19">"webhook_on_terminated"</a>: {
</strong>      "url": "https://my-webhook.com"
    }
  },
  "minimum_active_instances": 1
}
</code></pre>

{% endtab %}

{% tab title="❄️ Mesh 组" %}
每组服务器一个策略。游戏后端启动一个主节点，由其生成副本。每个节点读取注入的 Mesh 组 ID，并搜索其他要联网的节点。

<pre class="language-json" data-title=""><code class="lang-json">{
<strong>  "name": "sb-meshgroup-pqyt8sxcb",
</strong><strong>  <a data-footnote-ref href="#user-content-fn-11">"filter"</a>: "metadata.policy_name eq 'sb-meshgroup-pqyt8sxcb'",
</strong>  "deployment_request": {
    "private_host_ids": [],
    "application": <a data-footnote-ref href="#user-content-fn-12">"my-game-server"</a>,
    "version": <a data-footnote-ref href="#user-content-fn-13">"2024.01.30-16.23.00-UTC"</a>,
    "users": [
      {
        "user_type": "geo_coordinates",
        "<a data-footnote-ref href="#user-content-fn-14">用户数据</a>": {
<strong>          "latitude": 41.881832,
</strong><strong>          "longitude": -87.623177
</strong>        }
      }
    ],
<strong>    "tags": ["sb-meshgroup-pqyt8sxcb"],
</strong>    "environment_variables": [
      {
<strong>        "key": "SB_SCALING_POLICY_NAME",
</strong><strong>        "value": "sb-meshgroup-pqyt8sxcb",
</strong>        "is_hidden": false
      },
      {
<strong>        "key": "SB_MESH_GROUP_ID",
</strong><strong>        "value": "pqyt8sxcb",
</strong>        "is_hidden": false
      }
    ],
<strong>    <a data-footnote-ref href="#user-content-fn-21">"webhook_on_ready"</a>: {
</strong>      "url": "https://my-webhook.com"
    },
<strong>    <a data-footnote-ref href="#user-content-fn-23">"webhook_on_terminated"</a>: {
</strong>      "url": "https://my-webhook.com"
    }
  },
<strong>  <a data-footnote-ref href="#user-content-fn-24">"minimum_active_instances"</a>: 9
</strong>}
</code></pre>

{% endtab %}
{% endtabs %}

## ⚙️ 配置

Server Browser API 是从 JSON 配置生成的，该配置在您创建新的（或快速重启的）Server Browser 时指定。您可以指定服务器和槽位过期时间，以及自定义元数据：

{% tabs %}
{% tab title="🍀 简单示例" %}

<pre class="language-json" data-title="sb-simple-example-v1-0-0.json"><code class="lang-json">{
	"version": "1.0.0",
	"server_instances": {
		"expiration_period": "1m",
		"<a data-footnote-ref href="#user-content-fn-25">索引</a>": {
			"policy_name": "string",
			"name": "string"
		}
	},
	"server_instance_slots": {
		"<a data-footnote-ref href="#user-content-fn-25">索引</a>": {}
	},
	"seat_reservations": {
		"expiration_period": "30s"
	},
	"scaling_policies": {
		"monitoring_interval": "10s",
		"deployment_registration_period": "1m"
	}
}
</code></pre>

{% endtab %}

{% tab title="🎈 社交游戏" %}

<pre class="language-json" data-title="sb-social-example-v1-0-0.json"><code class="lang-json">{
	"version": "1.0.0",
	"server_instances": {
		"expiration_period": "15s",
		"<a data-footnote-ref href="#user-content-fn-25">索引</a>": {
			"policy_name": "string",
			"name": "string",
			"third_party_id": "string",
			"level": "string",
			"mode": "string",
			"difficulty": "string",
			"seed": "string",
			"max_players": "int",
			"app_version": "string",
			"location.city": "string"
		}
	},
	"server_instance_slots": {
		"<a data-footnote-ref href="#user-content-fn-25">索引</a>": {
			"third_party_id": "string",
			"max_players": "int",
			"avg_latency": "int",
			"player_ids": "string"
		}
	},
	"seat_reservations": {
		"expiration_period": "30s"
	},
	"scaling_policies": {
		"monitoring_interval": "10s",
		"deployment_registration_period": "30s"
	}
}
</code></pre>

{% endtab %}

{% tab title="🤝 合作游戏" %}

<pre class="language-json" data-title="sb-cooperative-example-v1-0-0.json"><code class="lang-json">{
	"version": "1.0.0",
	"server_instances": {
		"expiration_period": "15s",
		"<a data-footnote-ref href="#user-content-fn-25">索引</a>": {
			"policy_name": "string",
			"name": "string",
			"third_party_id": "string",
			"level": "string",
			"mode": "string",
			"difficulty": "string",
			"avg_rank": "int",
			"max_players": "int",
			"app_version": "string",
			"tags": "string",
			"match_id": "string",
			"location.city": "string"
		}
	},
	"server_instance_slots": {
		"<a data-footnote-ref href="#user-content-fn-25">索引</a>": {
			"third_party_id": "string",
			"max_players": "int",
			"player_ids": "string"
		}
	},
	"seat_reservations": {
		"expiration_period": "30s"
	},
	"scaling_policies": {
		"monitoring_interval": "10s",
		"deployment_registration_period": "30s"
	}
}
</code></pre>

{% endtab %}

{% tab title="⚔️ 竞技游戏" %}

<pre class="language-json" data-title="sb-competitive-example-v1-0-0.json"><code class="lang-json">{
	"version": "1.0.0",
	"server_instances": {
		"expiration_period": "15s",
		"<a data-footnote-ref href="#user-content-fn-25">索引</a>": {
			"policy_name": "string",
			"name": "string",
			"third_party_id": "string",
			"avg_rank": "int",
			"max_players": "int",
			"is_ranked": "bool",
			"app_version": "string",
			"cpu_frequency": "int",
			"match_id": "string",
			"location.city": "string"
		}
	},
	"server_instance_slots": {
		"<a data-footnote-ref href="#user-content-fn-25">索引</a>": {
			"third_party_id": "string",
			"max_players": "int",
			"avg_rank": "int",
			"avg_latency": "int"
		}
	},
	"seat_reservations": {
		"expiration_period": "30s"
	},
	"scaling_policies": {
		"monitoring_interval": "10s",
		"deployment_registration_period": "15s"
	}
}
</code></pre>

{% endtab %}
{% endtabs %}

{% hint style="info" %}
为了获得最佳性能，请避免为不用于过滤或排序的元数据指定索引。未索引的参数仍然可以通过服务器实例或槽位详情 API 方法进行设置和读取，参见 [#api](#api "mention").
{% endhint %}

## ☁️ 托管集群

Server Browser 由 Edgegap 24/7 全天候便捷托管和管理。

选择最适合您目标的托管方案：

### 私有集群层级

只需点击一下即可升级到私有集群，享受由 Edgegap 团队维护的高可用托管，并为公开发布的游戏提供 24/7 实时支持。

您的实例资源需求取决于以下因素：

* **玩家数量** - 更多玩家会产生更多 API 请求，
* **每位玩家的请求数量** - 更快的重试会增加服务负载并消耗资源，
* **服务器数量** - 更多服务器会导致存储更多数据并产生更多 API 请求，
* **客户端重试回退逻辑** - 使用带抖动的退避重试有助于分散流量突发峰值，
* **平均对局时长** - 会话越短，需要与服务器浏览器交互的频率就越高。

## 📗 API

**建议使用我们的 SDK 来** [**Unreal Engine**](/zh/unreal-engine/developer-tools.md) **或** [**Unity**](/zh/unity/server-browser.md) **通过预构建示例快速上手。**

游戏客户端和专用服务器在其生命周期内会向 Server Browser 发送 API 请求。

{% file src="/files/7d2c918178c58f8dedab23c3bb87a44a7fd8ae8a" %}

将 API 规范导入到 [Scalar API 网页客户端](https://client.scalar.com/workspace/default/request/default) 或 [Swagger 编辑器](https://editor.swagger.io/) 以查看详情。

### 分页

**Server Browser 提供游标分页，以便按特定顺序逐步获取过滤后的数据。** 这种方法要求在每次获取更多结果时发送游标（起始点）和页大小（响应项数量），而不是传统的 limit-offset 分页。

{% hint style="info" %}
结合我们为游戏服务器元数据开发的专有数据库索引系统，游标分页可为过滤高度动态的数据提供快速、一致且灵活的用户体验。
{% endhint %}

我们的目标是让用户在第一页就找到合适的服务器。为了获得最佳体验，我们建议为前几页显示缓存结果，并且仅在用户点击“搜索”时刷新结果。

## 🔖 更新日志

{% hint style="info" %}
**Server Browser 的最新版本是 `1.0.0`** 。请留意 [更新和公告](/zh/docs/release-notes.md).
{% endhint %}

[^1]: 第三方玩家标识符

[^2]: 等于

[^3]: 不等于

[^4]: 小于

[^5]: 小于或等于

[^6]: 大于

[^7]: 大于或等于

[^8]: 参见配置

[^9]: 参见示例策略

[^10]: 使用活跃缓存轻松缩短部署时间

[^11]: * 固定容量
    * 假定实例会通过注入变量在元数据中提供策略名称

[^12]: 替换为你自己的应用名称

[^13]: 替换为你自己的应用版本

[^14]: 芝加哥坐标

[^15]: * 当找到的可加入实例少于 10 个时部署
    * 假定实例会通过注入变量在元数据中提供策略名称

[^16]: 我们预计芝加哥区域至少有 10 次部署

[^17]: * 当找到的可加入座位数不超过 5 的实例少于 3 个时部署
    * 假定实例会通过注入变量在元数据中提供策略名称

[^18]: 如果有可用容量，优先使用私有资源池

[^19]: 服务器重启时通知游戏后端

[^20]: * 不监控容量
    * 假定实例会通过注入变量在元数据中提供策略名称

[^21]: 就绪时通知游戏后端

[^22]: 部署失败时通知游戏后端

[^23]: 停止时通知游戏后端

[^24]: 3x3 网格 = 每个世界 9 台服务器

[^25]: 索引包含用于过滤或排序的自定义元数据参数


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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/server-browser.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.
