<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    iamhuzl

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      1 隨筆 :: 13 文章 :: 21 評論 :: 0 Trackbacks
      忙碌的工作讓我很久沒有寫過博客了,另外技術上也沒有明顯的進步,也缺乏興奮點。項目正式上線很長時間,隨要訪問壓力的增大,每天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>
    
    


    已有 0 人發表留言,猛擊->>這里<<-參與討論


    ITeye推薦



    posted on 2011-12-03 00:36 溫水青蛙 閱讀(1318) 評論(3)  編輯  收藏

    評論

    # re: jdbc數據庫連接丟失或未釋放情況跟蹤 2013-10-31 10:14 牛武子
    哦  回復  更多評論
      

    # re: jdbc數據庫連接丟失或未釋放情況跟蹤[未登錄] 2015-06-17 17:53 1
    專門注冊了個號上來支持下,寫的很好,這個很實用  回復  更多評論
      

    # re: jdbc數據庫連接丟失或未釋放情況跟蹤[未登錄] 2015-06-17 17:54 1
    394012149@qq.com  回復  更多評論
      


    只有注冊用戶登錄后才能發表評論。


    網站導航:
     
    主站蜘蛛池模板: 亚洲欧美日韩国产精品一区| 一级毛片大全免费播放| 男女交性永久免费视频播放 | 亚洲精品天堂成人片AV在线播放| 日本高清免费网站| 日韩精品无码免费专区午夜不卡| 亚洲成人动漫在线观看| 亚洲人成网站色在线入口| 小草在线看片免费人成视久网| 亚洲日韩国产一区二区三区在线| 亚洲一区二区三区香蕉| 无码高潮少妇毛多水多水免费| 99麻豆久久久国产精品免费| 亚洲国产视频久久| 亚洲av无码专区在线播放| 午夜免费福利影院| 最近2019免费中文字幕6| 免费大片av手机看片| 亚洲精品中文字幕乱码影院| 亚洲精品国产高清不卡在线| 国产免费久久精品99re丫y| 一级特黄特色的免费大片视频 | 国产午夜无码精品免费看| 亚洲精品又粗又大又爽A片| 亚洲一区免费观看| 亚洲国产精品人人做人人爱| 午夜福利不卡片在线播放免费| 国产A∨免费精品视频| 亚洲精品国产综合久久久久紧| 亚洲av日韩综合一区在线观看| 国产在线ts人妖免费视频| 国产妇乱子伦视频免费| 在线播放免费人成毛片乱码| 美女黄频a美女大全免费皮| 亚洲娇小性xxxx色| 亚洲天堂男人天堂| 国产成A人亚洲精V品无码| 午夜亚洲av永久无码精品| 免费毛片在线播放| 久久综合AV免费观看| 亚洲精品免费在线|