给定一个大型软件项目,其中包含用不同语言编写的多个组件、配置文件、配置脚本、环境设置和数据库迁移脚本——部署到生产的常见做法是什么?
有哪些困难需要考虑?可以使用 Ant 或 Maven 等工具简化流程吗?如何处理回滚和数据库管理?是否建议对生产环境使用版本控制?
给定一个大型软件项目,其中包含用不同语言编写的多个组件、配置文件、配置脚本、环境设置和数据库迁移脚本——部署到生产的常见做法是什么?
有哪些困难需要考虑?可以使用 Ant 或 Maven 等工具简化流程吗?如何处理回滚和数据库管理?是否建议对生产环境使用版本控制?
在我看来,您主要是在询问发布工程AKA releng 的最佳实践和工具——了解一个主题的“艺术术语”很重要,因为它使搜索更多信息变得更加容易。
配置管理系统(CMS——又名修订控制系统或版本控制系统)对于当今的软件开发来说是必不可少的;如果您使用一个或多个 IDE,最好在它们与 CMS 之间进行良好的集成,尽管这对于开发目的而言更多是一个问题,而不是出于部署 / releng 的目的。
从 releng 的角度来看,CMS 的关键在于它必须对“分支”(以任何名称)提供良好的支持,因为必须从“发布分支”进行发布,其中所有正在开发的代码及其所有依赖项(代码和数据)在一个稳定的“快照”中,可以随意复制精确、相同的配置。
如果您必须维护多个分支(针对不同的用途、平台等进行定制),则对良好分支支持的需求可能会更加明显,但是即使您的发布始终严格按照单一线性顺序,releng 最佳实践仍然要求制作一个发布分支。“良好的分支支持”包括易于合并(以及对文件进行不同更改时的“冲突解决”),“樱桃采摘”(从一个分支或头部/主干获取一个补丁或变更集,并将其应用于另一个分支)等。
在实践中,你通过创建一个发布分支来开始发布过程;然后,您在该分支上运行详尽的测试(通常比您在持续构建中每天运行的要多得多——包括广泛的回归测试、集成测试、负载测试、性能验证等,甚至可能更昂贵的质量保证过程,具体取决于)。如果详尽的测试和 QA 揭示了候选版本中的缺陷(包括回归、性能下降等),则必须修复它们;在一个大型团队中,在完成 QA 的同时,head/trunk 上的开发可能会继续进行,因此需要易于挑选 / 合并 / 等(无论您的实践是在 head 上还是在发布分支上执行修复,它仍然需要合并到另一边;-)。
最后但并非最不重要的一点是,除非您以某种方式跟踪您的发布所依赖的“所有内容”,否则您不会从您的 CMS 中获得完全的 releng 价值——最简单的方法是拥有工具的所有二进制文件的副本或硬链接您需要构建您的版本等,但这通常是不切实际的;因此,至少要跟踪所使用的那些工具(操作系统、编译器、系统库、将图像、声音或视频文件预处理为最终形式的工具等)的确切版本、版本、错误修复和 c 编号。关键是能够在需要时准确地重现重建建议发布的确切版本所需的环境(否则,您将疯狂地追踪可能依赖于第三方工具更改的细微错误,因为它们版本更改;-)。
在 CMS 之后,releng 的第二个最重要的工具是一个很好的问题跟踪系统——最好是与 CMS 很好地集成的系统。这对于开发过程(以及产品管理的其他方面)也很重要,但就发布过程而言,问题跟踪器的重要性在于能够轻松地准确记录已修复的错误、添加、删除的功能,或更改,以及在即将发布的新版本中预期性能(或其他用户可观察的特征)的哪些修改。为此,开发中的一个关键“最佳实践”是提交给 CMS 的每个变更集都必须连接到问题跟踪系统中的一个(或多个)问题:毕竟,必须有一些该更改的目的(修复错误、更改功能、优化某些内容或某些本应对软件用户不可见的内部重构);同样,标记为“已关闭”的每个跟踪问题都必须连接到一个(或多个)变更集(除非关闭是“无法修复/按预期工作”的类型;与第三方组件中的错误和 c 相关的问题已由第三方供应商修复,如果您确实设法跟踪 CMS 中的所有第三方组件,则很容易进行类似处理,请参见上文;如果您不这样做,至少应该有文本CMS 下记录第三方组件及其演变的文件,再次参见上文,当第 3 方组件上的某些跟踪问题关闭时,需要更改它们)。
自动化各种 releng 流程(包括构建、自动化测试和部署任务)是第三个首要任务——自动化流程比要求一些可怜的人手动完成一系列步骤(对于足够复杂的任务,当然,自动化的工作流程可能需要“让人类参与其中”)。正如您推测的那样,诸如Ant
(和SCons
, etc, etc) 在这里可以提供帮助,但不可避免地(除非你足够幸运地摆脱了非常简单和直接的过程)你会发现自己用临时脚本和 c 来丰富它们(一些强大而灵活的脚本语言,例如perl、python、ruby 和 &c 会有所帮助)。当您的发布工作流程足够复杂时(例如,涉及特定人员或其组“签署”QA 合规性、法律合规性、UI 准则合规性等),“工作流程引擎”也很宝贵。
您询问的其他一些具体问题因环境的具体情况而有很大差异。如果您能负担得起程序化的停机时间,那么即使使用大型数据库,您的生活也会相对轻松,因为您可以按顺序和确定性地操作:您可以优雅地关闭现有系统,确保保存和备份当前数据库(轻松回滚,在极少数情况下需要它),运行用于架构迁移或其他“不可逆”环境更改的一次性脚本,以一般用户仍然无法访问的模式再次启动系统备份,运行另一套广泛的自动化测试- 最后,如果一切顺利(包括在新状态下保存和备份数据库,如果相关),系统将再次开放供一般使用。
如果您需要在不停机的情况下更新“实时”系统,这可能会从轻微的不便到系统性的噩梦。在最好的情况下,事务相当短,事务设置的状态之间的同步可能会延迟一点而不会造成损坏……并且您拥有合理丰富的资源(CPU、存储等)。在这种情况下,您并行运行两个系统——旧系统和新系统——并确保所有新事务都以新系统为目标,同时让旧系统在旧系统上完成。当旧系统上的事务终止时,一个单独的任务会定期将“旧系统中的新数据”同步到新系统。最终,您可以确定旧系统上没有任何事务正在运行,并且那里发生的所有更改都同步到新系统 - 那时您最终可以关闭旧系统。(当然,您也需要准备好“反向同步”,以防需要回滚更改)。
这是直播系统更新的“简单、甜蜜”的极致;在另一个极端,您会发现自己处于过度约束的情况下,以至于您可以证明任务是不可能的(您只是无法在给定资源的情况下从逻辑上满足所有规定的要求)。在旧系统上打开的长时间会话无法终止——稀缺资源导致无法并行运行两个系统——每个事务的硬实时同步的核心要求——等等,都可以让你的生活很悲惨(正如我注意到的那样,在极端情况下,可以使所陈述的任务绝对不可能)。你可以做的最好的两件事:(1)确保你有丰富的资源(当一些服务器意外崩溃时,这也可以节省你的皮肤......你将有另一个可以启动以应对紧急情况! -);
免责声明:在我工作的地方,我们使用我写的东西,我会提到
我会告诉你我是怎么做的。
对于配置设置以及代码和内容的一般部署,我使用了 NAnt、CI 服务器和dashy(一种自动部署工具)的组合。您可以将 dashy 替换为任何其他“东西”,它可以自动上传到您的服务器(可能是capistrano)。
对于 DB 脚本,我们使用 RedGate SQL Compare 来获取脚本,然后对于大多数更改,我实际上是在适当的地方手动制作它们。这是因为有些改动稍微复杂一些,我觉得手工做起来更舒服。您实际上可以使用此工具为您执行此操作,(或至少生成脚本)。
根据您的语言,有一些工具可以为您编写数据库更新脚本(我想这个论坛上有人写了一个;希望他会回复),但我没有这些经验。这是我想添加的东西。
困难
我忘了回答你的一个问题。
更新任何非常复杂/分布式站点的最大问题是数据库同步。您需要考虑是否会有停机时间,如果有,DB 会发生什么情况。你会关闭所有的东西,这样就不能处理任何交易了吗?还是将所有内容转移到一台服务器,更新 DB B,然后同步 DB A 和 B,然后更新 DB B?或者是其他东西?
无论您选择什么,您都需要选择它,或者说“好的,每次更新都会有 X 次停机”,或者其他什么。只需将其记录在案即可。
你能做的最糟糕的事情是让某人的事务在处理过程中失败,因为你正在更新那个服务器;或者以某种方式只保留系统的一部分运行。
我认为您对是否使用版本控制没有任何选择。
您不能没有版本控制(如评论中所述)。
我说的是经验,因为我目前正在一个网站上工作,我们有几个必须一起工作的项目:
这是因为我们使用了版本控制,尽管我必须承认我们的数据库非常简单,并且因为部署是自动化的。
版本控制意味着我们实际上在任何时间点都有消息、数据库、静态资源和 Java 小程序的多个并发版本。
在“回退”的情况下尤其重要。如果你在加载新软件的时候发现了一个漏洞,突然加载不起,如果没有版本化,你就会有危机,如果有,你只需要加载旧软件。
现在正如我所说,部署是脚本化的:-首先部署静态资源(+ java小程序)-接下来是数据库,几个配置共存,因为它们是版本化的-软件在“酷”时间排队等待加载-窗户(当我们的交通处于最低点时,所以在晚上)
当然,我们会处理与外部服务器的向后/向前兼容性问题,这一点不容小觑。