您如何在不同的暂存环境中维护 java webapps?
Posted
技术标签:
【中文标题】您如何在不同的暂存环境中维护 java webapps?【英文标题】:How do you maintain java webapps in different staging environments? 【发布时间】:2010-09-10 18:32:02 【问题描述】:您可能有一组用于开发人员计算机的属性,这些属性因开发人员而异,另一组用于暂存环境,另一组用于生产环境。
在 Spring 应用程序中,您可能还希望在本地环境中而不是在生产环境中加载 bean,反之亦然。
你如何处理这个问题?您是否使用单独的文件、ant/maven 资源过滤或其他方法?
【问题讨论】:
【参考方案1】:我将 Ant 的副本与过滤器文件一起使用。 在带有变量的配置文件的目录中,我有一个目录,其中包含每个环境的文件。构建脚本知道环境并使用正确的变量文件。
【讨论】:
【参考方案2】:我只是为每台机器使用不同的 Spring XML 配置文件,并确保从这些 Spring 配置文件加载的 bean 引用了机器之间不同的所有配置数据位。
例如,我有一个连接到另一个应用程序的 Java RMI 接口的 web 应用程序。我的应用程序通过在 Spring XML 配置文件中配置的 bean 获取另一个应用程序的 RMI 接口的地址。我的应用程序和另一个应用程序都有开发、测试和生产实例,因此我的应用程序有三个配置文件——一个对应于适合生产实例的配置,一个用于测试实例,一个用于开发实例实例。
然后,我唯一需要明确的是哪个配置文件被部署到哪台机器上。到目前为止,我对创建 Ant 任务的策略没有任何问题,这些任务在生成我的 WAR 文件之前处理将正确的配置文件复制到适当的位置;因此,在上面的示例中,我有三个 Ant 任务,一个生成生产 WAR,一个生成开发 WAR,一个生成测试 WAR。所有三个任务都将正确的配置文件复制到正确的位置,然后调用相同的下一步,即编译应用程序并创建 WAR。
希望这有点道理......
【讨论】:
有道理,和我正在做的事情非常相似。一个 ant task 用于 stage,一个用于生产,并且仅使用默认值进行本地开发。但是痛苦来自维护 3 个不同的应用程序上下文,它们具有几乎相同的内容.. Spring ApplicationContext 的大多数(全部?)子类都为 XML 配置文件提供一组位置,这样您就可以将常量信息放在一个文件中,将变量信息放在单独的文件中,然后通过多个上下文的构造函数。这有帮助吗?【参考方案3】:单独的配置文件,存储在源代码控制存储库中并手动更新。通常配置不会在一个版本和下一个版本之间发生根本变化,因此同步(即使是手动同步)并不是真正的主要问题。
对于生产环境中高度可扩展的系统,我会认真推荐一种方案,其中配置文件保存在模板中,作为构建脚本的一部分,这些模板用于呈现“最终”配置文件(所有环境都应该使用相同的进程)。
【讨论】:
我喜欢“模板”方法,但是当您不使用 ant/maven 并且仅使用 IDE 的默认值运行应用程序时,它会中断,或者? 我支持模板的建议,如果您为多个不同的生产部署部署了一个应用程序,这也很有用。我使用 ant、velocity 和 VPP 构建了一个模板系统。 我相信用maven的资源过滤可以完成这种模板化的方法? 如何使用 Spring 占位符而不是模板,并在部署期间将特定于主机的配置文件重命名为包含的文件名。 创建模板有什么意义?如果您将变量放入模板并在构建过程中将其替换为具体值 - 为什么不将这些变量放入配置文件并将模板中的定义放入 spring 配置中?【参考方案4】:我有不同的配置文件夹保存目标部署的配置,我使用 ANT 选择在文件复制阶段使用的一个。
【讨论】:
【参考方案5】:我们使用特定于环境的属性文件,并让 ant 构建在构建 jars/wars 时选择正确的设置。
环境特定的事情也可以通过目录服务 (JNDI) 来处理,具体取决于您的应用服务器。我们使用 tomcat,我们的 DataSource 是在 Tomcat 的只读 JNDI 实现中定义的。 Spring 使查找变得非常容易。
我们还使用 ant 策略从同一个源项目构建不同的站点(不同的内容、安全角色等)。
有一点让我们在使用这种构建策略时遇到了一些麻烦,那就是文件和目录通常在构建运行之前不存在,因此很难编写真正的集成测试(使用与部署时相同的弹簧设置)可在 IDE 中运行。您还错过了一些 IDE 检查文件是否存在等的能力。
【讨论】:
如果我理解正确:您为每个环境构建不同的 WAR?这不是一种反模式吗?【参考方案6】:我只是把各种属性放在 JNDI 中。这样每个服务器都可以配置,我可以有一个war文件。 如果属性列表很大,那么我将在另一台服务器上托管属性(或 XML)文件。我将使用 JNDI 来指定要使用的文件的 URL。
如果您为每个环境创建不同的应用程序文件 (war/ear),那么您部署的不是您正在测试的同一个 war/ear。
在我的一个应用程序中,我们使用了多个 REST 服务。我只是将根 url 放在 JNDI 中。然后在每个环境中,可以将服务器配置为与该环境的适当 REST 服务进行通信。
【讨论】:
【参考方案7】:我们针对不同的环境使用不同的 ant 目标。我们这样做的方式可能有点不雅,但它确实有效。我们将告诉某些 ant 目标过滤掉不同的资源文件(这是您可以排除某些 bean 被加载的方式),加载不同的数据库属性,并将不同的种子数据加载到数据库中。我们并没有真正的 ant 专家,但我们可以通过单个命令运行具有不同配置的构建。
【讨论】:
【参考方案8】:我见过的一种解决方案是配置登台环境,使其与生产环境相同。这意味着每个环境都有一个具有相同 IP 范围的 VLAN,以及相同 IP 地址上的机器角色(例如,每个环境中的数据库集群 IP 始终为 192.168.1.101)。防火墙将面向外部的地址映射到 Web 服务器,因此通过在您的 PC 上交换主机文件,可以使用相同的 URL - http://www.myapp.com/webapp/file.jsp 将进入暂存或生产,具体取决于您交换的主机文件。
我不确定这是一个理想的解决方案,维护起来相当繁琐,但值得注意的是一个有趣的解决方案。
【讨论】:
有趣。但是您可能有不想在暂存环境中运行的侦听器或服务,但它们仍会使用这种方法运行,对吧?【参考方案9】:Caleb P 和 JeeBee 可能有您最快的解决方案。此外,您不必设置不同的服务或指向不同机器上的文件。您可以通过使用 $user.name 变量或在 Ant 或 Maven 的 -D 参数中指定配置文件来指定您的环境。
此外,在此设置中,您可以拥有一个通用属性文件,并为特定环境覆盖属性文件。 Ant 和 Maven 都支持这些功能。
【讨论】:
【参考方案10】:我使用 Maven 过滤掉项目中 src/main/resources 下的资源。我将它与属性文件结合使用,以在基于 Spring 的项目中引入自定义属性。
对于默认构建,我的主目录中有一个属性文件,然后 Maven 将其用作覆盖(因此可以正确找到我的本地 Tomcat 安装之类的东西)。测试服务器和生产服务器是我的其他配置文件。只需一个简单的-Pproduction
即可为我的生产服务器构建应用程序。
【讨论】:
【参考方案11】:不要忘记调查 PropertyPlaceholderConfigurer - 这在 JNDI 不可用的环境中特别有用
【讨论】:
【参考方案12】:我最近还将 Maven 用于实时或临时环境的替代配置。 Production configuration using Maven Profiles。希望对您有所帮助。
【讨论】:
【参考方案13】:使用不同的属性文件并使用 ant replace 过滤器,它将根据构建完成的环境进行替换。 见http://www.devrecipes.com/2009/08/14/environment-specific-configuration-for-java-applications/
【讨论】:
以上是关于您如何在不同的暂存环境中维护 java webapps?的主要内容,如果未能解决你的问题,请参考以下文章