简体   繁体   English

JDNI数据源的模式

[英]Pattern for JDNI datasource

I'm using a JNDI ressource in Tomcat8 for connecting to a MS-SQL database (Azure). 我在Tomcat8中使用JNDI资源来连接到MS-SQL数据库(Azure)。 Randomly I experience Connection closed exception, eventually preceeded by Connection peer reset events. 我随机遇到Connection closed异常,最终出现Connection peer reset事件。 When this happens, the service is dead (running into Connection closed for every request) and restarting the tomcat (redploying) is the only chance to get it up again. 发生这种情况时,服务Connection closed运行(对于每个请求都将进入Connection closed ),重新启动tomcat(重新部署)是重新启动该服务的唯一机会。

On my way trying to solve this I double(triple)-checked every method for unclosed connections, I assure that every connection is opened as try-with-ressource . 在尝试解决此问题的过程中,我对未关闭的连接的每个方法进行了三重检查,确保每个连接都以try-with-ressource ressource的形式打开。

Currently I'm trying to get a better understanding about JNDI ressources and the connection pooling, I'm asking what is the preferred pattern to implement a service class which is injected into other services. 当前,我正在尝试更好地了解JNDI资源和连接池,我想问什么是实现注入到其他服务中的服务类的首选模式。 Eg questions are 例如问题是

  1. Where should the DataSource be allocated by calling ctx.lookup() ? 应该通过调用ctx.lookup()DataSource分配到哪里? On method level or class scope? 在方法级别或类范围上? Eg when using the hk2 @Service annotation it seems that a service is instantiated only once and not per request. 例如,当使用hk2 @Service批注时,服务仅实例化一次,而不是针对每个请求实例化。 Currently ctx.lookup() is invoced once (in the constructor) and the DataSource is stored in a class field and later on accessed by the methods using this.dataSource . 当前(在构造函数中)调用了ctx.lookup()一次,并且将DataSource存储在一个类字段中,然后由使用this.dataSource的方法访问。 Does this make sense ? 这有意义吗? Or should the DataSource be retrieved on every request (=method call) 还是应该在每个请求(=方法调用)上检索DataSource

  2. How can I verify the execution of several options of the DataSource, eg testOnBorrow and removeAbandoned (see complete configuration below) are executed correctly? 我如何验证DataSource的多个选项的执行,例如testOnBorrowremoveAbandoned (请参阅下面的完整配置)是否正确执行? There is an option logAbandoned but I can not see anything in my logs. 有一个选项logAbandoned但是我的日志中看不到任何内容。 Where should this appear anyhow? 无论如何应该出现在哪里? Can I somehow specifiy a certain log level for the pool? 我可以以某种方式指定池的特定日志级别吗? I only found org.apache.tomcat.jdbc.pool , but this class seems only to be called when creating the pool (at least this is the only moment when logs appear, even on level FINEST ). 我只找到org.apache.tomcat.jdbc.pool ,但是此类似乎仅在创建池时才被调用(至少这是日志出现的唯一时刻,即使是在FINEST级别)。

  3. Are there general patterns which I'm not aware of? 有我不知道的一般模式吗?

Here my current configuration: 这是我当前的配置:

<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 Thx,Gapvision

Gapvision, you can check this link - What is the good design pattern for connection pooling? Gapvision,您可以检查此链接- 连接池的良好设计模式是什么?

Probably, you would want to go with the object pool pattern. 可能您想使用对象池模式。 Hope this helps !! 希望这可以帮助 !!

I'm asking what is the preferred pattern to implement a service class which is injected into other services. 我在问实现注入到其他服务中的服务类的首选模式是什么。

Try spring data. 尝试弹簧数据。 It is very helpful in organizing resources to access data. 这对于组织访问数据的资源非常有帮助。

Without spring, without tomcat built-in features, you indeed need create your own singletons to allocate DataSource or ConnectionPool. 没有spring,没有tomcat内置功能,您确实需要创建自己的单例来分配DataSource或ConnectionPool。

Without spring(assuming you build web app for tomcat), you can add to web.xml: 无需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>

And in context.xml of tomcat: 在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"/>

And then you can lookup data source in each request: 然后,您可以在每个请求中查找数据源:

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(); }
}

Or you can create a singleton class and lookup DataSource once , on start or lazy, as singletons do. 或者,您可以创建一个单例类,并像单例一样在启动或延迟时查找一次DataSource。

But better try spring data. 但是最好尝试一下spring数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM