Dark如何部署50ms代码


开发过程越快,技术公司的发展速度就越快。


不幸的是,现代应用不利于我们-我们的系统必须实时更新,同时又不能打扰任何人,也不会导致停机和中断。 在这样的系统中部署成为一项复杂的任务,即使在小型团队中,也需要复杂的连续交付管道。


这些管道通常应用范围狭窄,工作缓慢且不可靠。 开发人员必须首先手动创建它们,然后对其进行管理,并且公司通常为此雇用整个DevOps团队。


开发速度取决于这些管道的速度。 对于最好的团队,部署需要5到10分钟,但通常会花费更长的时间,而对于一次部署,则需要几个小时。


在黑暗中,需要50毫秒。 五十 毫秒 Dark是一种完整的解决方案,它具有专为连续交付设计的编程语言,编辑器和基础结构 ,并且Dark的所有方面(包括语言本身)都是基于安全的即时部署而构建的。


为什么连续输送机这么慢?


假设我们有一个Python Web应用程序,并且已经创建了一个很棒的现代连续交付管道。 对于每天都忙于该项目的开发人员,部署一个小的更改将如下所示:


做出改变


  • 在git中创建一个新分支
  • 在功能开关后面进行更改
  • 进行单元测试以验证有无功能开关的更改

池请求


  • 提交提交
  • 将更改发布到github上的远程存储库
  • 池请求
  • CI在后台自动构建
  • 代码审查
  • 如有必要,再进行一些评论
  • 使用git向导合并更改。

CI在向导上运行


  • 通过npm设置前端依赖
  • 建立和优化HTML + CSS + JS资源
  • 在单元和功能测试的前端运行
  • 从PyPI安装Python依赖项
  • 在单元测试和功能测试的后端运行
  • 两端集成测试
  • 将前端资源发送到CDN
  • 为Python程序构建容器
  • 将容器发送到注册表
  • Kubernetes清单更新

用新代码替换旧代码


  • Kubernetes启动一个新容器的多个实例
  • Kubernetes正在等待实例开始运行
  • Kubernetes将实例添加到HTTP负载均衡器
  • Kubernetes等待旧实例停止使用
  • Kubernetes停止旧实例
  • Kubernetes重复这些操作,直到新实例替换所有旧实例为止

打开新功能开关


  • 新代码仅供我自己使用,以确保一切正常
  • 为10%的用户提供了新代码;跟踪了运营和业务指标
  • 为50%的用户提供了新代码;跟踪了运营和业务指标
  • 为100%的用户提供了新代码,跟踪了业务和业务指标
  • 最后,重复整个过程以删除旧代码并切换

该过程取决于工具,语言和面向服务的体系结构的使用,但是总的来说,它看起来像这样。 我没有提到数据库迁移部署,因为这需要仔细计划,但是下面我将描述Dark如何解决这个问题。


这里有很多组件,其中许多组件很容易降低速度,崩溃,引起临时竞争或降低工作系统的性能。


而且由于这些管道几乎总是在特殊场合创建的,因此很难依靠它们。 很多人有几天无法部署代码,这是因为Dockerfile中存在问题,数十种服务之一崩溃或度假时合适的专家。


更糟糕的是,这些步骤中有许多根本不起作用。 在立即为用户部署代码之前,我们需要它们,但是现在我们有了新代码的开关,并且这些过程是分开的。 结果,部署代码的步骤(将旧代码替换为新代码)现在变成了额外的风险。


当然,这是一个非常周到的管道。 创建团队花费了时间和金钱来快速部署。 通常,部署管道的速度要慢得多且不可靠。


在黑暗中实现连续交付


持续交付对Dark至关重要,因此我们可以在不到一秒钟的时间内准时交货。 我们完成了管道的所有步骤,以删除所有不必要的内容,然后将其余的内容记入脑海。 这就是我们删除步骤的方式。


杰西·弗雷泽Jessie Frazelle )在雷克雅未克举行的软件开发的未来会议上创造了新词“ deployment”

我们立即决定,Dark将基于“ deployless”的概念(感谢Jesse Frazel的新词)。 无需部署意味着可以立即部署任何代码并准备在生产中使用。 当然,我们不会错过错误或不完整的代码(我将在下面描述安全原则)。


在Dark演示中,经常有人问我们如何设法加快部署速度。 奇怪的问题。 人们可能认为我们提出了某种超级技术,可以对代码进行比较,编译,将其打包到一个容器中,启动一个虚拟机,在一个冷的容器中启动一个容器,然后在50毫秒之内完成所有这些工作。 这几乎是不可能的。 但是我们创建了一个特殊的部署引擎,不需要所有这些。


Dark在云中启动了口译员。 假设您在用于HTTP或事件的函数或处理程序中编写代码。 我们将diff发送到抽象语法树(由编辑器和服务器内部使用的代码的实现)到我们的服务器,然后在收到请求时运行此代码。 因此,部署看起来像数据库中的适度记录-即时和基本。 部署是如此之快,因为它包括了最低限度。


将来,我们计划从Dark中创建基础结构编译器,以创建和运行理想的基础结构,以实现应用程序的高性能和可靠性。 当然,即时部署并没有任何进展。


安全部署


结构化编辑器


Dark中的代码是在Dark编辑器中编写的。 结构化编辑器不会发生语法错误。 实际上,Dark甚至没有分析仪。 在您输入时,我们将直接使用抽象语法树(AST),例如PareditSketch-n-SketchTofuPruneMPS


Dark中任何不完整的代码都具有有效的执行语义,就像Hazel中的打孔一样。 例如,如果您更改一个函数调用,我们将保留旧函数,直到新函数可用为止。


Dark中的每个程序都有其自身的含义,因此不完整的代码不会干扰完成的工作。


编辑模式


您有两种情况在Dark中编写代码。 第一:您编写新代码,并且是唯一的用户。 例如,它位于REPL中,其他用户将永远无法访问它,或者它是您在任何地方都未引用的新HTTP路由。 您可以在这里工作而无需采取任何预防措施,现在您即将在开发环境中工作。


第二种情况:该代码已被使用。 如果流量通过代码(函数,事件处理程序,数据库,类型)传递,则必须小心。 为此,我们阻止了所有使用的代码,并要求使用结构更丰富的工具来对其进行编辑。 我将在下面讨论结构性工具:用于HTTP和事件处理程序的功能开关,用于数据库的强大迁移平台以及用于功能和类型的新版本控制方法。


功能开关


消除 Dark中额外复杂性的一种方法是用一种解决方案解决几个问题。 功能开关执行许多不同的任务:替换本地开发环境,git分支,部署代码,当然还有传统的缓慢而受控的新代码发布。


功能开关的创建和部署是在我们的编辑器中一次完成的。 它为新代码创建了一个空白空间,并提供了对旧代码和新代码的访问控制,以及用于逐步过渡到新代码或将其排除的按钮和命令。


功能开关内置于Dark语言中,即使不完整的开关也可以执行其任务-如果不满足开关中的条件,则将执行旧的被阻止的代码。


开发环境


功能开关代替本地开发环境。 如今,团队难以确保每个人都使用相同版本的工具和库(代码格式化程序,lint,软件包管理器,编译器,预处理器,测试工具等)。使用Dark,您无需在本地安装依赖项,控制Docker的本地安装或采取其他措施,至少确保发展环境与生产之间的相似性。 鉴于这种平等仍然是不可能的 ,我们甚至不会假装我们正在为此而努力。


Dark中的交换机没有创建克隆的本地环境,而是在生产环境中创建了一个新的沙箱,以替换开发环境。 将来,我们还计划为应用程序的其他部分(例如,即时数据库克隆)创建一个沙箱,尽管目前看来这并不那么重要。


分支机构和部署


现在,有几种方法可以将新代码输入系统:git分支,部署阶段和功能开关。 它们解决了工作流不同部分中的一个问题:git-部署之前的阶段,部署-从旧代码过渡到新代码时,以及功能切换-用于新代码的受控发布。


最有效的方法是功能开关(同时最容易理解和使用)。 有了它们,您可以完全放弃其他两种方法。 删除部署特别有用-如果我们仍然使用功能开关来包含代码,则将服务器转移到新代码的步骤只会带来不必要的风险。


Git很难使用,特别是对于初学者,它确实限制了它,但是它具有方便的分支。 我们已经消除了许多git缺陷。 Dark可以进行实时编辑,并具有以Google Docs样式一起工作的功能,因此您不必发送代码,并且可以减少重新定位和合并的频率。


功能开关是安全部署的基础。 与即时部署一起使用,它们使您能够以低风险快速测试小片段中的概念,而无需进行可能导致系统瘫痪的重大更改。


版本控制


要更改功能和类型,我们使用版本控制。 如果要更改功能,Dark会创建此功能的新版本。 然后,您可以使用HTTP或事件处理程序中的开关来调用此版本。 (如果此函数在调用图中很深,则会在此过程中创建每个函数的新版本。它看起来太多了,但是如果您不使用它们,它们不会相互干扰,因此您甚至都不会注意到它。)


出于相同的原因,我们是版本控制类型。 在上一篇文章中,我们详细讨论了类型系统。


通过版本控制功能和类型,您可以逐渐对应用程序进行更改。 您可以验证每个处理程序都适用于新版本,不需要立即对应用程序进行所有更改(但是,如果您愿意,我们有工具可以快速执行此操作)。


这比现在立即一次部署所有内容要安全得多。


新软件包版本和标准库


在Dark中更新软件包时,我们不会立即在整个代码库中替换每个函数或类型的使用。 这不安全。 该代码继续使用与以前相同的版本,并且使用开关针对每种情况将功能和类型的使用更新为新版本。



Dark中自动过程的一部分的屏幕快照,显示了Dict :: get函数的两个版本。 Dict :: get_v0返回类型Any(我们拒绝),而Dict :: get_v1返回类型Option。


我们通常在标准库中提供一项新功能,并排除旧版本。 在代码中具有旧版本的用户将保留对其的访问权限,但新用户将无法获得它们。 我们将提供工具,一步一步将用户从旧版本转移到新版本,然后再次使用功能开关。


Dark还提供了一个独特的机会:一旦执行了您的工作代码,我们就可以自己测试新版本,比较输出的新旧请求,以告知您有关更改的信息。 结果,通常盲目地执行(或要求严格的安全测试)的程序包更新所带来的风险要少得多,并且可以自动发生。


新黑暗版本


从Python 2到Python 3的过渡已经进行了十多年,但仍然是一个问题。 一旦我们创建了Dark进行连续交付,就需要考虑这些语言更改。


当我们对语言进行小的更改时,我们将创建新版本的Dark。 旧代码保留在Dark的旧版本中,新代码用于新版本中。 要切换到新版本的Dark,可以使用功能的开关或版本。


考虑到最近出现了Dark,这特别有用。 语言或库的许多更改可能会失败。 该语言的逐步版本控制使我们可以进行较小的更新,也就是说,在拥有更多用户并因此获得更多信息之前,我们不能急于推迟关于该语言的许多决定。


数据库迁移


有一个用于安全数据库迁移的标准公式


  • 重写代码以支持新旧格式
  • 将所有数据转换为新格式
  • 删除旧数据访问

结果,数据库迁移被延迟并且需要大量资源。 而且我们正在积累过时的方案,因为即使是简单的任务,例如更正表或列的名称,也不值得付出努力。


Dark拥有一个有效的数据库迁移平台,我们希望该平台将简化流程,以至于您不再担心。 Dark中的所有数据存储(键值对或持久性哈希表)均为类型。 要迁移数据仓库,您只需为其分配新的类型以及回滚和回滚功能即可在两种类型之间转换值。


在Dark中,通过版本化变量名称访问数据仓库。 例如,Users数据存储最初将被称为Users-v0。 创建具有不同类型的新版本时,名称将更改为Users-v1。 如果数据是通过Users-v0保存的,并且您是通过Users-v1进行访问的,则将应用翻转功能。 如果数据是通过Users-v1保存的,而您是通过Users-v0访问的,则使用回滚功能。



数据库迁移屏幕,其中包含旧数据库的字段名称,回滚和回滚表达式以及启用迁移的说明。


使用功能开关将到Users-v0的呼叫路由到Users-v1。 您可以一次执行一个HTTP处理程序以降低风险,并且这些开关还适用于单个用户,以便您可以验证所有功能均按预期工作。 如果不保留Users-v0,则Dark会将背景中的所有剩余数据从旧格式转换为新格式。 您甚至不会注意到它。


测试中


Dark是一种具有静态类型和不可变值的功能编程语言 ;因此,与具有动态类型的面向对象的语言相比,Dark的测试范围要小得多。 但是您仍然需要测试。
在Dark中,编辑器会在后台自动运行可编辑代码的单元测试,默认情况下会为所有功能开关运行这些测试。 将来,我们希望使用静态类型来自动模糊代码以查找错误。


此外,Dark在生产中运行您的基础架构,这开辟了新的可能性。 我们自动将HTTP请求保存在Dark基础结构中(目前,我们保存了所有请求,但随后我们希望切换到获取)。 我们在它们上测试新代码并进行单元测试,并且,如果您愿意,您可以轻松地将有趣的查询转换为单元测试。


我们摆脱了什么


由于我们没有部署,但是有功能开关,因此约有60%的部署管道仍然在外。 我们不需要git分支或池请求,构建后端资源和容器,将资源和容器发送到Kubernetes中的注册表或部署步骤。



比较标准连续输送管道(左)和深色连续供应(右)。 在Dark中,交付过程包括6个步骤和一个循环,而传统版本包括35个步骤和3个循环。


在Dark,部署中只有6个步骤和1个周期(这些步骤重复了几次),而现代的连续供应管道则由35个步骤和3个周期组成。 在Dark中,测试会自动运行,您甚至看不到它; 依赖项会自动安装; 不再需要与git或github相关的任何内容; 无需收集,测试和发送Docker容器; 不再需要Kubernetes部署。


甚至《黑暗》中的其余步骤也变得更加容易。 由于功能开关可以在一个动作中进行控制,因此您无需再次遍历整个部署管道即可删除旧代码。


我们尽可能简化了代码交付,从而减少了时间和连续交付的风险。 我们还大大简化了软件包更新,数据库迁移,测试,版本控制,依赖项安装,开发环境与生产之间的等同性以及快速安全的语言版本升级。


我在HackerNews上回答有关此问题。


要了解有关Dark设备的更多信息,请阅读Dark文章在Twitter (或上关注我们 ,或注册Beta版并接收有关以下帖子的通知 。 如果您9月份要来StrangeLoop,请参加我们的发布会

Source: https://habr.com/ru/post/zh-CN462027/


All Articles