Startup CliX:用 JavaScript 编写的无服务器推送器竞赛条目
我建造了什么
我是如何建造它的
其他资源/信息
结论
经过一个漫长而疲惫的周末。
我终于找到时间为参赛作品写一篇正式的博客文章。
我建造了什么
游戏玩法
您的起步资金为 30,000 美元。
每一轮您都可以通过尽可能快地点击并提交产品来创建产品。
您的产品价格(=您的利润)计算如下500000 * clicks / milliseconds
由于你的初创公司烧钱速度太快,你每轮也会损失 5000 美元。
所以你可能每轮都会输钱,哈哈。
如果你输掉了所有的钱你就出局了。
最后剩下的玩家获胜。
演示链接
代码链接
我是如何建造它的
堆
我的想法是完全无服务器构建。虽然 Pusher 允许无服务器设置,但遗憾的是它没有无服务器定价模式,呵呵。
我使用了 AWS SAM,它是 CloudFormation 的扩展,因此除了 Pusher 之外,它是 100% 基础设施即代码。
用于 HTTP 请求的Amazon API 网关。加入游戏,每轮提交产品,接收 Pushers 的 webhook 数据。
AWS Lambda用于所有服务器端计算。检查空盘游戏,计算每轮收益,并通过 Pusher 通知玩家游戏事件(round:start
、round:end
等)。
AWS Step Function用于游戏协调。启动游戏,开始回合,每回合调用 Lambda 进行计算并通过 Pusher 通知玩家。
Amazon DynamoDB存储游戏数据(产品、玩家数量),以便状态机控制的 Lambda 函数可以访问这些数据。
推送通道无需轮询即可从后端获取数据到客户端。
前端由create-react-app和Bootstrap (v4 + Bootswatch Sketchy ) 构建。
建筑学
我也做了一个架构图:
如您所见,数据通过 HTTP 从播放器和 Pusher 传入我的无服务器后端,并通过 Pusher Channels 反馈给客户端。
推送渠道的作用
Pusher Channels 允许向客户端广播/多播事件,而无需直接连接到客户端。
您只需调用 Pusher HTTP-API 发送事件,Pusher 就会负责将其分发给客户端。
这很酷,因为 WebSocket 会强制你与所有客户端保持开放连接,而 Lambda 函数则无法做到这一点。它们只能运行大约 5 分钟。
当调用 Lambda 函数(通过 API-Gateway 或 Step Functions)时,它可以简单地执行其操作,向 Pusher 发送 HTTP 请求并再次暂停,同时 Pusher 会跟踪打开的连接。
Pusher API 还允许通过 HTTP 获取所有通道的状态,因此您可以启动 Lambda,检查谁在线,并根据通道状态发送数据(如果您愿意)。
问题
慢速实时
Pusher 宣传其频道是实时的,但事实并非如此。
它以 Web 技术为核心,因此完全基于 TCP 构建,并且在整个架构中添加了至少一个其他服务器(= 网络跃点)。
首先,您拥有从 Pusher 到客户端的 WebSockets 连接,其延迟比每个事件的完整 HTTP 请求要小,但仍然会带来一些往返。
其次,您使用服务器端的 HTTP API 将事件发送到 Pusher,这会导致client -HTTP-> back-end -HTTP-> Pusher -WebSockets-> client
延迟。
它的独特卖点在于通过非常简单的设置将数据推送给客户端(因此得名 Pusher,哈哈),但延迟却很小。
它允许您使用客户端事件来切断后端作为中间人,以进一步减少延迟,但您不能为每个事件在 Pusher 端运行代码,这会大大降低实用性。
所以目前我们讨论的是每秒少于 10 个事件。这对于大多数应用程序来说已经足够了。
这就是为什么我不会每次点击都发送到服务器,而是每轮收集它们。这样每 10 秒就会发送一次 HTTP 请求(10 秒轮次)。
像用于 Pusher 事件的 Lambda 这样的功能,在 Pushers 基础设施上运行将是一个杀手级功能,呵呵。
单向阶跃函数
下一个问题是 AWS 阶跃函数。我发现它可以用来模拟游戏状态、回合等,但一直没找到轻松将数据导入状态机的方法。
问题如下:
你定义一个状态机。这个状态机可以执行多次。
状态机的每个状态都可以使用一些输入来调用 Lambda 函数或创建活动任务。
我的想法是将游戏定义为状态机,并且状态机的每次执行都是一个正在运行的游戏。
虽然每次执行都可以等待工作者(例如 API-Gateway Lambda)完成活动,但工作者无法过滤每个活动中的任务以供执行。
所以我无法让工人执行特定于游戏。
我必须添加 DynamoDB 才能将数据放入状态机。
玩家通过 HTTP(API 网关 -> Lambda)发送成品,后端会将其存储到 DynamoDB 中,并gameId
作为主键。
当状态机决定一轮结束时,例如在Wait
10 秒的状态之后,它会启动一个 Lambda 函数,查看 DynamoDB,计算结果并将其发布到客户端。
DynamoDB 具有良好的并发特性,所以它还不错,并且最终可以更轻松地同步玩家。
其他资源/信息
我还为这个过程写了一堆博客文章。
- 推杆比赛创意:JavaScript 游戏
- Pusher 竞赛创意:JavaScript 游戏(2)
- Pusher 竞赛创意:JavaScript 游戏(3)
- Startup Clix:使用 AWS SAM 的 Pusher Presence Channels
- Startup Clix:清理并应对 Pusher 应用程序状态
- Startup Clix:ESLint 和 Pusher 应用程序状态制胜
- Startup Clix:使用 AWS Step Functions 的第一步
- Startup Clix:使用 Pusher 进行预身份验证和 Webhook
- Startup CliX:GitHub Pages 上的 DynamoDB 和 React 前端
- Startup CliX:终于有游戏玩法了
- Startup CliX:RC1 版,包含私人游戏和移动 UI
结论
使用我的新后端技能并看到自己现在真正地做全栈工作很有趣。
我学到了很多关于 Pusher、AWS 和无服务器的知识。
我会很感激你们所有的喜欢、独角兽等等,但即使我没有赢,将这个项目添加到我的投资组合中也是很好的(也许在清理之后,哈哈)
另外,一如既往,欢迎大家提出问题和提交 Pull 请求。说不定有人能想出一些让游戏更好玩的点子呢,呵呵。