JavaEE解决方案配置最佳实践

我们构建3层企业解决方案,通常由几个webapp和ejbjar模块组成,这些模块都与​​数据库通信并具有多个外部集成点。

每个模块通常都需要自己的配置,可以改变解决方案的生命周期。 部署它变成了一场噩梦,因为现在我们有18个属性文件,必须记住这些文件才能复制并配置为设置数据源,队列,内存要求等。

我希望能有更好的方式,但不乐观。 我们考虑/使用的一些选项,每个选项都有它的优点和缺点:

  1. 使用多个maven项目和持续集成(例如,hudson或jenkins)来构建一个配置jar,其中包含每个环境(dev,qa,prod)的所有属性文件,然后将所有内容捆绑为EAR。 但是,在需要时,生产中的事情不容易改变。
  2. 将大多数设置放在数据库中,并有一个简单的屏幕来修改它。 在内部,我们可以拥有一个可以读取和修改值的通用配置服务EJB。 每个模块都可以拥有一个具有特定getter和setter的自定义扩展版本。
  3. 版本控制所有属性文件,然后在生产时检查它,并在进行更改后将其检入生产分支。

有了所有这些,你仍然需要以容器特定的方式配置数据源和队列等:(

用户一个简单的数据库表(Section,Key,Value)。 如果需要,添加“Version”,并使用getInt(String section, String key)等方法将整个事物包装在一个简单的ConfigurationService类中

不是很多工作,它使应用程序代码非常整洁,并且使用配置进行调整非常容易。

  1. Сonsider将自定义配置对象绑定到JNDI 。 然后在应用中查找此对象以进行配置。 好处 – 您可以使用自定义配置对象而不是通用的MapProperties
  2. 另一种方法是使用JMX配置您需要的应​​用程序。 好处 – 您可以将必须​​直接配置的对象绑定到MBean Server ,然后使用jconsolevisualvm等众所周知的工具来配置应用程序的组件。

两种方式都支持在运行时动态重新配置应用程序。 我更喜欢使用JMX

我已经经历了几个寻找方法的周期。 我仍然没有明确的答案。

最后一个循环以一个基于属性文件的进程结束。 我们的想法是每个服务器实例都配置了一个配置所有内容的属性文件。 该文件由启动脚本读取,用于设置内存参数,由应用服务器和应用程序本身读取。

但关键是这个文件不是直接管理的。 相反,它是构建过程的产物。 我们有一系列用于不同目的的文件,保存在版本控制中,以及合并相应文件的构建步骤。 这使您可以分解沿各个轴共享的共性。

例如,我们有开发,持续集成,QA,UAT,登台和生产环境,每个环境都有自己的数据库。 不同环境中的服务器需要不同的数据库设置,但给定环境中的每个服务器都使用相同的设置。 所以,有一些像development-db.properties,qa-db.properties等等。 在每个环境中,我们有几种服务器 – Web服务器,内容管理服务器,批处理服务器等。每个服务器都有JVM设置,堆大小等等,与其他类型的服务器不同,但是服务器之间是一致的环境。 所以,我们有类似web-jvm.properties,cms-jvm.properties,batch-jvm.properties等等。 我们还有一种方法可以覆盖特定的系统 – production-cms-jvm.properties。 我们还有一个common.properties来设置公共属性,以及可以在需要时覆盖的合理默认值。

我们的构建过程实际上比从每组中选择正确的选项要复杂一些; 我们为每个环境中的每个服务器都有一个主文件,指定要包含的其他文件。 我们允许文件指定要包含的其他文件,因此我们可以构建导入图以最大化重用。

结果很复杂。 我觉得太复杂了。 但它确实有效,它确实使得以受控方式对许多服务器进行更改非常非常容易。 我们甚至合并了一组来自开发的输入文件,另一组来自包含敏感信息的操作。 这是一种非常灵活的方法。

我知道这已经得到了解答,我的答案不一定是通用的,但这是我对事物的看法:

注意,这里我只考虑系统/资源属性,而不是应用程序设置。 在我看来,应用程序设置(例如支付阈值或其他设置应存储在数据库中,以便可以重新配置系统,而无需重新启动服务或通过重新部署或重新读取属性文件导致停机) 。

对于影响系统的不同部分如何相互连接的设置(例如Web服务端点等),我会使用JNDI树。

然后,可以使用Websphere控制台设置数据库连接和JMS连接,并可由Websphere管理员进行管理。 这些也可以创建为JACL脚本,必要时可以将其置于版本控制中。

除了JNDI资源之外,对于其他属性,例如对后端的Web服务调用的用户名等,我将使用Websphere“Name Space Bindings”。 可以使用Websphere控制台编辑这些绑定,并使用“cell / persistent / mypassword”名称通过JNDI访问这些绑定。

所以我可以创建“mypassword”绑定(一个字符串),它的管理属于Websphere管理员(远离开发人员眼睛或其他不应该访问生产系统的人),同时可以使用相同的EAR文件关于开发,测试,预生产和生产(对于不同的系统,最好有不同的EAR文件,因为其他差异蔓延的可能性降低)。

然后,Java代码将使用简单的JNDI查找(并可能将值缓存在内存中)。

属性文件的优点:

  • 由于系统属性包含密码,因此没有需要保护的“易受攻击”文件。
  • 无需添加Java安全策略即可访问该文件位置

优于数据库属性的优点:

  • 与将一个数据库绑定到应用程序服务器无关。

希望有所帮助

使用多个maven项目和持续集成(例如,hudson或jenkins)来构建一个配置jar,其中包含每个环境(dev,qa,prod)的所有属性文件,然后将所有内容捆绑为EAR。 但是,在需要时,生产中的事情不容易改变。

我认为配置应该在应用程序实例的数据库中。 您的本地计算机配置可能与开发人员和QA,PROD,DR等不同。

您需要的是一种以简单的方式将配置输出数据库的方法。

我创建了一个单独的项目,其中提供了Apache commons配置的依赖关系。它有许多存储数据的方法,但我喜欢数据库,配置存在于数据库环境中。

  import javax.sql.DataSource; import org.apache.commons.configuration.DatabaseConfiguration; public class MYConfig extends DatabaseConfiguration { public MYConfig(DataSource datasource) { super(datasource, "TABLE_CONFIG", "PROP_KEY", "PROP_VALUE"); } } 

将大多数设置放在数据库中,并有一个简单的屏幕来修改它。 在内部,我们可以拥有一个可以读取和修改值的通用配置服务EJB。 每个模块都可以拥有一个具有特定getter和setter的自定义扩展版本。

Commons配置作为一个简单的API,然后您可以根据需要编写GUI。 您可以随意进行界面操作。 或者快速获胜没有界面。

版本控制所有属性文件,然后在生产时检查它,并在进行更改后将其检入生产分支。

版本控制很棒。 使用合成添加另一个DatabaseConfiguration。 您扩展的类是活动配置,组成的是审计。 还有另一个构造函数可以拥有一个版本。 只需重载正确的方法即可获得所需的效果。

  import javax.sql.DataSource; import org.apache.commons.configuration.DatabaseConfiguration; public class MYConfig extends DatabaseConfiguration { final DatabaseConfiguration audit; public MYConfig(DataSource datasource) { super(datasource, "TABLE_CONFIG", "PROP_KEY", "PROP_VALUE"); audit = new DatabaseConfiguration("TABLE_CONFIG_AUDIT", "PROP_KEY", "PROP_VALUE"); } @Override public void addProperty(String key, Object value) { Object wasValue = super.getProperty(key); super.addProperty(key, value); audit.put(key,wasValue);//add version code } } 

http://commons.apache.org/proper/commons-configuration/

有趣的替代配置文件格式:写一个scala特征。 然后,您的配置文件可以只是一个scala文件,您可以在服务器启动时编译和评估该文件。 http://robey.lag.net//2012/03/26/why-config.html