JDNI数据源的模式

时间:2015-08-01 13:02:24

标签: java tomcat azure jndi

我在Tomcat8中使用JNDI资源来连接到MS-SQL数据库(Azure)。随机我遇到Connection closed异常,最后是Connection peer reset个事件。发生这种情况时,服务已经死亡(每个请求都运行Connection closed)并重新启动tomcat(redploying)是唯一一次再次启动它。

在试图解决这个问题的过程中,我对未闭合连接的每个方法进行了双重(三次)检查,我保证每个连接都以try-with-ressource打开。

目前我正在努力更好地了解JNDI资源和连接池,我问的是实现一个注入其他服务的服务类的首选模式。例如。问题是

  1. 通过致电DataSource,应该在哪里分配ctx.lookup()?在方法级别或类范围?例如。当使用hk2 @Service注释时,似乎服务仅实例化一次而不是每个请求。当前ctx.lookup()被调用一次(在构造函数中),DataSource存储在类字段中,稍后由方法使用this.dataSource访问。这有意义吗?或者应该在每个请求(=方法调用)

  2. 上检索DataSource
  3. 如何验证DataSource的多个选项的执行,例如testOnBorrowremoveAbandoned(请参阅下面的完整配置)是否正确执行?有一个选项logAbandoned但我在日志中看不到任何内容。无论如何这应该出现在哪里?我可以以某种方式指定池的某个日志级别吗?我只找到org.apache.tomcat.jdbc.pool,但这个类似乎只在创建池时被调用(至少这是日志出现的唯一时刻,即使在级别FINEST上)。

  4. 是否有一些我不知道的一般模式?

  5. 这是我目前的配置:

    <Resource name="jdbc/mssql"
              auth="Container"
              type="javax.sql.XADataSource"
              driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
              username="***"
              password="***"
              url="jdbc:sqlserver://***.database.windows.net:1433;database=***;encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30;"
              factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
              removeAbandonedOnBorrow="true"
              removeAbandonedTimeout="55"
              removeAbandonedOnMaintenance="true"
              timeBetweenEvictionRunsMillis="34000"
              minEvictableIdleTimeMillis="55000"
              logAbandoned="true"
              validationQuery="SELECT 1"
              validationInterval="34000"
            />
    

    Thx,gapvision

2 个答案:

答案 0 :(得分:1)

Gapvision,您可以查看此链接 - What is the good design pattern for connection pooling?

您可能希望使用对象池模式。 希望这会有所帮助!!

答案 1 :(得分:0)

  

我问的是实现一个注入其他服务的服务类的首选模式。

尝试弹簧数据。它在组织资源以访问数据方面非常有用。

没有spring,没有tomcat内置功能,你确实需要创建自己的单例来分配DataSource或ConnectionPool。

没有spring(假设你为tomcat构建web应用程序),你可以添加到web.xml:

<resource-ref>
<description>H2DB</description>
<res-ref-name>jdbc/project1</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>

在tomcat的context.xml中:

<Resource name="jdbc/project1" auth="Container" type="javax.sql.DataSource" driverClassName="org.h2.Driver"  url="jdbc:h2:tcp://localhost/~/project1"   username="sa" password="" maxActive="20" maxIdle="10" maxWait="-1"/>

然后您可以在每个请求中查找数据源:

Context ctx = new InitialContext();
Context envContext = (Context) ctx.lookup("java:comp/env");
DataSource ds = (DataSource) envContext.lookup("jdbc/project1");
Connection conn = null;
try {
conn = ds.getConnection();
PreparedStatement ps = conn.prepareStatement("INSERT INTO USERS (NAME) VALUES (?)");
ps.setString(1,name);
ps.executeUpdate();
response.getWriter().write("added user "+name);
response.getWriter().write("\n");
} finally {
if (conn!=null) { conn.close(); }
}

或者你可以像单身一样创建一个单例类并在开始或懒惰时查找一次DataSource。

但更好的尝试弹簧数据。