在运行时添加新的DataSource

时间:2015-08-03 17:12:53

标签: java jdbc connection-pooling spring-jdbc

我不是一个非常有经验的java程序员,可能会有非常简单的问题。在我描述问题之前,让我解释一下这个架构:

  1. 我们需要云中的应用
  2. 我们有四个客户,每个客户都有自己的MySQL数据库实例(总共4个数据库)。这主要是出于政治原因和一些性能原因(某些读取最多需要20秒执行,INSERT语句每隔一秒或两秒执行一次)
  3. 该应用程序将在两个VM实例上运行以进行故障转移和更好的性能,即。 DataSource将是动态的,因为两个应用程序实例中的任何一个都可以定位其中一个数据库实例
  4. 我们计划为所有客户提供一个配置数据库,用作应用程序的内部存储库。在这里,我们维护用户和其他配置,活动监控等
  5. 每当我们添加新客户时,都不应该重新启动应用程序,因此配置数据库。在这个数据库中,我们计划为每个用户保留一个DataSource,并在调用RESTful服务时执行查找(可以称之为无状态DataSource)。唯一要做的就是添加新的MySQL实例 我们使用的主要框架/工具是java,Spring(JdbcTemplate),HikariCP(JDBC连接池)和Tomcat。

    我们有以下问题:

    1. 连接池和javax.sql.DataSource之间的关系是什么,即。因为我们计划为每个RESTful方法调用重新创建DataSource,这会将现有的连接池销毁到数据库X吗?
    2. 在配置数据库中指定DataSource时,在Spring中实现动态DataSource的最佳方法是什么(我读过以下link解释配置文件中定义的动态DataSource,不支持在运行时添加新的源)

    3. 亲切的问候 A.H。

2 个答案:

答案 0 :(得分:0)

  

连接池和javax.sql.DataSource之间的关系是什么,即。因为我们计划为每个RESTful方法调用重新创建DataSource,这会破坏现有的连接池到数据库X吗?

数据库连接池不一定是JDBC构造。相反,出现了JDBC DB连接池的各种实现。 Tomcat一个特别可能不容易用于添加动态运行时DataSources(我自己没有这样做,所以不确定)。但是还有其他的存在允许这样做。例如,vibur是一个DB连接池,允许用户在运行时添加DataSource。

public DataSource createDataSourceWithStatementsCache() {
    ViburDBCPDataSource ds = new ViburDBCPDataSource();

    ds.setJdbcUrl("jdbc:hsqldb:mem:sakila;shutdown=false");
    ds.setUsername("sa");
    ds.setPassword("");

    ds.setPoolInitialSize(10);
    ds.setPoolMaxSize(100);

    ds.setConnectionIdleLimitInSeconds(30);
    ds.setTestConnectionQuery("isValid");

    ds.setLogQueryExecutionLongerThanMs(500);
    ds.setLogStackTraceForLongQueryExecution(true);

    ds.setStatementCacheMaxSize(200);

    ds.start();
    return ds;
}   

那种方法来自振动website。我过去在性能关键应用程序中使用它们取得了巨大成功。可能是连接池将检测到重复项,但如果不是,您可以在该方法中添加一些HashSet检查以查看具有该用户名/ pw / connectionString的DataSource是否已存在。

  

在配置数据库中指定DataSource时,在Spring中实现动态DataSource的最佳方法是什么(我确实阅读了以下链接,解释了配置文件中定义的动态DataSource,不支持在运行时添加新源)

过去我曾经在一个必须使用运行时DataSources的项目上工作。这并不难。这就是我们这样做的方式。您基本上只需要一个包含连接字符串的表,驱动程序(如果需要多个数据库并且驱动程序是动态加载的,可能不是您的问题)和凭据。您可以使用更多属性(如连接数等等)来增强表格。然后,您只需要一个可用于查找此信息的ID。

当请求进入时,您可以检查从请求获取数据库ID或从缓存源或任何地方进行轮询。然后使用该DB ID,您可以使用上述方法查找数据库连接信息并创建DataSource。显然你会使用缓存来避免数据库调用...这些数据非常静态,不需要在每次请求时检索。

答案 1 :(得分:0)

也许这会有所帮助:

public static DataSource getDataSource() {
    ApplicationContext context = new ClassPathXmlApplicationContext("myContext.xml");
    return (DataSource) context.getBean("dataSource");
}

和myContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ws="http://jax-ws.dev.java.net/spring/core"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:wss="http://jax-ws.dev.java.net/spring/servlet" xmlns:jee="http://www.springframework.org/schema/jee"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
       http://jax-ws.dev.java.net/spring/core
        http://jax-ws.dev.java.net/spring/core.xsd
       http://www.springframework.org/schema/context
       http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://jax-ws.dev.java.net/spring/servlet
        http://jax-ws.dev.java.net/spring/servlet.xsd
       http://www.springframework.org/schema/jee
       http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">

    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="oracle.jdbc.OracleDriver" />
        <property name="url" value="" />
        <property name="username" value="" />
        <property name="password" value="" />
    </bean>

</beans>