我应该在应用程序中还是在应用程序服务器中定义数据源?
Posted
技术标签:
【中文标题】我应该在应用程序中还是在应用程序服务器中定义数据源?【英文标题】:Should I define datasources in application or in app server? 【发布时间】:2015-11-04 23:46:53 【问题描述】:我与两个不同的团队一起开发了应用程序(在 Jboss 服务器上运行)。一个团队在应用程序 WAR 文件中拥有数据源配置,而另一个团队在应用服务器的standalone.xml 中拥有它。而且我不确定哪种方法更好。
所以,我在服务器的standalone.xml 中定义数据源时发现了一些优点。
在服务器的standalone.xml 中定义数据源比在war 文件中更安全。如果数据库连接凭据存储在服务器的standalone.xml 中,几乎从不修改,它比在war 文件中保存密码更安全,war 文件通常从开发人员的机器传输到服务器,并且数据库配置由所有开发人员传播电脑。 通过在standalone.xml 中包含数据源,我们可以使war 文件更小,因为JDBC 驱动程序可以作为模块安装并且可以从war 文件中删除。此外,将 JDBC 作为模块加载比从类路径加载更有效。 如果我们不希望应用程序开发团队知道数据库连接设置,我们可以将数据源放在standalone.xml 中。通过在应用程序 WAR 文件中进行数据源配置,我看到了以下优势:
开发团队无权更改运行 Jboss 的环境中的 Jboss 配置文件。所以数据库连接只能在应用中定义。 在开发状态下很有用,开发者经常需要在不同的数据库连接之间切换。例如,开发者可以在构建 WAR 文件时指定连接。所以我想知道这两种方法是否还有其他优势。您认为哪种方法更好?
【问题讨论】:
【参考方案1】:对我来说,将所有数据源配置从 war 文件中取出的第一大好处是易于部署。
如果我正确阅读了您的问题,那么如果您在构建中包含任何配置,您就无法将完全相同的构建部署到多个环境。一个直接的含义是您永远无法将 DEV 构建部署到 QA,更重要的是,您无法将 QA 构建部署到 PROD 或 UAT。如果您的流程被审计,这可能会让人头疼。
如果我误解了你的问题,请告诉我,否则,我希望这会有所帮助。
【讨论】:
你已经正确理解了这个问题。我同意你的说法,我们不能在不同的环境中部署相同的构建。 谢谢!很高兴我能做出贡献。祝你的项目好运。【参考方案2】:为了正确验证您的应用程序是否正常工作,您应该在将其发送到生产环境之前在暂存服务器中进行尝试。
在这种情况下,您安装到生产环境中的 war 文件应该与您测试的相同,因此您无需更改任何内容即可让应用程序在具有不同数据库连接的不同环境中工作。
因此,数据库配置不应在 war 文件中,而应在应用程序服务器中。此外,您可以让系统管理员的工作更轻松,因为他们无需操纵(解压缩和更改)您的 war 即可将其安装到服务器中。
在应用程序的早期开发阶段,添加数据库(和任何其他开发配置)以减少开发人员无需配置即可投入项目并开始编程的时间会很有用开发应用程序服务器中的应用程序。
【讨论】:
【参考方案3】:我赞成让应用程序服务器公开数据源,但要注意。 您需要您的开发团队至少知道他们使用您的应用程序服务器的方式,或者至少可以访问 jboss 控制台以查看配置或更改它。 原因是例如他们需要监视数据源连接池的连接使用情况。由于您在谈论 jboss,我不知道带有 jboss AS 的数据源的“实时”bean 是否在本机公开了相同的信息例如 oracle ucp(ucp .getStatistics 是一个上帝发送的原因不止一个......)。
考虑一下,即使您在 xml 中内部化数据源,使用配置文件的概念,您也可以根据加载应用程序的配置文件在一个或另一个属性文件中“填充”某个特定值的 xml 字段..
例如,春天你肯定可以做到
<beans profile="local">
<bean id="dataSource" class="oracle.ucp.jdbc.PoolDataSourceFactory" factory-method="getPoolDataSource">
<property name="URL" value="jdbc:oracle:thin:@db00-ccea.labucs.int:1521:CCEA"/>
<property name="user" value="myuser_DCI"/>
<property name="password" value="mypassword_DCI"/>
<property name="connectionFactoryClassName" value="oracle.jdbc.pool.OracleConnectionPoolDataSource"/>
<property name="connectionPoolName" value="$name.connection.pool"/>
<property name="minPoolSize" value="5"/>
<property name="maxPoolSize" value="1000"/>
<property name="maxIdleTime" value="3000"/>
<property name="maxStatements" value="3000"/>
<property name="validateConnectionOnBorrow" value="true" />
<property name="inactiveConnectionTimeout" value="3000" />
<property name="connectionWaitTimeout" value="3000"/>
<property name="abandonedConnectionTimeout" value="3000"/>
<qualifier value ="dataSourceDCI" />
</bean>
<orcl:pooling-datasource id="dataAltSource"
url="jdbc:oracle:thin:@db00-ccea.labucs.int:1521:CCEA" username="some_OWN" password="some_OWN"/>
<util:properties id="flyway.prop" location="classpath:config_local.properties"/>
</beans>
在本地配置文件上的含义是从类路径中的 config_loca.properties 文件中加载属性
也有
<beans profile="qa">
<bean id="dataSource" class="oracle.ucp.jdbc.PoolDataSourceFactory" factory-method="getPoolDataSource">
<property name="URL" value="jdbc:oracle:thin:@db00-ccea.labucs.int:1521:CCEA"/>
<property name="user" value="myuserQA_DCI"/>
<property name="password" value="myuserQA_DCI"/>
<property name="connectionFactoryClassName" value="oracle.jdbc.pool.OracleConnectionPoolDataSource"/>
<property name="connectionPoolName" value="$name.connection.pool"/>
<property name="minPoolSize" value="5"/>
<property name="maxPoolSize" value="1000"/>
<property name="maxIdleTime" value="3000"/>
<property name="maxStatements" value="3000"/>
<property name="validateConnectionOnBorrow" value="true" />
<property name="inactiveConnectionTimeout" value="3000" />
<property name="connectionWaitTimeout" value="3000"/>
<property name="abandonedConnectionTimeout" value="3000"/>
<qualifier value ="dataSourceDCI" />
</bean>
<bean id="dataAltSource" class="oracle.ucp.jdbc.PoolDataSourceFactory" factory-method="getPoolDataSource">
<property name="URL" value="jdbc:oracle:thin:@db00-ccea.labucs.int:1521:CCEA"/>
<property name="user" value="myuserQA_OWN"/>
<property name="password" value="myuserQA_OWN"/>
<property name="connectionFactoryClassName" value="oracle.jdbc.pool.OracleConnectionPoolDataSource"/>
<property name="connectionPoolName" value="$name.connection.pool"/>
<property name="minPoolSize" value="5"/>
<property name="maxPoolSize" value="1000"/>
<property name="maxIdleTime" value="3000"/>
<property name="maxStatements" value="3000"/>
<property name="validateConnectionOnBorrow" value="true" />
<property name="inactiveConnectionTimeout" value="3000" />
<property name="connectionWaitTimeout" value="3000"/>
<property name="abandonedConnectionTimeout" value="3000"/>
</bean>
<util:properties id="flyway.prop" location="file:///$prefix.iam.dir/$filecert.iam.path/external.properties"/>
</beans>
因此,在您的 QA 环境或其他非开发环境中,您改为引用外部 xml 文件,而不是集成在战争中的文件。 如果您担心,您甚至可以通过内部//外部属性文件包含要“填充”的用户名和密码,以增强安全性。
【讨论】:
【参考方案4】:除了问题中提到的几点之外,将数据源置于应用程序之外的另一个优点是它允许在不同区域使用相同的 war 文件。这将允许团队在使用相同的 war 文件时为不同的环境(例如 Test、Perf 和 Prod)拥有不同的数据库。
您可以进行一次部署,然后您的 QA 团队测试过的 war 文件可以提升到生产区域。这将确保没有未经测试的代码进入更高的区域,同时避免 SCM 分叉和代码冻结的需要。
【讨论】:
您已经介绍了我认为将 DS 置于应用之外的优势的关键点。我在较小项目上取得成功的另一种有用但不直接相关的方法是通过环境变量之类的东西在服务器配置中参数化数据源域(假设用于登台、生产等的相同数据库设置)。这允许移动包括应用程序服务器在内的整个堆栈的额外好处,可能用于容器化之类的东西。我绝不是这方面的专家,但它似乎在我有限的使用中运作良好。以上是关于我应该在应用程序中还是在应用程序服务器中定义数据源?的主要内容,如果未能解决你的问题,请参考以下文章
我应该在 Android 应用程序中使用 XML 还是 JSON 作为数据格式?
我应该开发一个单独的快速服务器,还是在我的 next.js 应用程序中处理所有 API 调用?
在android中定义常量的最佳方法是静态类、接口还是xml资源?