单页应用程序 (SPA) 的零停机/蓝绿部署

Posted

技术标签:

【中文标题】单页应用程序 (SPA) 的零停机/蓝绿部署【英文标题】:Zero downtime/blue-green deployment of Single Page Application (SPA) 【发布时间】:2017-02-13 09:23:40 【问题描述】:

昨天我们与团队一起讨论了使用零停机时间部署来支持我们的单页应用程序的可能性。

在讨论它时,我们确定了它的一种极端情况。 用户在浏览器中加载页面后,在重新加载页面之前无法将其从内存中删除。这意味着如果用户加载页面并开始使用该网站(例如开始像我现在所做的那样开始输入一篇长文章),那么在他重新加载页面之前,他无法收到它的更新版本。

我们可以忽略用户在其浏览器中看到旧应用程序版本的事实,但下面列出了 2 点。

    如果我们对用于服务 spa 的 HTTP Api 进行重大更改,则用户将无法保存他的文章(数据丢失!),或者在执行其他后端相关操作时可能会收到其他错误。李> 当用户导航到新页面而不重新加载 SPA 时,他会收到下一页的模板或与外部旧容器不兼容的某些控件的模板。它可能会导致标记或应用程序逻辑损坏。 我们不能强制用户重新登录,因为他可能正在输入他的文章,这只是一个糟糕的用户体验。

考虑到所有这些点,可以提出以下解决方案:

    用户 1 将 SPA 的 v1 加载到他的浏览器中。 版本信息与身份验证令牌一起发送到浏览器(例如使用 JWT)。 我们想要部署我们的应用程序的 v2 版本。我们启动了 v2 版本,但不禁用 v1。 用户 2 将 SPA 的 v2 加载到他的浏览器中 用户 1 转到 SPA 中的下一页。负载均衡器检查其令牌中的版本信息,并将用户 1 的流量路由到 v1 服务器。 用户 2 以相同的方式路由到 v2。 用户 1 退出应用并关闭浏览器。 用户 1 重新登录 - 这次他收到 v2。 v1 应用程序在长时间没有收到任何流量后被丢弃。

但是,在这种方法中,可以有多个版本,超过 2 个(例如,如果用户一整天或两天都在线)。这意味着在最后一个用户注销之前,我们将无法将数据库迁移到新模式(想象一下它如何适用于 Facebook 等网站)。拥有多个版本不是问题,但是像 Docker 和 Rancher 这样的工具让我们可以轻松地做到这一点。

也在第 7 步中。用户需要重新加载页面或关闭浏览器 - 否则他仍将使用 v1,我们无法强制他进入下一个版本。

我的问题是您使用什么方法来实现单页应用程序的零停机/蓝绿部署

当您将流量切换到“绿色”版本时,您如何管理应用程序“蓝色”版本的生命周期,尤其是对于现有的“蓝色”客户端应用程序。

这些问题你解决了吗,你知道其他解决方法吗?

【问题讨论】:

我很想知道您最终的决定。我目前正在思考这样的问题。谢谢。 事实上我没有得到确切的解决方案 - 我正在做一种蓝/绿部署方法的研究或 POC。一种可能的解决方案是启用绝对会话到期并强制每个用户每天至少注销一次。在这种情况下,您还需要强制用户重新加载浏览器页面并重新加载 JS 应用程序。在这种情况下,可以在最早的登录会话结束后进行切换。 【参考方案1】:

我已经为这个问题苦苦挣扎了很长一段时间,并尝试了几种方法,其中一种特别有效:

捆绑 SPA 时使用散列名称(包括图像等) 使用静态资产存储桶(例如:AWS S3)并将所有资产上传到它在部署过程开始之前 强制执行内部准则,以尽量减少 API 合同被破坏(即:端点的字段只能在 X 版本后删除) 使用通常的蓝/绿策略进行部署

基本原理

使用带有散列捆绑包的存储桶可确保如果客户获得旧版本的 SPA,其所有资产将在任何部署过程之前/期间/之后可用。 强制执行内部准则以不破坏 API 兼容性有时很棘手,但它来自适用于任何公共 API 的相同原则。通过具体示例与团队沟通时,接受/调整来自大玩家的 API 弃用政策会有所帮助。

【讨论】:

【参考方案2】:

您可能会考虑的一种方法是在这样的时刻逐渐重新加载 SPA,此时它对最终用户来说不是负担(甚至不明显)。

建议的方法:

系统的彩色版本(提供后端服务、API 和前端的组件)“知道”(提供运行时)它们的“颜色”。为用户提供前端应用程序的组件将此颜色信息嵌入到 SPA 中。然后(通过 cookie 或自定义 HTTP 标头)与 SPA 向后端发出的每个请求一起发送。

路由 API 调用的组件(API 网关、负载平衡器、nginx、HAproxy、基于 Zuul 的自定义路由器等)知道此颜色信息,并使用它来将流量引导到适当颜色的基础设施。

此外,还有一个带有最新版本颜色的公共 URL(不是由“彩色”基础设施提供的 - 例如通过 CloudFront 或其他代理提供的 S3 文件)。 SPA 在每个给定的时间段(60 或 120 秒)检查此版本。如果版本与加载时提供的一个 SPA 不匹配,则在主要的下一个路由更改页面上“物理地”重新加载,而不是仅在浏览器中实现此导航。

您可以选择哪些路由更改正在验证此版本,以使其对用户的干扰最小(可能几乎不引人注意)。

如果您选择所有用户每天都使用的一些路线,那么很快所有用户都会迁移到最新的颜色。长时间不使用打开的浏览器窗口(电脑休眠两周?)可以通过在一段时间不活动后强制重新加载来处理。

我希望我终于设法让自己听起来有点凝聚力:-)

问候, 沃伊泰克

【讨论】:

很好的答案!我还认为(因为我对 PWA 的一些新概念有所了解)应用程序可以使用 App Shell 架构构建,它可以允许您在此类导航中重新加载所有内容,但不要重新加载 shell(它可以没事) 一个有趣的想法,将重载隐藏在路由后面!【参考方案3】:

不知道为什么要对 UI 进行全面检修,因为它们总是涉及学习曲线。实际上,在现实世界中,立即切换到新 UI 是个坏主意。您将允许客户在一段时间内切换到新界面,然后在预警后禁用旧版本。不值得为这样的实时切换付出努力。 A/B 测试可能是向客户介绍新界面然后进行实际推出的一种方式。

【讨论】:

【参考方案4】:

您所描述的技术称为蓝绿部署;您从现有服务器(蓝色)开始,然后添加更新后的服务器(绿色)。从那时起,所有 流量都被重定向到绿色环境。蓝色环境仅用于为现有的 http 连接提供服务,也用于可选的“回滚”,以防绿色环境遇到重大问题。最终,当“蓝色”环境完成所有请求的服务后,它就可以退役了。

此技术要求两个系统有些相似。例如,数据库模式可能使其不切实际。

【讨论】:

是的,我知道这是蓝绿部署,但更准确地说,问题是它如何与单页应用程序一起工作,您无法强制用户升级他的客户端更新服务器部分时的应用程序

以上是关于单页应用程序 (SPA) 的零停机/蓝绿部署的主要内容,如果未能解决你的问题,请参考以下文章

微服务架构的零停机部署

基于Nginx+lua的蓝绿发布系统

蓝绿部署滚动部署灰度发布金丝雀发布

如何设置NGINX以根据位置(在相同的server_name下)部署不同的单页应用程序(SPA的...即静态文件)和子路由

如何设置 NGINX 以部署不同的单页应用程序(SPA 的...即静态文件),具体取决于位置(在相同的 server_name 下)和子路由

蓝绿发布滚动发布灰度发布等部署方案对比与总结