0

我有一个有状态的游戏应用程序,它部署在 Cloud Foundry 上。如果我更新应用程序,我需要正常关闭,即在所有正在运行的游戏完成之前不应停止旧版本。根据CF 文档,在发出cf stopSIGTERM 后,应用程序只有 10 秒的时间关闭,然后应用程序被使用 SIGKILL 杀死。这在我的情况下不起作用。

我考虑过将状态推送到数据库或 Redis 之类的东西中,然后将正在运行的游戏热交换到新的应用程序实例,但由于我大量使用 Web Sockets,这似乎造成的问题比它解决的问题多,因为它也会打破现有的连接。

另一种解决方案是不发送cf stop,而是向我的应用程序添加一个操作端点,例如POST /api/admin/stop,这会使应用程序停止接受新游戏,然后在所有正在运行的游戏完成后自行关闭。

我的第三个选择可能是完全改变设计并使用像WebRTC这样的协议作为协议,这意味着应用程序将只提供静态资源,但在运行游戏时不再发挥积极作用,导致所有客户端直接相互连接通过服务器。不过,我在 WebRTC 方面没有经验,想知道该解决方案是否可靠,例如,如果某些用户使用 VPN。

现在我赞成第二种选择。但它应该是 CF 应用程序可以自行终止的方式吗?如果是的话,如何干净地做到这一点?

或者还有其他选择吗?最好的解决方案是什么?

4

1 回答 1

0

根据 CF 文档,发出 cf stop 时,在发送 SIGTERM 之后,应用程序只有 10 秒的时间关闭,然后应用程序被使用 SIGKILL 杀死。这在我的情况下不起作用。

这是预期的行为。如果你没有看到这一点,你会想要更仔细地研究事情。您没有提到您正在使用的语言/框架,有些语言使处理信号变得更容易,而有些语言使处理信号变得更加困难(有些甚至默认处理它们)。

我建议如下:

  1. 您会想查看应用程序语言的细节并了解如何处理信号。确保您在应用程序中正确实施。即使在自动处理信号的语言中,您仍然需要绑定某种关闭挂钩,以便您可以执行自定义关闭代码并保存您的状态。

  2. 您需要捕获信号并尽快处理它。在发送 SIGKILL 之前,您只会得到 10 秒,然后您的应用程序就会终止。

  3. 我建议编写一个处理信号的简单示例应用程序,您可以记录信号何时被捕获并暂停不同的持续时间,然后查看平台如何处理事情。这也很有用,因为 10 秒只是平台等待时间的默认值。您的平台运营商可以更改该值,因此它可能会更短或更长。进行这样的测试将允许您测试并找到操作员设置的确切值。

我想过将状态推送到数据库或 Redis 之类的东西中,然后将正在运行的游戏热交换到新的应用程序实例,但是由于我大量使用 Web Sockets,这似乎产生的问题比它解决的问题多,因为它也会打破现有的连接。

我对您的应用程序架构没有太多评论,因为除了以下注释之外,我对您正在做什么以做出有根据的评论知之甚少。

在 CF 上运行时,您希望尽可能多地尝试和利用服务的状态。不要写入本地磁盘并尝试确保您将会话状态等内容存储在持久缓存(如 Redis)中。

应用程序实例可能因多种原因而关闭。其中之一是如果您运行cf stop,但如果您的平台运营团队正在进行更新或 Diego Cell(您的应用程序容器所在的位置)崩溃,它们也可能会被关闭。您的应用程序将被关闭的某些原因不是您可以控制的,因此您必须牢记这一点。

要记住的关键事项是 a.) 如果您有多个实例,该平台将保证您始终至少有一个正在运行,并且 b.) 如果 a.) 您需要能够平衡多个应用程序实例之间的请求。如果您可以管理这两个项目,那么您的应用程序应该在 CF 上运行良好。

于 2021-11-08T15:08:00.270 回答