> ## 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.

# 在本地调试游戏服务器以及与 PlayFab 的集成

> 介绍如何使用 PlayFab Game Server SDK (GSDK) 集成 PlayFab 多人游戏服务器,以及如何验证和调试该集成。

## 概述

PlayFab 多人游戏服务器需要与 [PlayFab Game Server SDK (GSDK)](/services/playfab/multiplayer/servers/integrating-game-servers-with-gsdk) 集成。此外,游戏服务器在 PlayFab Multiplayer 平台上以容器化应用程序的形式运行。

以容器化应用的方式运行,能够在与 Azure 上 PlayFab 平台匹配的环境中本地运行并调试服务器,从而加快开发迭代。本文帮助你验证 PlayFab 游戏服务器是否符合平台要求。

PlayFab 本地调试工具集包括 [LocalMultiplayerAgent](https://github.com/PlayFab/MpsAgent),它向 GSDK 提供模拟响应,并验证你的游戏服务器是否正确集成了 GSDK。借助这些模拟响应,VmAgent 让游戏服务器循环经历其在 PlayFab Multiplayer 平台生命周期中的各种状态。

你可以将此代理配置为将游戏服务器作为容器化应用运行。这样可以验证游戏服务器已打包所有必需依赖项,并在 PlayFab Multiplayer 平台上正常运行。LocalMultiplayerAgent 可以与 Windows 或 Linux 游戏服务器一起使用。

## 基本设置 - Windows

* 将游戏服务器与 GSDK 集成并构建它。有关详细信息,请参阅[将游戏服务器与 PlayFab Game Server SDK (GSDK) 集成](/services/playfab/multiplayer/servers/integrating-game-servers-with-gsdk)。
* 将你的游戏服务器及其依赖项压缩为 zip 存档。要在容器模式下正确运行,zip 存档必须包含容器映像中未包含的所有系统 DLL。有关详细信息,请参阅[确定所需的系统 DLL](/services/playfab/multiplayer/servers/determining-required-dlls)。

<Note>
  请避免这一常见错误 - 不要不小心在 zip 中将一个文件夹嵌套在另一个文件夹*内*。压缩后,请浏览 zip 文件夹并再次确认压缩软件没有添加额外的一层文件层级结构。
</Note>

* 下载[本地调试工具集](https://github.com/PlayFab/MpsAgent/releases)并将其解压到你选择的文件夹中(例如 *C:\PlayFabVmAgent*)。

* 在查看:[LocalMultiplayerAgent MultiplayerSettings.json 生成器](https://github.com/PlayFab/MpsAgent/tree/main/LocalMultiplayerAgent/SettingsJsonGenerator) json 文件时,请阅读以下选项的更多信息。

* 导航到解压后文件夹的位置,并在文本编辑器(例如 [Visual Studio Code](https://code.visualstudio.com/download))中打开 *MultiplayerSettings.json* 文件。更新以下属性:
  * `LocalFilePath` - 先前创建的游戏服务器资产 zip 文件在你工作站上的完整本地路径,例如:*D:\\\MyAmazingGame\\\asset.zip*(请注意,反斜杠需要为 JSON 格式转义)。
  * `StartGameCommand` - 容器内游戏服务器可执行文件的完整路径。例如,如果可执行文件名称为 *mygame.exe*,示例路径为 *C:\\\Assets\\\mygame.exe*。StartGameCommand 的路径在进程模式和容器模式下有所不同。容器的 StartGameCommand 路径是容器或资产文件夹内某个资源的绝对路径。进程的 StartGameCommand 路径是相对路径,工作目录将是指定的第一个资产。
  * `PortMappingsList` - 这些是游戏运行时可用的端口。`NodePort` 是在你工作站上打开的端口,`GamePort.Number` 是游戏服务器在容器中运行时需要绑定的端口。更新 GamePort 部分以匹配游戏服务器监听客户端的协议和端口。如果游戏服务器需要多个端口,请复制/粘贴现有端口配置并递增 `NodePort`,然后更新 `GamePort.Number` 和 `GamePort.Name` 为所需端口。当作为进程运行时,`GamePort.Number` 会被忽略,你的进程应绑定到 NodePort。要同时处理这两种情况,请执行以下操作之一:
    * 将端口设置为相同的值
    * 在运行时检查 GSDK 配置中键为 `GamePort.Name` 的值,它总是返回要绑定的正确端口。

* *MultiplayerSettings.json* 文件中还有其他可能需要编辑的字段:
  * `ResourceLimits`(可选) - 如果指定,docker 会限制 CPU/内存使用。警告:如果你的服务器超出允许的内存,它将被终止。ResourceLimits 只能在容器模式下指定。
  * `SessionCookie`(可选) - 通过 [RequestMultiplayerServer API](xref:titleid.playfabapi.com.multiplayer.multiplayerserver.requestmultiplayerserver) 调用传递给你游戏服务器的任何会话 Cookie。
  * `OutputFolder`(可选) - 生成输出和配置文件的驱动器或文件夹的绝对路径。请确保有足够可用空间,因为游戏服务器将在此路径下解压。如果未指定,则使用代理文件夹。
  * `MountPath` - 容器内挂载资产的路径。在进程模式下运行时不需要指定此字段。我们建议使用示例值 - *C:\\\Assets*(请注意,反斜杠需要为 JSON 格式转义)。
  * `AgentListeningPort` - 指定代理绑定以与游戏服务器通信的端口。任何开放端口都可以,如果你有另一个进程绑定到 56001,则必须更改此值(或终止其他进程)。

## 验证 GSDK 集成

* 在 *MultiplayerSettings.json* 文件中,将 `RunContainer` 设置为 `false`。
* 在 Powershell 窗口(以管理员身份):
  * 将工作目录更改为解压工具集的文件夹。
  * 运行 *LocalMultiplayerAgent.exe*。此时,**LocalMultiplayerAgent** 会设置 http 侦听器,解压游戏资产,并在单独的进程中启动游戏服务器。**LocalMultiplayerAgent** 随后等待来自与游戏服务器集成的 GSDK 的心跳。
* 如果 GSDK 集成正确,**LocalMultiplayerAgent** 会打印以下输出:
  * `CurrentGameState - Initializing`(这是可选的,如果你的游戏服务器直接调用 `GSDK::ReadyForPlayers` 且未调用 `GSDK::Start`,则可能不会显示)
  * `CurrentGameState - StandingBy`
  * `CurrentGameState - Active`
  * `CurrentGameState - Terminating`
* 如果关闭回调设置正确,你的游戏服务器会在状态设置为 terminating 后不久退出。验证游戏服务器是否退出很重要,以避免在 PlayFab 平台上出现不正常关闭。
* **LocalMultiplayerAgent** 也应与游戏一起终止。

### 测试与游戏的连接

当你的游戏服务器可执行文件正在运行,并且 **LocalMultiplayerAgent** 打印 `CurrentGameState - Active` 时,你可以使用 IP 地址 **127.0.0.1** 和游戏服务器正在监听的 `NodePort` 端口连接到游戏服务器。

在经过 `NumHeartBeatsForActivateResponse` 次心跳后,**LocalMultiplayerAgent** 会请求游戏服务器从待机切换到活动状态。然后在经过 `NumHeartBeatsForTerminateResponse` 次心跳后,**LocalMultiplayerAgent** 会请求游戏服务器从活动切换到已终止。可以通过更新 *MultiplayerSettings.json* 文件中的值来调整此行为。

## 验证容器化

如果你刚接触容器,可以查看[这里](https://learn.microsoft.com/en-us/dotnet/architecture/microservices/container-docker-introduction/)的介绍。

### 先决条件

* Windows 10 Pro(或以上版本)并安装 2018 年 4 月(1803)更新。
* 下载 [Docker](https://download.docker.com/win/stable/Docker%20for%20Windows%20Installer.exe)。或者,你可以从 [Docker 网站](https://www.docker.com/products/docker-desktop)主页下载。

### 设置

* 确保将 Docker 设置为[使用 Windows 容器](https://docs.docker.com/docker-for-windows/#switch-between-windows-and-linux-containers)
* 在 Powershell 窗口(以管理员身份):
  * 导航到解压工具集的文件夹。
  * 运行 *Setup.ps1*,它会设置 docker 网络、添加防火墙规则以与 **LocalMultiplayerAgent** 通信,并从 [Microsoft/PlayFab-Multiplayer](https://hub.docker.com/r/microsoft/playfab-multiplayer/) 拉取 PlayFab docker 映像。请注意,首次运行脚本时,下载容器映像可能需要几分钟。

<Note>
  要成功运行此设置,你可能需要配置任何已安装的第三方防病毒程序(例如 McAfee、Norton 或 Avira)的防火墙。
</Note>

### 在容器内运行游戏服务器

* 在 *MultiplayerSettings.json* 文件中,将 `RunContainer` 设置为 `true`。
* 在解压工具集的文件夹(*C:\PlayFabVmAgent*)中打开 **Powershell** 窗口(以管理员身份),并运行 `LocalMultiplayerAgent.exe`。这将在容器内启动游戏服务器。最终,你应该会在 Powershell 窗口中看到游戏状态变化的输出(就像上面"验证 GSDK 集成"部分中一样)。

### 测试与容器内运行的游戏服务器的连接

当 **LocalMultiplayerAgent** 输出打印 `CurrentGameState - Active` 时,使用 IP 地址 **127.0.0.1** 和端口(等于 *MultiplayerSettings.json* 文件中指定的 `NodePort`,默认为 **56100**)连接到游戏服务器。

在经过 `NumHeartBeatsForActivateResponse` 次心跳后,**LocalMultiplayerAgent** 会请求游戏服务器从待机切换到活动状态。然后在经过 `NumHeartBeatsForTerminateResponse` 次心跳后,**LocalMultiplayerAgent** 会请求游戏服务器从活动切换到已终止。可以通过更新 *MultiplayerSettings.json* 文件中的值来调整此行为。

### 将 LocalMultiplayerAgent 与 Linux 容器一起使用

你可以使用 LocalMultiplayerAgent 调试 Linux 游戏服务器,方法是使用 [Docker for Windows](https://docs.docker.com/docker-for-windows/) 在 Windows 上的容器中运行它。你可以在[这里](https://learn.microsoft.com/en-us/virtualization/windowscontainers/deploy-containers/linux-containers)查看有关在 Windows 上运行 Linux 容器的更多信息。本质上,你只需使用 *-lcow* 参数运行代理并正确配置你的 *LocalMultiplayerSettings.json* 文件即可。

要在 Windows 上运行容器化的 Linux 游戏服务器,你需要执行以下步骤:

* 从 GitHub 的[发布](https://github.com/PlayFab/MpsAgent/releases)页面下载 LocalMultiplayerAgent 的最新版本
* [在 Windows 上安装 Docker Desktop](https://docs.docker.com/docker-for-windows/install/)
* 确保它在 [Linux 容器](https://docs.docker.com/docker-for-windows/#switch-between-windows-and-linux-containers)上运行
* 你应该挂载你的一个硬盘驱动器,你可以在[这里](https://docs.docker.com/docker-for-windows/#file-sharing)找到说明
* 你的游戏服务器映像可以发布在容器注册表上,也可以在本地构建。
* 运行 `SetupLinuxContainersOnWindows.ps1` Powershell 文件,它会创建一个名为 "PlayFab" 的 Docker 网络
* 正确配置 *LocalMultiplayerSettings.json* 文件。下面你可以看到一个示例,包含在 `MultiplayerSettingsLinuxContainersOnWindowsSample.json` 中:

```json theme={null}
{
    "RunContainer": true,
    "OutputFolder": "C:\\output\\UnityServerLinux",
    "NumHeartBeatsForActivateResponse": 10,
    "NumHeartBeatsForTerminateResponse": 60,
    "TitleId": "",
    "BuildId": "00000000-0000-0000-0000-000000000000",
    "Region": "WestUs",
    "AgentListeningPort": 56001,
    "ContainerStartParameters": {
        "ImageDetails": {
            "Registry": "mydockerregistry.io",
            "ImageName": "mygame",
            "ImageTag": "0.1",
            "Username": "",
            "Password": ""
        }
    },
    "PortMappingsList": [
        [
            {
                "NodePort": 56100,
                "GamePort": {
                    "Name": "game_port",
                    "Number": 7777,
                    "Protocol": "TCP"
                }
            }
        ]
    ],
    "SessionConfig": {
        "SessionId": "ba67d671-512a-4e7d-a38c-2329ce181946",
        "SessionCookie": null,
        "InitialPlayers": [ "Player1", "Player2" ]
    }
}
```

<Note>
  一些说明:1. 你必须将
</Note>

`RunContainer` 设置为 true。这是 Linux 游戏服务器所必需的。

<Note>
  2. 修改
</Note>

`imageDetails` 以配置你的游戏服务器 docker 映像详细信息。映像可以在本地构建(使用 [docker build](https://docs.docker.com/engine/reference/commandline/build/) 命令)或托管在远程容器注册表中。

<Note>
  3.
</Note>

`StartGameCommand` 和 `AssetDetails` 是可选的。使用 Docker 容器时通常不使用它们,因为所有游戏资产 + 启动游戏服务器命令都可以打包在相应的 [Dockerfile](https://docs.docker.com/engine/reference/builder/) 中

<Note>
  4. 最后但同样重要的是,请注意你的
</Note>

`OutputFolder` 变量的大小写,因为 Linux 容器是区分大小写的。如果大小写错误,你可能会看到类似于 *error while creating mount source path '/host\_mnt/c/output/UnityServerLinux/PlayFabVmAgentOutput/2020-01-30T12-47-09/GameLogs/a94cfbb5-95a4-480f-a4af-749c2d9cf04b': mkdir /host\_mnt/c/output: file exists* 的 Docker 异常

* 完成所有前述步骤后,你就可以使用 `LocalMultiplayerAgent.exe -lcow` 命令运行 LocalMultiPlayerAgent(lcow 代表 *Linux Containers On Windows*)

### 故障排除

* 在容器模式下,如果你的游戏服务器立即退出并出现类似 "Container ... exited with exit code 1" 的错误,但在进程模式下工作正常。请确保你已在资产包中包含所有必需的[系统 DLL](/services/playfab/multiplayer/servers/determining-required-dlls)。
* 所有日志都位于 *MultiplayerSettings.json* 文件中指定的 `OutputFolder` 下。**LocalMultiplayerAgent** 每次启动时都会创建一个新文件夹,文件夹名称为时间戳。通过 GSDK 发出的所有游戏服务器日志都位于 GameLogs 文件夹内。
  如果游戏服务器在容器中运行,可能会有额外一层目录层次需要浏览。
* GSDK 将调试日志写入 GameLogs 文件夹。这些日志与游戏服务器输出的日志一起位于 GameLogs 文件夹内。
* 确保防火墙(Windows 及其他防病毒程序)已配置为允许通过端口的流量。
* 如果你收到类似于以下的错误:`Docker API responded with status code=InternalServerError, response={"message":"failed to create endpoint <container_name> on network playfab: hnsCall failed in Win32: The specified port already exists". It's likely there is already a container running on the specified port.` 这可能是 **LocalMultiplayerAgent** 过早退出所致。使用 `docker ps` 命令查找正在运行的容器,然后使用 `docker kill <container_name>` 终止它。
* 如果你收到包含 `Failed to find network 'playfab'` 的错误,请尝试重新运行 *Setup.ps1*
* 如果你收到 `Unhandled Exception` 错误,可能是因为你以管理员身份运行 PowerShell。
* `OutputFolder` 可能反过来被其他系统变量使用,因此请确保使用绝对路径。例如,GSDK\_CONFIG\_FILE 具有这样的依赖关系,因此此处使用相对路径(或不正确的值)可能会导致游戏服务器配置加载错误。

### 已知限制

1. 容器在调试结束时可能不会终止。如果发生这种情况,请以管理员身份运行以下 PowerShell 命令。这些命令会停止并删除所有容器,包括那些不是由 **LocalMultiplayerAgent** 启动的容器。

```powershell theme={null}
docker stop $(docker ps -aq)
docker rm $(docker ps -aq)  
```


## Related topics

- [PlayFab 游戏服务器基础知识](/zh-CN/services/playfab/multiplayer/servers/basics-of-a-playfab-game-server.md)
- [使用 LocalMultiplayerAgent 调试容器游戏服务器](/zh-CN/services/playfab/multiplayer/servers/LocalMultiplayerAgent/run-container-gameserver.md)
- [Wrapper 示例](/zh-CN/services/playfab/multiplayer/servers/wrapper-sample.md)
- [直接连接以调试游戏服务器](/zh-CN/services/playfab/multiplayer/servers/directly-debugging-game-servers.md)
- [使用 LocalMultiplayerAgent 调试基于进程的游戏服务器](/zh-CN/services/playfab/multiplayer/servers/LocalMultiplayerAgent/run-process-based-gameserver.md)
