Deployment slackbot的零停机部署

Deployment slackbot的零停机部署,deployment,parallel-processing,mutex,devops,slack,Deployment,Parallel Processing,Mutex,Devops,Slack,我们用BotKit开发bot,现在我们试图用最少的部署停机时间来解决这个问题 此服务器上运行着服务器和docker容器。容器内运行与RTM服务器连接的bot应用程序实例(Slack)。 当我开始部署新版本(v2)的bot应用程序时,我希望获得零停机时间,用户不应该看到“bot处于脱机状态” 部署脚本使用新版本的bot应用程序运行第二个docker容器。和机器人应用程序连接到RTM服务器也。这样,当两个应用程序都运行、连接到RTM服务器并响应用户命令时,只有几秒钟的时间(用户将看到对其命令的两个

我们用BotKit开发bot,现在我们试图用最少的部署停机时间来解决这个问题

此服务器上运行着服务器和docker容器。容器内运行与RTM服务器连接的bot应用程序实例(Slack)。 当我开始部署新版本(v2)的bot应用程序时,我希望获得零停机时间,用户不应该看到“bot处于脱机状态”

部署脚本使用新版本的bot应用程序运行第二个docker容器。和机器人应用程序连接到RTM服务器也。这样,当两个应用程序都运行、连接到RTM服务器并响应用户命令时,只有几秒钟的时间(用户将看到对其命令的两个回答)

如果一方面我们希望获得零停机时间,另一方面我们希望防止用户同时与这两个实例交互,那么我可以得到什么最佳决策

决定1: 当两个实例都响应用户命令时,允许发生冲突的可能性很小

决定2: 放弃零停机部署。在本例中,部署脚本首先停止第一个docker容器,然后启动另一个容器。在停止当前版本的应用程序和完全启动新版本的应用程序之间发送的用户命令,应用程序将不响应

决定3: 通过并行运行当前和新版本的应用程序或互斥体进行交互。总示意图: 1) 应用程序的当前版本正在运行 2) 部署脚本启动新版本的应用程序 3) 当新版本的应用程序几乎运行并准备连接到RTM服务器时,它会发送到当前版本的应用程序命令以关闭RTM连接。 4) 当前版本的应用程序关闭RTM连接 5) 新版本的应用程序开放RTM连接

我认为还有其他好的解决办法


<>你如何在你的申请中解决这个问题?

< P>我将考虑的一个想法分为两个部分:

  • 保持WebSocket连接到Slack RTM API的组件。该组件只是从API读取消息并将其放入队列。(我们称之为“排队者”)
  • 实际的“bot”,它从队列中读取消息并根据需要进行响应
  • 根据bot的行为方式,它可以直接使用webapi,也可以将自己的消息放在“queuer”可以通过rtmapi发送的出站队列上

    这种架构可能会解决您的问题。。。现在,您可以暂时关闭bot,而升级响应将延迟到新版本运行,或者您可以同时运行两个版本的bot,并依靠队列的语义来防止两个版本对同一消息做出响应。

    (抱歉,第二次回复;我有另一个想法。)

    我前面描述的方法会对您现有的代码造成相当大的破坏,因为您可能需要停止使用botkit(或者至少不使用它进行RTMAPI通信)。一种破坏性较小的方法是使用某种外部方式来表示给定消息已被处理

    例如,使用Redis,让机器人在收到消息时执行以下命令:

    SET message:<message timestamp> 1 NX PX 30000
    
    设置消息:1 NX PX 30000
    
    NX
    选项意味着只有当密钥不存在时,该命令才会成功。因此,成功执行此操作的bot的第一个实例将成功,而另一个实例将失败。只有当此命令成功时,bot才会处理消息并作出响应

    (px30000的
    px30000
    设置了30秒的过期时间,这样Redis就不会充满这些密钥。)

    这将允许您通过重叠运行的bot实例来执行零停机升级,而无需担心消息被处理两次


    请注意,在这个方案中,如果bot以一种不优雅的方式关闭,则仍然可以完全删除消息。(它可能会在调用
    SET
    命令后,但在实际处理消息之前死亡。)使用两阶段“get/delete”的真实队列会更好,但之后您又回到了我的另一个答案::-)

    谢谢smarx!有很好的解决方案!与第一个变体不同,它看起来不那么复杂,更可靠。这会阻止bot有状态。如果没有直接的Websocket连接,您将不得不模拟对话对象。(或者至少状态需要在bot流程外部。)