无服务器异步多玩家游戏参考体系结构
体系结构关系图
体系结构服务
- Azure Functions - 用于运行小块的匹配逻辑。 请注意,使用 Consumption 计划时,函数定义存储在 File Storage 中,这意味着您必须创建 Storage 帐户。 为了获得最佳性能,您应该使用与 Functions 位于同一区域的 Storage 帐户。
- Azure Database for MySQL - 由于其快速、轻量、可靠且经济高效,用于存储信息。
- 通知中心 - 一种易用的扩展型推送引擎,允许您向多个平台(iOS、Android、Windows、Kindle、百度等)推送通知。
- SignalR - 简化通过 HTTP 向应用程序添加实时网络功能的过程,从而让您将数据推送到已连接的设备客户端。
- Key Vault - 用于管理密钥(包括数据库连接字符串)的最佳服务。
设计注意事项
这个参考体系结构展示了一个简单的无服务器“井字棋” 游戏。
在这个参考体系结构中,一个帮助程序类(数据客户端)将连接到数据库并与之交互,而其余 Functions 将在需要时使用它。 游戏会话类用来根据玩家提交的信息运行回合,并计算赢家。 支持 3 种不同的操作事件 :forfeit(放弃游戏)、addPlayer(将玩家加入游戏会话)和 takeTurn
部署模板
请查看一般指南文档,其中有一部分概述了 Azure 服务的命名规则和限制。
备注
如果您对 ARM 模板的工作原理感兴趣,请参阅此参考体系结构中使用的每个不同服务对应的 Azure 资源管理器模板文档:
警告
数据库管理员的密码必须包含 8 到 128 个字符。 此外,它必须包含以下三种类别的字符:英文大写字母、英文小写字母、数字 (0-9) 和非字母数字字符(!、$、#、% 等)。
提示
要在本地运行 Azure Functions,请使用这些相同的应用设置更新 local.settings.json 文件。
分步操作
创建新游戏会话
- 设备客户端会格式化玩家选择的游戏设置,并将开始游戏会话事件发送到后端,然后等待响应。
- 后端收到开始新游戏会话的命令。 首先,它会尝试查找与玩家设置相匹配的现有游戏会话。
- 如果没有匹配的合适游戏会话,将创建一个新的游戏会话对象。
- 创建一个新的持久 Orchestrator Function。
- 持久 Orchestrator Function 将读取游戏会话对象,并且一直等到至少 2 个玩家加入此游戏会话为止。
- 具有与第一个玩家所选设置相同的另一个玩家将开始游戏会话事件发送到后端。
- 后端收到命令并尝试查找现有游戏。 在这种情况下,它将查找之前创建的游戏会话。
- 持久 Orchestrator Function 接收 addPlayer 事件,并在两个玩家都加入游戏会话后停止等待。
- 持久 Orchestrator Function 正式开始匹配,将游戏状态设置为正在进行,并随机选择一个玩家以开始游戏。 简而言之,Orchestrator 负责执行游戏逻辑和更新游戏状态。
- 持久 Orchestrator Function 触发一个操作以将数据保存到数据库中。 它利用数据客户端帮助程序类来连接到数据库,以保存数据。
- 持久 Orchestrator Function 运行游戏会话逻辑,并返回“轮到下一个玩家开始”。
- 它根据游戏条件将排队通知发送给一个玩家或多个玩家(轮到别的玩家、有玩家胜出、有玩家弃权,等)。
- 持久 Orchestrator 随后自行调用新游戏状态,并等待接收下一个事件。
- 设备客户端收到通知,包括管理游戏会话的 Orchestrator Function 的唯一标识符。
- 设备客户端将加载游戏会话事件发送到后端,包括在通知中收到的持久 Orchestrator 的唯一标识符。
- 后端收到加载游戏会话的命令,并返回要由设备客户端显示的游戏会话的详细信息。
- 玩家将一个 X 或 O 直接提交到持久 Orchestrator Function,这一轮结束。
请求玩家游戏列表
- 设备客户端向后端提交获取会话列表命令。
- 后端通过查询数据库来处理该请求,然后将数据发送到设备客户端。 请考虑对查询返回的结果数量做出限制并进行排序。
- 设备客户端收到后端响应,使用它所包含的数据来填充相关 UI。
实现示例
读者练习
提供的示例不包含用于标注从数据库进行读取的逻辑,而仅仅是写入逻辑。 请考虑使用缓存保护数据库或扩展数据库,以避免耗尽指向数据库的连接。
安全注意事项
不要将数据库连接字符串硬编码到 Function 的源代码中。 但至少应充分利用函数应用设置,或者,若要获取更高的安全性,请改用密钥保管库。 有一个指南介绍如何创建密钥保管库、如何将托管服务与函数标识结合使用,以及如何从函数中读取存储在密钥保管库中的机密。
备选方案
这个参考体系结构中使用了 Azure Database for MySQL,但可以将它替换为 Azure SQL 数据库或Azure Database for PostgreSQL。
其他资源和示例
使用持久 Function 和 Azure SignalR 服务的益智答题游戏
尽管它不是完全异步的(运行一个 20 秒的计时器),您可以在此链接找到用持久 Function 和 Azure SignalR 服务构建的益智答题游戏的实施。 问题是从 jservice.io 检索的。 要查看它的运行情况,请参阅此链接。
以下是它的工作原理:
- 益智答题游戏托管方启动游戏,按照部署或通过网络请求调用 HttpStartSingle Azure Functions。
- 该 Azure Functions 启动 TriviaOrchestrator Durable Azure Functions。
- 玩家加入游戏。 运行应用的每个玩家的设备客户端都从后端检索 Azure SignalR 服务中心详细信息。 后端通过 SignalRInfo Azure Functions 接收该请求。 函数绑定通过在连接字符串中使用键生成一个标记,然后将其发送到设备客户端。 设备客户端设置要侦听的来自 Azure SignalR 服务的两个事件:newClue 和 newGuess。
- 在后端,TriviaOrchestrator Durable Azure Functions 调用 GetAndSendClue Durable Azure Functions。
- TriviaOrchestrator Durable Azure Functions 将计时器设置为每隔 20 秒调用一次,即玩家必须在这段时间内响应问题。
- GetAndSendClue Durable Activity Azure Functions 从 jservice.io 服务中拉取一个问题。
- 然后问题通过 Azure SignalR 服务广播到所有具有目标 *newClue * 的已连接用户。
- 玩家收到来自 Azure SignalR 服务的问题,并提供他们的答案。
- 后端通过 SubmitGuess Azure Functions 接收玩家的响应。
- 此 Azure Functions 计算玩家提交的答案是否正确。 然后,结果通过 Azure SignalR 服务广播到所有具有目标 newGuess 的已连接用户。
- 设备客户端收到来自 Azure SignalR 服务的响应,并更新回答正确或回答错误的次数。
定价
如果您没有 Azure 订阅,可以创建免费帐户,开始使用 12 个月的免费服务。 除非您超出这些服务的使用限制,否则无需为 Azure 免费帐户中包含的这些免费服务付费。 了解如何通过 Azure 门户或使用情况文件查看服务使用情况。
您需要承担运行这些参考体系结构时所使用的 Azure 服务的费用。 总金额将因使用情况而异。 请参阅参考体系结构中使用的每项服务的定价网页:
您还可以使用 Azure 定价计算器,以配置和估算您计划使用的 Azure 服务的成本。