忙碌的工作让我很久没有写过博客了,另外技术上也没有明显的进步,也缺乏兴奋点。项目正式上线很长时间,随要访问压力的增大,每天PV差不多有500万。这时出现了一些问题,主要的是访问响应慢,程序中未发现异常。错误日志有数据库连接的错误,怀疑是数据库连接丢失或有某些请求会锁表。因此写一段代码跟踪数据库连接获取和释放的情况。
原理很简单,拦截DataSource的getConnnection方法,把当前Connection和调用堆栈保存到连接列表;拦截Connection对象close方法,把Connection从连接列表中删除。
直接上代码:
package com.emagsoftware;
import java.lang.reflect.Method;
import java.sql.Connection;
import javax.sql.DataSource;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.apache.log4j.Logger;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* DataSource connection监控处理
*
* @author huzl
* @date 2010-11-26 9:42:17
*/
class DataSourceBeanPostProcessor implements BeanPostProcessor {
public static Map connections = new ConcurrentHashMap();
public static Map connectionTime = new ConcurrentHashMap();
Logger log = Logger.getLogger(DataSourceBeanPostProcessor.class);
public Object postProcessBeforeInitialization(Object object, String name) {
return object;
}
//创建DataSource或DataSource工厂的代理
public Object postProcessAfterInitialization(Object object, String name) throws org.springframework.beans.BeansException {
if (!"dataSource".equals(name)) return object;
System.out.println("****************DataSource postProcessAfterInitialization success ");
if (object instanceof FactoryBean)
return createDataSourceFactoryProxy((FactoryBean) object);
else
return createDataSourceProxy((DataSource) object);
}
private FactoryBean createDataSourceFactoryProxy(final FactoryBean factoryBean) {
if (Enhancer.isEnhanced(factoryBean.getClass())) return factoryBean;
MethodInterceptor factoryInterceptor = new MethodInterceptor() {
public java.lang.Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws java.lang.Throwable {
Object result = method.invoke(factoryBean, args);
if ("getObject" != method.getName()) return result;
return createDataSourceProxy((DataSource) result);
}
};
return (FactoryBean) createProxy(FactoryBean.class, factoryInterceptor);
}
//拦截DataSource getConnection方法,记录获取的数据库连接
private DataSource createDataSourceProxy(final DataSource dataSource) {
if (Enhancer.isEnhanced(dataSource.getClass())) return dataSource;
MethodInterceptor dataSourceInterceptor = new MethodInterceptor() {
public java.lang.Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws java.lang.Throwable {
Object result = method.invoke(dataSource, args);
if ("getConnection" != method.getName()) return result;
connections.put(result, new Exception());
connectionTime.put(result, new java.util.Date());
System.out.println("****************DataSource Connection get size = " + connections.size());
return createConnectionProxy((Connection) result);
}
};
return (DataSource) createProxy(DataSource.class, dataSourceInterceptor);
}
//拦截Connection close方法,清除释放的数据库连接
private Connection createConnectionProxy(final Connection conn) {
if (Enhancer.isEnhanced(conn.getClass())) return conn;
MethodInterceptor connectionProxy = new MethodInterceptor() {
public java.lang.Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws java.lang.Throwable {
if ("close" == method.getName()) {
connections.remove(conn);
connectionTime.remove(conn);
System.out.println("****************DataSource Connection close size = " + connections.size());
}
return method.invoke(conn, args);
}
};
return (Connection) createProxy(Connection.class, connectionProxy);
}
private Object createProxy(Class targetInterfaceClass, MethodInterceptor interceptor) {
Enhancer enhancer = new Enhancer();
enhancer.setInterfaces(new Class[]{targetInterfaceClass});
enhancer.setCallback(interceptor);
return enhancer.create();
}
}
spring配置文件
<bean class="com.emagsoftware.DataSourceBeanPostProcessor"/>
写一个页面,检查connections和connectionTime中的对象即可
<%@ page import="org.apache.commons.lang.exception.ExceptionUtils" %>
<%@ page import="java.util.Iterator" %>
<%@ page import="com.emagsoftware.DataSourceBeanPostProcessor" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-CN" dir="ltr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>连接池查询</title>
<style type="text/css">
.hidden{
display: none;
}
</style>
</head>
<body>
<h1>连接池(<%=DataSourceBeanPostProcessor.connections.size()%>)</h1>
<%
if(DataSourceBeanPostProcessor.connections.size()>0){
out.println("时间:" + DataSourceBeanPostProcessor.connectionTime.values() + "
");
Iterator iterator = DataSourceBeanPostProcessor.connections.values().iterator();
while(iterator.hasNext())
{
Exception ex = (Exception) iterator.next();
out.println("<pre>" + ExceptionUtils.getFullStackTrace(ex) + "</pre>
");
}
}
%>
</body>
</html>
分享到:
相关推荐
Java JDBC 数据库连接池总结 Java 语言中,JDBC(Java DataBase Connection)是应用程序与数据库沟通的桥梁。在 Web 应用开发的早期,主要使用的技术是 CGIASPPHP 等。之后,Sun 公司推出了基于 Java 语言的 ...
本资源集合了常用的JDBC数据库连接jar包,以及一些知名的数据库连接池实现,如dbcp和c3p0,这对于开发人员来说是非常宝贵的资源。 首先,让我们了解一下JDBC。JDBC提供了一套标准的API,包括接口和类,使得开发者...
jdbc连接数据库jdbc连接数据库jdbc连接数据库jdbc连接数据库jdbc连接数据库jdbc连接数据库jdbc连接数据库jdbc连接数据库jdbc连接数据库jdbc连接数据库jdbc连接数据库jdbc连接数据库jdbc连接数据库jdbc连接数据库jdbc...
Java JDBC 数据库连接池技术是Java应用程序访问数据库的关键优化手段,尤其在Web应用程序中,它解决了传统JDBC连接方式存在的效率低下和资源浪费问题。Java JDBC(Java Database Connectivity)是Java语言与各种...
Java JDBC 数据库连接池总结 Java JDBC 数据库连接池是 Java 应用程序访问数据库的基本原理之一。Java 语言通过 JDBC 技术访问数据库,JDBC 是一种“开放”的方案,为数据库应用开发人员和数据库前台工具开发人员...
JDBC连接数据库测试JDBC连接数据库测试JDBC连接数据库测试JDBC连接数据库测试JDBC连接数据库测试JDBC连接数据库测试JDBC连接数据库测试JDBC连接数据库测试JDBC连接数据库测试JDBC连接数据库测试JDBC连接数据库测试...
在IT领域,特别是软件开发与数据管理中,Java Database Connectivity(JDBC)是连接Java应用程序与各种数据库管理系统的重要桥梁。JDBC提供了一种标准的API,使得开发者能够使用SQL语句来查询、更新和管理数据库中的...
以下是对给定文件中提到的JDBC数据库连接模板代码的知识点详细解析。 ### JDBC概念 JDBC是一种用于执行SQL语句的Java API,它由一组用Java语言编写的类和接口组成。通过JDBC,开发者可以将SQL语句发送到几乎任何...
**JDBC数据库连接JAR包详解** Java Database Connectivity(JDBC)是Java平台中的一个标准API,它允许Java应用程序与各种类型的数据库进行交互。JDBC为开发者提供了统一的接口,使得开发者无需关心底层数据库的具体...
使用ODBC连接数据库通常用于非标准的数据库类型或当没有可用的JDBC驱动时。 **代码示例:** ```java // 加载ODBC驱动 Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); // 连接数据库 Connection ...
在本教程中,我们将深入探讨JDBC的使用,并提供完整的数据库连接代码示例。 首先,了解JDBC的基本概念至关重要。JDBC包括一组Java类和接口,它们位于java.sql和javax.sql包中。主要组件有: 1. **DriverManager**...
JDBC(Java Database Connectivity)是Java编程语言中用于规范应用程序如何访问数据库的应用程序接口,它提供了标准的API让Java程序员能够连接各种不同类型的数据库。本篇将深入讲解JDBC的基础知识,以及如何利用...
BaseDao文件中包含了数据库连接技术的URL,DRIVER等。
1. **选择连接池实现**:首先,我们需要选择一个合适的数据库连接池实现,如Apache的DBCP、C3P0、HikariCP或Tomcat JDBC连接池等。这些连接池库提供了管理和维护数据库连接的功能。 2. **配置连接池**:在应用的...
本文将详细介绍如何使用JDBC连接Oracle、SqlServer、MySql和Access这四种常见的数据库。 一、Oracle数据库连接 Oracle数据库是企业级的大型关系型数据库管理系统。在Java中,我们通常会使用`ojdbc`驱动来连接Oracle...
这个是JDBC数据库连接的案例,很实用,很容易移植,希望大家喜欢。
Java JDBC数据库连接池是Java应用程序与数据库交互的重要优化手段,旨在提高数据库访问效率和资源利用率。在传统的JDBC操作中,每次请求都需要建立和关闭数据库连接,这不仅耗时,还可能导致系统资源的过度消耗,...
一、实验目的: ...(5)理解数据库连接池的基本原理和思想,学会在tomcat服务器中配置数据库连接池,并掌握从连接池中获取连接的基本方法。 (6)初步理解数据访问层的基本设计方法,理解web的分层架构。