> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 调用 XBOX 服务的最佳实践

> 使用 XSAPI 或 REST 调用 XBOX Live 服务的指南，涵盖幂等和非幂等端点以及网络故障的正确重试逻辑。

XBOX 服务可以通过两种主要方式调用：使用 XBOX Services API (XSAPI)，或直接调用 REST 端点。
无论您的代码如何调用 XBOX 服务，都必须具有正确的调用模式和重试逻辑。

要了解如何编写正确的重试逻辑，有必要了解两种类型的 REST 端点：**幂等**和**非幂等**。
下面对这些进行了描述。

## 非幂等端点

在重复调用时具有副作用的 HTTP 方法被视为**非幂等**。
这意味着如果客户端调用端点并发生网络超时，重试该方法是不安全的，因为资源可能已被更新，但网络无法通知调用方它已成功。

出错时，客户端必须首先查询以查看调用是否成功，而不是重试。
只有当调用不成功时，才应重试。

在 XBOX Services API 中，某些 API 在内部被标记为调用非幂等端点。
这意味着如果在调用这些端点时发生失败，API 将不会自动重试该端点。

非幂等 API 的完整列表为：

* [XblMatchmakingCreateMatchTicketAsync](/reference/live/xsapi-c/matchmaking_c/functions/xblmatchmakingcreatematchticketasync)

* [XblMultiplayerWriteSessionAsync](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayerwritesessionasync)

* [XblMultiplayerWriteSessionByHandleAsync](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayerwritesessionbyhandleasync)

* [XblMultiplayerSendInvitesAsync](/reference/live/xsapi-c/multiplayer_c/functions/xblmultiplayersendinvitesasync)

* [XblSocialSubmitReputationFeedbackAsync](/reference/live/xsapi-c/social_c/functions/xblsocialsubmitreputationfeedbackasync)

* [XblSocialSubmitBatchReputationFeedbackAsync](/reference/live/xsapi-c/social_c/functions/xblsocialsubmitbatchreputationfeedbackasync)

## 幂等方法

另一方面，**幂等** HTTP 方法不会留下副作用。
这反过来意味着它们可以安全地重试。
在 XBOX Services API 中，所有幂等方法在某些条件下都会自动重试。

幂等 API 的完整列表是上面未列为非幂等的所有 API。

## 重试逻辑最佳实践

对于幂等调用，应自动重试以下情况：

* 所有网络错误
* 401：未授权
* 408：请求超时
* 429：请求过多
* 500：内部错误
* 502：错误网关
* 503：服务不可用
* 504：网关超时

在 UWP 上，401：未授权被特殊处理。
此值表示 XBOX 服务身份验证令牌已过期，因此 XBOX Services API 调用操作系统刷新令牌，然后作为单次重试执行。

执行重试时，最佳实践是在达到 "Retry-After" 标头时间之前不调用服务。
XSAPI 现在实现了此最佳实践。
如果任何 API 返回失败 HTTP 状态代码和 "Retry-After" 标头，则在 Retry-After 时间之前对同一 API 的其他调用将立即返回原始错误，而不会命中服务。

重试调用时，最佳实践是执行带有随机抖动的指数退避，以将负载分散到服务。
XSAPI 以默认 2 秒的延迟开始，该延迟通过 [XblContextSettingsSetHttpRetryDelay](/reference/live/xsapi-c/xbox_live_context_settings_c/functions/xblcontextsettingssethttpretrydelay) 进行控制。
这意味着默认情况下每次重试都会进行 2、4 或 8 秒或更长时间的指数退避。它会根据响应时间在当前和下一个退避值之间抖动延迟，以在尝试重试的设备集之间进一步分散负载。

游戏应控制重试调用的时长。
使用 XSAPI，开发者可以通过 [XblContextSettingsSetHttpTimeoutWindow](/reference/live/xsapi-c/xbox_live_context_settings_c/functions/xblcontextsettingssethttptimeoutwindow) 函数直接控制这一点。
默认情况下，这设置为 20 秒。
将其设置为 0 秒将有效地关闭重试逻辑。

### 动态调整内部 HTTP 超时

XSAPI 根据 [XblContextSettingsGetHttpTimeoutWindow](/reference/live/xsapi-c/xbox_live_context_settings_c/functions/xblcontextsettingsgethttptimeoutwindow) 中剩余的时间动态调整内部 HTTP 超时。

内部 HTTP 超时控制操作系统在中止之前执行 HTTP 网络操作的时间。

除非 [XblContextSettingsGetHttpTimeoutWindow](/reference/live/xsapi-c/xbox_live_context_settings_c/functions/xblcontextsettingsgethttptimeoutwindow) 中至少剩余 5 秒，否则不会重试调用，以便为调用完成提供足够合理的时间。
此规则不适用于第一次调用，因此将 [XblContextSettingsSetHttpTimeoutWindow](/reference/live/xsapi-c/xbox_live_context_settings_c/functions/xblcontextsettingssethttptimeoutwindow) 设置为 0 是可以接受的，并且将导致单次调用。

此逻辑的作用是 [XblContextSettingsGetHttpTimeoutWindow](/reference/live/xsapi-c/xbox_live_context_settings_c/functions/xblcontextsettingsgethttptimeoutwindow) 对 API 调用何时返回更具确定性。

如果返回了 "Retry-After" 标头，则在达到 "Retry-After" 时间之前不会进行重试。
如果 "Retry-After" 时间在 [XblContextSettingsGetHttpTimeoutWindow](/reference/live/xsapi-c/xbox_live_context_settings_c/functions/xblcontextsettingsgethttptimeoutwindow) 之后，则调用将在 [XblContextSettingsGetHttpTimeoutWindow](/reference/live/xsapi-c/xbox_live_context_settings_c/functions/xblcontextsettingsgethttptimeoutwindow) 结束时返回。

## 错误处理

游戏开发者应**始终**对**每个**服务调用使用正确的错误处理，他们需要确保正确处理失败的响应。

有许多现实世界的情况可能会导致对 XBOX 服务的请求返回失败代码，例如：

* 网络不可用。例如，设备失去 4G、失去 Wi-Fi 或网络中断。
* 服务负载过高 (503)。
* 服务上发生故障 (500)。
* 向服务发送了太多请求 (429)。
* 写入操作冲突 (412)。例如，多人游戏会话中的另一位玩家先提交了更改。
* 用户已被禁止或没有权限。
* 用户已注销。

正确的错误处理程序对于确保游戏在这些条件下正常运行至关重要。

有关错误处理最佳实践的详细信息，请参阅[错误处理](https://learn.microsoft.com/gaming/gdk/docs/services/archive/services-archive/live-error-handling-nav)。

有关介绍此内容的视频，请参阅 [Xfest 2015 视频](https://aka.ms/xgddl)中名为 *XSAPI: C++, No Exceptions!* 的演讲。

## 最佳调用模式

### 使用批处理请求

某些端点支持将一组请求批处理或聚合到单个调用中。
例如，使用 XBOX 服务的个人资料服务，您可以请求单个用户的个人资料或一组用户的个人资料。

因此，如果您需要一组用户的个人资料，一次针对每个用户个人资料调用端点或 API 将非常低效。

每次调用都会增加大量的身份验证开销。
因此，请一次将您想要获得信息的所有用户传递给 API，以便端点可以同时处理所有用户个人资料并返回单个响应。

### 使用实时活动 (RTA) 服务而不是轮询

最佳实践是使用实时活动 (RTA) 服务而不是定期轮询。
实时活动服务公开了一个 Web 套接字，当目标资源在服务上发生更改时向客户端发送通知。

RTA 服务在状态更改、统计信息更改、多人游戏会话文档更改和社交关系更改时提供通知。

要了解客户端感兴趣的信息，客户端必须首先通过 Web 套接字订阅该项。
这样可以避免轮询服务以检测更改，因为您将在项发生更改时被准确告知。

XSAPI 将 RTA 服务作为一组订阅 API 公开给客户端使用。
这些 API 中的每一个都有相应的 `*ChangedHandler` API，它接受一个回调函数，当项发生更改时将调用该函数。

* XblPresenceSubscribeToDevicePresenceChange
* XblPresenceSubscribeToTitlePresenceChange
* XblUserStatisticsSubscribeToStatisticChange
* XblSocialSubscribeToSocialRelationshipChange

## 使用 XSAPI 客户端管理器

XSAPI 有一组管理器，它们充当缓存和状态机，为某些场景执行所有繁重的工作。

### Social Manager

Social Manager 负责朋友列表和个人资料的所有繁重工作。
Social Manager 使用 RTA 服务保持您的朋友列表、他们的个人资料和他们的状态数据处于最新状态。

Social Manager 公开了一个对游戏引擎非常友好的同步 API。
游戏可以频繁调用 Social Manager API，因为 Social Manager 维护着来自服务的最新信息的内存缓存。

请参阅 [Social Manager](/services/xbox-services/community/social-manager/live-social-manager-nav)。

### Multiplayer Manager

对于多人游戏会话管理，Multiplayer Manager 是传统多人游戏的即插即用解决方案。
Multiplayer Manager API 包括玩家名册和会话管理，处理游戏邀请、加入进行中的游戏、匹配，并可插入到您现有的网络解决方案中。
它执行有关实现传统多人游戏流程的所有繁重工作。

请参阅 [Multiplayer Manager](/services/xbox-services/multiplayer/mpm/live-multiplayer-manager-nav)。

## 限流（细粒度速率限制）

XBOX 服务实施了限流以防止任何单个设备对服务造成极大的负载。
重要的是要知道您的游戏何时被限流。

要确定您的游戏是否被限流，请使用以下任何方法：

* 监视 HTTP 状态代码 429
* 使用调试断言
* 使用 XBOX 服务跟踪分析器工具

下面描述这些方法。

### 监视 HTTP 状态代码 429

您可以使用 Fiddler 并观察是否返回 HTTP 状态代码 429。
JSON 响应将包含有关端点如何被限流的详细信息。

例如：

```json theme={null}
{
  "version":1,
  "currentRequests":13,
  "maxRequests":10,
  "periodInSeconds":120,
  "limitType":"Rate"
}
```

如果您使用 XSAPI，API 将返回 **HTTP\_E\_STATUS\_429\_TOO\_MANY\_REQUESTS** 错误，并将错误消息设置为显示有关 API 如何被限流的详细信息。

### 使用调试断言

使用 XSAPI 时，如果在开发者沙盒中使用游戏的调试版本时调用被限流，它将进行断言以立即让开发者知道发生了限流。
这是为了避免因错误编写的代码而无意中错过 429 限流错误。
如果您希望在不修复有问题的代码的情况下禁用这些断言以继续工作，可以使用 [XblDisableAssertsForXboxLiveThrottlingInDevSandboxes](/reference/live/xsapi-c/xbox_live_global_c/functions/xbldisableassertsforxboxlivethrottlingindevsandboxes) API：

```cpp theme={null}
XblDisableAssertsForXboxLiveThrottlingInDevSandboxes(
    XblConfigSetting::ThisCodeNeedsToBeChanged
);
```

请注意，此 API 不会阻止您的游戏被限流。您的游戏仍将被限流。这只是在使用调试版本时在开发沙盒中禁用断言。

### 使用 XBOX 服务跟踪分析器工具

确定您的游戏是否被限流的另一个选择是记录 XBOX 服务调用的跟踪，然后使用 [XBOX 服务跟踪分析器工具](/tools/tools-services/live-trace-analyzer)分析该跟踪。

要记录跟踪，您可以使用 Fiddler 记录 .SAZ 文件，或者使用 XSAPI 的内置跟踪日志记录。
有关在 XSAPI 中打开跟踪的详细信息，请参阅 XBOX 文章 [XBOX 服务跟踪分析器 (XblTraceAnalyzer.exe)](/tools/tools-services/live-trace-analyzer)。
获得跟踪后，XBOX 服务跟踪分析器工具会在检测到限流调用时向您发出警告。

## XBOX 服务是否可用？

XBOX 服务是一组微服务，公开 XBOX 功能，如个人资料、朋友和状态、统计信息、排行榜、成就、多人游戏和匹配。
没有单个服务器或端点定义 XBOX 服务是否可用。
如果单个服务器出现故障，XBOX 服务的其余微服务在很大程度上是独立的，应该可以运行。

如果单个服务经历暂时中断，重要的是要知道此服务调用对您的游戏是否至关重要。
尝试在网络或服务出现间歇性问题时提供合理的体验。
例如，如果状态服务返回失败，该调用对您的游戏可能并不至关重要。
所以只需向用户报告最后已知的状态，而不是报告 XBOX 网络（也称为 XBOX Live）已关闭。

XBOX 服务遵循"最终一致性"的一致性模型。
这意味着如果没有新的更新，最终对该资源的所有请求将报告最后更新的值。
这意味着在数据传播时，有一小段时间信息是陈旧的。


## Related topics

- [最佳实践](/zh-CN/services/xbox-services/develop/best-practices/index.md)
- [细粒度速率限制](/zh-CN/services/xbox-services/develop/best-practices/live-fine-grained-rate-limiting.md)
- [处理离线游戏的最佳实践](/zh-CN/services/xbox-services/develop/best-practices/live-best-practices-offline-play.md)
- [登录基础和最佳实践](/zh-CN/services/playfab/identity/player-identity/login/login-basics-best-practices.md)
- [快速入门 (Windows) - 调用 PlayFab 服务](/zh-CN/services/playfab/sdks/unified-sdk/quickstart-services.md)
