浅析 Jndi / DataSource / ConnectionPool 三者
最近有个用户量 5W-10W 的 web 应用,频繁导致 weblogic 崩溃,让运维组很难受。
通过几天跟踪系统日志和 weblogic 运行状况,发现报错的姿势有很多,其中对定位问题比较关键的报错:
ExecuteThread: '496' for queue: 'weblogic.kernel.Default (self-tuning)' has beenbusy for "712" seconds working on the request "XXXX", which is more than the configured time (StuckThreadMaxTime) of "600" seconds.
weblogic 分配给 web 应用使用的线程响应返回周期最大为10分钟,线程迟迟无法返回结果导致阻塞,并且这样的刺头线程越来越多。
运行一段时间后达到 weblogic 阻塞线程的阀值,weblogic 自然就崩溃了。
刚开始也试着调大 weblogic 响应周期/阻塞线程的阀值,但是阻塞线程还是会存在并且很快达到阀值。
仔细比对奔溃前后日志,查看 weblogic 阻塞线程详情,导致阻塞开始罪魁祸首是数据库查询需要很长时间。
该系统与内外围很多厂商系统有进行数据交互,数据库里面旁根错杂的 db_link/synonyms/view/procedure。
而且是老旧项目,代码经过很多人修改,已经风烛残年摇摇欲坠,俺想重造它不是一天两天了,因为很多原因无法进行,很无奈。
规范数据库中的交互流程?然后动代码?oh,no! 限定解决的期限将至,不能拖。
应用起初使用的是自带 C3P0 ConnectionPool,出现崩溃问题后,辗转尝试很多方法。
将应用的数据库连接池改动为服务器 weblogic JNDI ConnectionPool ,使数据库连接的压力从应用转移到 web 容器。
崩溃问题得到了缓解,经过后续的 weblogic 连接池参数的调整,卡死崩溃问题得到妥善解决。
实践证明 web 容器配置 JNDI 提供给应用使用效率远远大于应用自带的连接池,也使我不得不重新审视这块对于 web 项目的重要性。
同样 JNDI 避免了程序与数据库之间的紧耦合,使应用更加易于配置、易于部署。 而且这样几乎无代码改动,只需变动下 DataSource 的获取。
试想发布在 weblogic 上面的 10个自带连接池的应用,当数据库信息变动时,你是不是想哭?
1. DataSource / ConnectionPool / JNDI 三者关系

DataSource:数据源是在 JDBC2.0 中引入的一个概念;
在 JDBC 扩展包中定义了Java.sql.DataSource 接口,它负责建立与数据库的连接;
在应用程序访问数据库是不必编写连接数据库的代码,可直接从数据源获得数据库连接。
ConnectionPool :在数据源中初始化建立了多个数据库连接,这些数据库连接保存在连接池(ConnectionPool)中。
Java程序访问数据库时,只需从连接池中取出空闲状态的数据库连接,当访问结束时,将数据库连接返回给连接池。
JNDI : (Java Naming and Directory Interface)Java命名与目录接口;
为开发人员提供了查找和访问各种命名和目录服务的通用、统一的接口。
其实可以将 JNDI 理解为一种对象和名字绑定的技术,即指定一个资源名称,将该名称与某一资源或服务相关联。
结合图和上面的简述,数据层关键性对象都已展露无遗,同样也很容易理解。
JNDI 避免了程序与数据库之间的紧耦合,使应用更加易于配置、易于部署。
2. 配置 JNDI 数据源的方式和使用
weblogic 上配置 JNDI 为图形界面,操作起来很方便,而且那是运维组的事情,术业有专攻。
这里我拿 Tomcat 为例(开发时你也不可能在本机装个 weblogic 调试吧),简述下配置 JDNI 的几种方式:
a. 全局使用:Tomcat 的 conf 文件夹下的 context.xml 配置文件中添加:
<Resource name="jndi/db_test"
auth="Container"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/db_test"
username="root"
password="123456"
maxActive="20"
maxIdle="10"
maxWait="10000"/>
b.局部使用:Tomcat 的 conf 文件夹下 server.xml 的 <host> 标签内添加:
Context path="/demo_jndi" docBase="/demo_jndi">
<Resource
name="jndi/db_test"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
maxIdle="2"
maxWait="5000"
username="root"
password="123456"
url="jdbc:mysql://localhost:3306/db_test"
maxActive="4"/>
</Context>
c.局部使用:应用 META-INFO 下新建 context.xml 添加:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Resource name="jndi/db_test"
auth="Container"
type="javax.sql.DataSource"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/db_test"
username="root"
password="123456"
maxActive="20"
maxIdle="10"
maxWait="10000"/>
</Context>
上述几种配置使用的数据源都为 javax.sql.DataSource,当然你也可以引入其他开源的数据源。
也就是 web 容器使用其他的开源数据库连接池,比如像下面这几种姿势(记得将依赖的 jar 添加到容器的 lib 中):
<Resource name="jndi/db_test"
auth="Container"
//DBCP
type="javax.sql.DataSource"
factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory" //C3P0
type="com.mchange.v2.c3p0.ComboPooledDataSource"
factory="org.apache.naming.factory.BeanFactory" //Druid
type="com.alibaba.druid.pool.DruidDataSource"
factory="com.alibaba.druid.pool.DruidDataSourceFactory" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/db_test"
username="root"
password="123456"
maxActive="20"
maxIdle="10"
maxWait="10000"/>
配置好之后,使用起来也是相当的简单,核心如下2行代码即可:
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:comp/env/jndi/db_test");
如果项目中引入了 Spring 上述两行代码都可以省了,注入数据源配置,如下:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value = "java:comp/env/jndi/db_test"/>
</bean>
因为命名前缀的不用,避免发布时忘记修改,统一配置 tomcat 和 weblogic 上的数据源 jndi 的方式:
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/db_test" />
浅析 Jndi / DataSource / ConnectionPool 三者的更多相关文章
- 浅析JNDI注入Bypass
之前在Veracode的这篇博客中https://www.veracode.com/blog/research/exploiting-jndi-injections-java看到对于JDK 1.8.0 ...
- Java JNDI Datasource HOW-TO Problem
在开发JAVA的时候发生了点问题,解决方案记录一下,在这里http://tomcat.apache.org/tomcat-7.0-doc/jndi-datasource-examples-howto. ...
- Tomcat中使用JNDI加载JDBC数据源
以前写JDBC的时候总是手工写一个类,用硬代码写上className.url.用户名和密码什么的,然后通过DriverManager获取到Connection.那样写是很方便,但是如果想更改的话,需要 ...
- tomcat JNDI 设置
一.在Spring配置文件中的配置 <bean id="dataSource" class="org.springframework.jndi.JndiObje ...
- tomcat下jndi配置
jndi(Java Naming and Directory Interface,Java命名和目录接口)是一组在Java应用中访问命名和目录服务的API.命名服务将名称和对象联系起来,使得我们可以用 ...
- 转!数据库连接池概念、种类、配置(DBCP\C3P0\JndI与Tomact配置连接池)
数据库连接池概念.种类.配置(DBCP\C3P0\JndI与Tomact配置连接池) 一.DBCP 连接:DBCP 连接池是 Apache 软件基金组织下的一个开源连接池实现. 需要的 java 包c ...
- tomcat下jndi的三种配置方式
jndi(Java Naming and Directory Interface,Java命名和目录接口)是一组在Java应用中访问命名和目录服务的API.命名服务将名称和对象联系起来,使得我们可以用 ...
- 【转】tomcat下jndi的三种配置方式
jndi(Java Naming and Directory Interface,Java命名和目录接口)是一组在Java应用中访问命名和目录服务的API.命名服务将名称和对象联系起来,使得我们可以用 ...
- Springmvc +JNDI 在Tomcat下 配置数据源(转)
一. 简介 jndi(Java Naming and Directory Interface,Java命名和目录接口)是一组在Java应用中访问命名和目录服务的API.命名服务 ...
随机推荐
- 深入浅出Redis-Spring整合Redis
概述: 在之前的博客中,有提到过Redis 在服务端的一些相关知识,今天主要讲一下Java 整合Redis的相关内容. 下面是Jedis 的相关依赖: <dependency> <g ...
- ios的300ms点击延时问题
一.什么是ios的300ms点击延时问题 ios的移动端页面对点击事件有300ms延时. 二.为什么存在这个问题 这要追溯至 2007 年初.苹果公司在发布首款 iPhone 前夕,遇到一个问题 —— ...
- 关于hession 随笔
今天遇到一个问题,纠结了很久也没有解决,情况是这样的, 我这个项目使用的是 hession 通信.我做的业务很简单,只是新加了一个接口 ,这 个接口是广告那一块的,数据库在之前的项目里面都没有使用到 ...
- Java程序员入门:程序员究竟可以干多少年?
很多人都说程序员是青春饭,只能干到30岁. 然而事实真的如此么? 今天我们来探讨一下这个老话题,看看为了技术与编程执着究竟能走多远? 01年龄分布图 先来看一下程序员的年龄分布图: 我们可以看到程序员 ...
- 提交Sublime Text 插件到Package Control
最近写了一个lua智能提示的插件LuaSmartTips.这个插件一直都是自己一个人在用,昨天突然想把插件提交到Package Control,如果其他的人有这样的需求就可以直接安装. Package ...
- 移动端利用rem实现自适应布局
好久没有写博客了,刚好说说最近遇到的移动端布局问题吧. 本来一直是觉得我的页面布局能力还是不错的,当然,是相对于较基础的来说还是不错的.不过,自己写的案例终归是跟实际开发有区别的,自己写案例的是觉得这 ...
- 用Use Case获取需求的方法是否有什么缺陷,还有什么地方需要改进?
一.用例解释 用例是一种在开发新系统或者软件改造时捕获潜在需求的技术.每个用例提供了一个或多个场景,该场景揭示了系统是如何同最终用户或其它系统交互的,从而获得一个明确的业务目标.用例要避免技术术语,取 ...
- 九度OJ题目1208:10进制 VS 2进制 (JAVA)
题目描述: 对于一个十进制数A,将A转换为二进制数,然后按位逆序排列,再转换为十进制数B,我们乘B为A的二进制逆序数. 例如对于十进制数173,它的二进制形式为10101101,逆序排列得到1 ...
- js页面跳转常用的几种方式
第一种: <script language="javascript" type="text/javascript"> window.location ...
- .Net编译运行原理
.Net Framework: 它是框架库和运行时的集合 ( FCL, Framework Class Library ) ( CLR, Common Language Runtime ) 不严格说它 ...