17

根据我的经验,我们在 web 开发过程中遇到的一个更大的问题是在不同的服务器上保持不同的设置更新和安全。

我的公司拥有自己的 CMS,目前安装在 100 多台服务器上。目前,我们使用基于 FTP 的黑客方法,结合特定位置的升级脚本来升级我们所有的 CMS 设置。当涉及多个自定义模块时,有效管理这些设置变得越来越困难和风险。

  • 保持 Web 应用程序的多个设置安全和最新的最佳方法是什么?
  • 你是怎么做到的?
  • 是否有任何关于应用程序模块化的具体技巧,以保持对我们客户的灵活性,但仍然能够有效地管理应用程序的多个“分支”?

一些上下文信息:我们主要在 LAMP 堆栈上开发。帮助我们销售 CMS 的主要因素之一是我们几乎可以插入客户想要的任何东西。这可以是 10 到 10.000 行自定义代码。

许多定制工作由非常小的代码组成;在 Subversion 中管理所有这些小段代码对我来说似乎相当乏味和低效(因为我们每周交付大约 2 个网站,这会导致很多分支)。

如果有什么我忽略了,我很想听听你的意见。

提前致谢。


综述:首先,感谢您的所有回答。所有这些都非常有帮助。

我很可能会使用基于 SVN 的方法,这使得benlumley的解决方案最接近我将使用的解决方案。由于这个问题的答案在其他用例中可能会有所不同,因此我将在运行结束时接受得票最多的答案。

请检查答案并投票给您认为具有最大附加值的答案。

4

13 回答 13

8

我认为使用版本控制系统并“分支”您必须修改的代码部分可能会成为健壮性和效率方面的最佳方法。

分布式版本系统可能最适合您的需求,因为它允许您在不同的“分支”上无缝更新您的“核心”功能,同时在需要时将一些更改保留在本地。

编辑:我很确定使用分布式版本系统保持所有最新状态将远没有您预期的那么乏味:您可以保留您确定永远不会在本地其他地方需要的更改,并且分布式方面意味着您部署的每个应用程序实际上都独立于其他应用程序,并且只有您要传播的修复程序才会传播。

于 2009-02-02T15:17:52.473 回答
6

如果定制您的应用程序涉及更改许多小段代码,这可能表明您的应用程序设计存在缺陷。您的应用程序应该具有一组稳定的核心代码、可插入自定义库的扩展点、使用模板更改外观的能力,以及使用配置文件更改行为和安装插件的能力。这样一来,您就不需要为每个客户端创建一个单独的 SVN 分支。相反,将核心代码和扩展插件库照常保存在源代码管理中。在另一个存储库中,为每个客户端创建一个文件夹并将其所有模板和配置文件保存在那里。

目前,创建 SVN 分支可能是帮助您保持理智的唯一解决方案。在您目前的状态下,您几乎不可避免地会犯错误并弄乱客户的网站。至少对于分支,您可以保证每个客户端都有稳定的代码库。SVN 分支的唯一问题是,如果您在分支中移动或重命名文件,则无法将该更改合并回主干(您必须手动进行)。

祝你好运!

编辑:有关使用我上面概述的所有原则的精心设计的应用程序的示例,请参阅Magento E-Commerce。Magento 是迄今为止我使用过的最强大、可扩展且易于定制的 Web 应用程序。

于 2009-02-05T05:58:36.470 回答
4

我可能错了,但在我看来,Aron 追求的不是版本控制。版本控制很棒,我确信他们已经在使用它,但是要管理数百个自定义安装的更新,您需要其他东西。

我在想一些类似于专门构建的包系统的东西。您将希望模块的每个版本都跟踪其各自的依赖关系和“保证的兼容性”,并使用此信息仅自动更新“安全”模块。

例如,假设您已经构建了“Wiki”模块的新版本 3。您希望将新版本传播到运行您的应用程序的所有服务器,但您已经对 Wiki 模块中的一个接口从版本 2 开始进行了更改。现在,对于所有默认安装,这没问题,但它会中断在旧界面之上使用自定义扩展进行安装。一个精心策划的包装系统会解决这个问题。

为了解决安全问题,您应该考虑在补丁上使用数字签名。有很多很好的库可用于基于公钥的签名,所以只要选择似乎是您选择的平台的标准的任何东西。

于 2009-02-05T02:44:53.677 回答
4

不知道是不是有人说的,这里有很多很长的回复,我没有全部看完。

我认为更好的版本控制方法是让您的 CMS 在自己的存储库中独立运行,每个项目都在自己的存储库中。(或者,我猜所有这些都可能是一个仓库中的子文件夹)

然后,您可以在每个需要它的项目中使用它的主干(或者如果您愿意,也可以使用特定的分支/标签)作为 svn:external 。这样,您对 CMS 所做的任何更新都可以提交回其存储库,并在 svn 更新(或外部是 svn:switch 'ed)时被拉入其他项目。

作为使这更容易的一部分,您需要确保 CMS 和自定义功能位于不同的文件夹中,以便 svn externals 正常工作。

IE:

project
 project/cms <-- cms here, via svn external
 project/lib <-- custom bits here
 project/www <-- folder to point apache/iis at

(如果需要,您可以在 www 文件夹下拥有 cms 和 lib)

这将使您可以根据需要对每个项目进行分支/标记。您还可以在每个分支/标签的基础上切换 svn:external 位置。

在实时更改方面,我建议您立即摆脱 ftp 并使用 rsync 或 svn checkout/exports。两者都很好,选择取决于您。

我对 rsync 路由最有经验,将 svn 导出同步到服务器。如果你走这条路,写一些 shell 脚本,你可以创建一个测试 shell 脚本来向你展示它将上传的文件,而不用上传它们,使用 -n 标志。我通常为每个环境使用一对脚本——一个用于测试,一个用于实际执行。

共享密钥身份验证,因此您不需要密码来发送上传也可能很有用,具体取决于授予访问权限的服务器的安全程度。

您还可以维护另一个用于批量升级的 shell 脚本,它只需为要升级的每个项目调用相关的 shell 脚本。

于 2009-02-07T08:50:36.073 回答
2

你看过 Drupal 吗?不,不是为了部署和替换你所拥有的,而是为了看看他们如何处理定制和特定于站点的模块?

基本上,有一个“站点”文件夹,其中包含您托管的每个站点的目录。每个文件夹中都有一个单独的 settings.php,它允许您指定不同的数据库。最后,您可以(可选)在站点中拥有“主题”和“模块”文件夹。

这允许您对特定模块进行特定于站点的自定义,并将某些模块限制在这些站点中。结果,您最终会得到一个网站,其中绝大多数内容都完全相同,只有不同之处被重复。结合它处理升级和更新的方式,你可能会有一个可行的模型。

于 2009-02-02T12:34:49.683 回答
2

在代码中构建一个自我更新的过程。
它将检查更新并在您为客户端配置它的时间/地点/方式运行它们。

您将必须创建某种模块列表(自定义或非自定义),这些模块需要在推出之前使用新版本进行测试。部署更新时,您必须确保正确测试和集成这些更新。希望您的设计可以处理这个问题。

理想情况下,更新是几个关键步骤。

  1. a)备份,以便您可以退出。您应该能够随时退出整个更新。因此,这意味着首先创建应用程序和数据库的本地存档。

    b)更新监控过程- 让 CMS 系统打电话回家寻找新版本。

    c)根据可用性安排更新- 您可能不希望更新在可用的第二个运行。这意味着您必须创建某种类型的 cron/agent 才能在半夜自动进行系统更新。您还可以考虑客户要求在周末或特定日期更新。您还可以错开推出更新,这样您就不会在 1 天内更新 1000 个客户端并获得技术支持。某种形式的交错推出可能对您有益。

    d)添加维护模式以更新站点——将站点踢入维护模式。

    e) SVN checkout 或可下载的软件包——理想情况下,您可以通过 svn checkout 进行部署,如果没有,请设置您的服务器以将 svn 生成的软件包交付到可以部署在客户端站点上的存档中。

    f)部署数据库脚本- 备份数据库、更新它们、填充它们

    g)更新站点代码- 所有这些工作一步。

    h)对其进行一些测试。 如果您的代码内置了自测试,那将是理想的选择。

于 2009-02-09T09:50:46.270 回答
2

这就是我要做的...

特定于客户端的包含路径

  • 共享,通用代码在shared/current_version/lib/
  • 特定于站点的代码位于clients/foo.com/lib
  • 包含路径设置为包含从clients/foo.com/lib,然后share/lib
  • 整个事情都在一个版本控制系统中

这可以确保代码尽可能使用共享文件,但是如果我出于某种原因需要覆盖特定的类或文件,我可以在他们的文件夹中编写客户端特定的版本。

别名公用文件

我的虚拟主机配置将包含一行

Alias /common <path>/shared/current_version/public_html/common

允许跨项目共享通用 UI 元素、图标等

使用每个站点版本标记公共代码

在每个站点发布后,我通过创建一个分支来标记公共代码以有效地冻结该时间点。这允许我将 /shared/version_xyz/ 部署到实时服务器。然后我可以让虚拟主机使用特定版本的公共文件,或者如果我希望它获取最新更新,则让它指向 current_version。

于 2009-02-09T10:15:07.520 回答
1

您是否查看过诸如Puppet(用于系统管理,包括应用程序部署)或Capistrano(在 RubyOnRails 中部署应用程序但不限于这些)之类的工具?

于 2009-02-02T10:35:53.137 回答
1

一种选择是设置只读版本控制系统(Subversion)。您可以将对存储库的访问集成到您的 CMS 中并通过菜单调用更新,或者如果您不希望用户选择更新(可能很关键),则可以自动调用更新。使用版本控制系统还可以让您轻松地保留不同的分支

于 2009-02-02T10:36:41.200 回答
1

正如人们已经提到的那样,使用版本控制(由于功能我更喜欢 Subversion)和分支将是最好的选择。sourceforge 上的另一个开源软件叫做 Cruisecontrol。令人惊奇的是,您使用 subversion 配置 Cruisecontrol,这样任何代码修改或在服务器中添加的新代码,Cruise Control 都会自动知道并为您构建。它会节省你的时间。

我在公司也做过同样的事情。我们有四个项目,必须在不同的服务器上部署该项目。我已经设置了 Cruiseconrol,使得代码库中的任何修改都会触发自动构建。另一个脚本将在服务器上部署该构建。你很高兴。

于 2009-02-05T02:27:14.353 回答
1

如果您使用 LAMP 堆栈,我肯定会将解决方案文件转换为您的分发包,并将其用于传播更改。我推荐 Redhat/Fedora 因为 RPM 并且这是我的经验。无论如何,您也可以使用任何基于 Debian 的发行版。

前段时间,我制作了一个 LAMP 解决方案来管理 ISP 托管服务器。他们有多个服务器来处理网络托管,我需要一种方法来部署我的经理的更改,因为每台机器都是独立的并且有一个在线经理。我制作了一个 RPM 包,其中包含解决方案文件(主要是 php)和一些使用 RPM 运行的部署脚本。

对于自动更新,我们在 yum.conf 中的每台服务器上都设置了自己的 RPM 存储库。我设置了一个 crontab 作业,每天使用来自该受信任存储库的最新 RPM 更新服务器。

也可以实现信任,因为您可以在 RPM 包中使用信任设置,例如使用您的公钥文件对其进行签名并仅接受签名包。

于 2009-02-05T03:37:16.957 回答
1

嗯,添加配置文件是个好主意吗?你写了很多小脚本都在做某事。现在,如果您将它们构建到源代码中并使用配置文件引导它们,那不应该“轻松”吗?

另一方面,为每个客户开设分支机构对我来说似乎是指数级增长。你如何“知道”你在哪些领域做了一些事情,并且不要忘记在所有其他分支中也“做出”改变。这对我来说看起来很丑陋。

似乎修订控制、配置选项和/或部署收据的组合似乎是一个“好”的主意.....

于 2009-02-07T08:58:05.123 回答
1

由于您的核心软件有如此多的变化,我认为您确实需要一个版本控制系统来随时将更新从主干推送到各个客户端站点。

因此,如果您认为 Subversion 会很乏味,那么您对痛点会有一个很好的了解……就个人而言,我不会为此推荐 Subversion,因为它在管理和跟踪分支方面并不是那么好。尽管 benlumley 建议为您的核心软件使用外部代码是一个很好的建议,但如果您需要为您的客户站点调整核心代码,这将失效。

查看 Git 的版本控制,它是为分支而构建的,而且速度很快。

查看 Capistrano 以管理您的部署。这是一个 ruby​​ 脚本,经常与 Rails 一起使用,但它可以用于远程服务器上的各种文件管理,甚至是非 ruby​​ 站点。它可以通过包括 ftp、scp、rsync 在内的各种策略将内容发送到远程端,并自动从您的存储库中检出最新版本。它提供的不错的功能包括部署过程的每个步骤的回调挂钩(例如,您可以复制可能不在版本控制中的特定于站点的配置文件),以及一个发布日志系统——通过符号链接完成——所以你如果出现问题,可以快速回滚到以前的版本。

我建议使用包含分支列表及其托管位置的配置文件,然后使用脚本依次检查每个分支并上传最新更改。这可能是 cron'd 自动进行夜间更新。

于 2009-02-09T06:39:54.247 回答