我们使用BotKit开发了bot,现在我们尝试以最小的部署停机时间解决问题。
该服务器上运行着服务器和Docker容器。在容器内部运行与RTM服务器(Slack)连接的bot-app实例。当我开始部署bot-app的新版本(v2)时,我希望停机时间为零,用户不应看到“机器人已脱机”。
Deploy脚本使用新版本的bot-app运行第二个Docker容器。并且bot-app也连接到RTM服务器。这样,当两个应用程序都运行并连接到RTM服务器并响应用户命令时,会有几秒钟的时间(用户将看到对其命令的两个答案)。
如果一方面我们希望获得零停机时间,另一方面又希望防止用户同时与两个实例进行交互,那么我可以得到什么样的最佳决策呢?
决策1:当两个实例都将响应用户命令时,为了尽可能减少发生碰撞的可能性。
决策2:放弃零停机时间部署。在这种情况下,deploy脚本首先停止第一个docker-container,然后再启动另一个。该应用程序将不响应在停止当前版本的应用程序与完全启动新版本的应用程序之间发送的用户命令。
决策3:通过并行运行当前和新版本的应用程序或互斥锁进行交互。总体示意图:1)当前版本的应用程序正在运行2)部署脚本启动新版本的应用程序3)我正在等待新版本的应用程序几乎运行并准备连接到RTM服务器时,它会发送至当前版本的app命令以关闭RTM连接。4)应用程序的当前版本关闭RTM连接5)应用程序的新版本打开RTM连接
我认为还有其他好的解决方案。
您将如何在应用程序中解决此问题?
(很抱歉第二个答复;还有其他想法。)
我前面介绍的方法将对您现有的代码造成很大的破坏,因为您可能需要停止使用botkit(或者至少不使用它来进行RTM API通信)。一种破坏性较小的方法是使用某种外部方式来发出给定消息已被处理的信号。
例如,使用Redis,让机器人在收到消息时执行以下命令:
SET message:<message timestamp> 1 NX PX 30000
该NX
选项表示仅当密钥不存在时,此命令才会成功。因此,能够执行此操作的bot的第一个实例将成功,而另一个实例将失败。机器人仅应处理该消息,并在此命令成功后做出响应。
(这PX 30000
设置了30秒的到期时间,因此Redis不会充满这些密钥。)
这应该让您通过重叠正在运行的机器人实例来进行零宕机时间升级,而不必担心消息会被处理两次。
请注意,如果以非正常方式关闭漫游器,则在此方案中仍然有可能完全丢弃一条消息。(它可能在调用该SET
命令之后但实际上未处理该消息之前就消失了。)带有两个阶段的“获取/删除”的真实队列会更好,但是您又回到了我的其他答案。:-)
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句