【问题标题】:How to efficiently manage multiple installations of a web application?如何有效地管理 Web 应用程序的多个安装?
【发布时间】:2010-10-04 21:42:35
【问题描述】:

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

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

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

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

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

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

提前致谢。


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

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

请检查答案并投票选出您认为最具附加价值的答案。

【问题讨论】:

  • 这 100 多台服务器在客户位置?
  • 大部分服务器都是内部的(虚拟服务器也是如此),但是当客户要求在他们的服务器上进行设置时,我们会自行制作。跨度>
  • 定制工作是否仅由贵公司完成?或者您的客户是否也可以自行改变?
  • 定制工作始终由我的公司完成。

标签: php web-applications module release-management


【解决方案1】:

这就是我的工作......

客户端特定的包含路径

  • 共享,通用代码在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。

【讨论】:

  • 感谢您的回答,我很欣赏我看到的许多不同的方法!
【解决方案2】:

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

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

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

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

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

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

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

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

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

    g) 更新网站代码 - 一步到位。

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

【讨论】:

    【解决方案3】:

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

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

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

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

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

    【讨论】:

      【解决方案4】:

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

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

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

      【讨论】:

        【解决方案5】:

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

        我认为更好的版本控制方法是让您的 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 脚本。

        【讨论】:

        • 感谢您的回答,我一定会研究这个解决方案!
        【解决方案6】:

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

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

        祝你好运!

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

        【讨论】:

        • 这比分支更具可扩展性和可维护性。将钩子添加到代码中并为钩子建立可扩展的通信协议将使其非常简单。将 Jens Roland 的答案与依赖跟踪结合起来,它会变得容易更新且难以破解。
        • 感谢您的回答和提示,这很有帮助。
        【解决方案7】:

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

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

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

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

        【讨论】:

          【解决方案8】:

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

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

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

          要解决安全问题,您应该考虑在补丁上使用数字签名。有很多不错的库可用于基于公钥的签名,所以只要选择适合您所选平台的标准即可。

          【讨论】:

          • 很好的答案,这是对我问题的直接回答。我一定会调查的。
          【解决方案9】:

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

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

          【讨论】:

            【解决方案10】:

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

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

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

            【讨论】:

              【解决方案11】:

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

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

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

              【讨论】:

                【解决方案12】:

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

                【讨论】:

                  【解决方案13】:

                  您是否看过Puppet(用于系统管理,包括应用部署)或Capistrano(在RubyOnRails 中部署应用但不限于这些)等工具?

                  【讨论】:

                  猜你喜欢
                  • 2011-08-23
                  • 1970-01-01
                  • 1970-01-01
                  • 2023-04-11
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2012-10-15
                  • 1970-01-01
                  相关资源
                  最近更新 更多