`
mgoann
  • 浏览: 255699 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

BTrace实际案例分析

    博客分类:
  • Java
阅读更多

BTrace实际案例分析

问题表象

问题描述

1.最近有项目组的童鞋反馈,web页面频繁出现假死的状态。

2.web页面的假死出现是概率事件,且无法确定假死的引发原因。

3.是在一定的操作之后出现的,但是无法确定究竟是哪些操作引发这些操作。

问题分析

初步分析

我们都知道web容器一般都是单实例多线程的方式工作的,当页面发起请求后,tomcat发分配一个线程进行当前请求的处理,当出现页面假死,说明是由于某种原因导致了线程在等待某种资源,可以是IO、网络响应、数据库连接、等待锁等等,所以需要首先确定该线程是在等待什么资源。

 

经过初步分析,可以知道是线程阻塞导致web不能够及时返回给页面响应,导致页面出现假死的情况。所以首先确定导致线程阻塞的原因。

 

确定线程是由于什么原因导致的阻塞其实也是比较简单的,可以使用jstack工具,到出现阻塞现象后,使用jstack工具查看器堆栈,看下是等待什么。也可以使用Eclipsedebug功能,将当前线程suspend。在这里我采用第二种方式。

 

操作步骤

在本地以Debug方式启动Tomcat应用,模拟一些操作,尽量将假死项目重现,开发人员根据以往的映像去操作一些功能,过了若干时间后,果然出现了假死现象。由于是debug方式启动所以查看其debug视图,发现启动了3http线程,下图中红色部分标示的位置。



 

通过右击suspend挂起线程,发现有一个线程确实被阻塞掉了



 

观察堆栈可以确定是到连接池中去获取连接,但是当前连接池中无可用的连接,导致线程阻塞出现页面假死现象。

进一步分析

很明显这个是由于连接泄露导致无可用连接,所引起的线程阻塞,页面假死。查看连接池配置:

driver=oracle.jdbc.driver.OracleDriver

url=jdbc:oracle:thin:@127.0.0.1:1521:orcl

username=****

password=****

active=20

minidle=20

maxidle=20

maxwait=-1

出现连接泄露问题是较为难定位的问题,因为问题的表象离问题的根源较远,并没有直接的联系,所以只能凭经验和感觉去分析,另外出现该情况应当尽量将连接池连接个数配置改小,这样可以有效的拉近问题表象和问题根源之间的距离,减小问题重现的成本和最大化问题重现的概率。然后根据BTrace来进行分析。但是我们这里有BTrace这个利器来进行动态诊断。

诊断思路

只要跟踪所有的调用过BasicDataSource.getConnection这个方法的地方,然后在看看那些方法调用以后没有关系连接,而关闭连接的地方并非是Connectionclose方法,需要对连接池的工作原理有一定的了解。




 
 

如上图,连接池持有Connection代理的引用,用来维护Connection,而Connection代理实现了JDBC,通过Connection代理来操作驱动程序,在oracle中是oracle.jdbc.driver.T4CConnection



 

实际上连接池主要是通过PoolableConnection作为代理类,持有T4CConnection的引用,完成对数据的操作,并且自己实现了java.sql.Connection接口,我们看下close方法的具体实现。

 

/**
     * Returns me to my pool.
     */
     public synchronized void close() throws SQLException {
        if (_closed) {
            // already closed
            return;
        }

        boolean isUnderlyingConectionClosed;
        try {
            isUnderlyingConectionClosed = _conn.isClosed();
        } catch (SQLException e) {
            try {
                _pool.invalidateObject(this); // XXX should be guarded to happen at most once
            } catch(IllegalStateException ise) {
                // pool is closed, so close the connection
                passivate();
                getInnermostDelegate().close();
            } catch (Exception ie) {
                // DO NOTHING the original exception will be rethrown
            }
            throw (SQLException) new SQLException("Cannot close connection (isClosed check failed)").initCause(e);
        }

        if (!isUnderlyingConectionClosed) {
            // Normal close: underlying connection is still open, so we
            // simply need to return this proxy to the pool
            try {
                _pool.returnObject(this); // XXX should be guarded to happen at most once
            } catch(IllegalStateException e) {
                // pool is closed, so close the connection
                passivate();
                getInnermostDelegate().close();
            } catch(SQLException e) {
                throw e;
            } catch(RuntimeException e) {
                throw e;
            } catch(Exception e) {
                throw (SQLException) new SQLException("Cannot close connection (return to pool failed)").initCause(e);
            }
        } else {
            // Abnormal close: underlying connection closed unexpectedly, so we
            // must destroy this proxy
            try {
                _pool.invalidateObject(this); // XXX should be guarded to happen at most once
            } catch(IllegalStateException e) {
                // pool is closed, so close the connection
                passivate();
                getInnermostDelegate().close();
            } catch (Exception ie) {
                // DO NOTHING, "Already closed" exception thrown below
            }
            throw new SQLException("Already closed.");
        }
}

  

 

而获取连接的代码是通过PoolingDataSourcegetConnection进行获取的代码如下:

 

/**
     * Return a {@link java.sql.Connection} from my pool,
     * according to the contract specified by {@link ObjectPool#borrowObject}.
     */
    public Connection getConnection() throws SQLException {
        try {
            Connection conn = (Connection)(_pool.borrowObject());
            if (conn != null) {
                conn = new PoolGuardConnectionWrapper(conn);
            } 
            return conn;
        } catch(SQLException e) {
            throw e;
        } catch(NoSuchElementException e) {
            throw new SQLNestedException("Cannot get a connection, pool error " + e.getMessage(), e);
        } catch(RuntimeException e) {
            throw e;
        } catch(Exception e) {
            throw new SQLNestedException("Cannot get a connection, general error", e);
        }
    }

 

可以非常清楚的看到,就是通过该方法释放连接到连接池中,供后续的业务代码进行调用。

到这里基本的思路已经出来了,只要跟踪PoolingDataSourcegetConnection方法和PoolableConnectionclose方法就可以知道究竟哪些业务代码只调用了获取连接而没有调用close方法进行释放连接,导致连接泄露。

BTrace利器

通过编写BTrace脚本进行分析跟踪,只要业务代码在调用完getConnection方法后调用了close就说明没有问题,也就是getConnection方法和close方法成对出现,如果只调用了getConnection方法而没有调用close方法那就说明该业务代码有连接泄露。

 

import com.sun.btrace.annotations.*;
import static com.sun.btrace.BTraceUtils.*;

@BTrace public class BTraceConnection {
	
    @Export private static long openedCount;
    
    @Export private static long closedCount;
	
    @OnMethod(clazz="/.*PoolingDataSource/", method="getConnection", location=@Location(kind.RETURN))
    public static void m(@return Object obj) {
    	    openedCount++;
    			println("One connection is opened!");
    			println(obj);
    	    Threads.jstack();
    }
    
    @OnMethod(clazz="/.*PoolableConnection/", method="close")
    public static void d(@Self Object obj) {
    	    closedCount++;
    			println("One connection is closed!");
    			println(obj);
    	    Threads.jstack();
    }
    
    @OnExit
    public static void f(){
          print("Total opened connection:");
          println(openedCount);
          print("Total closed connection:");
          println(closedCount);	
    }
    
}

  

 

 

将连接池个数修改为3,启动应用,使用jps输出应用pid

 

运行命令btrace <pid> BTraceConnection.java > trace.log

日志分析

输出结果

 

One connection is opened!
org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper@1d6fc56
org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)
..................
com.***************************.dao.UserDAO.checkUserState(UserDAO.java:142)
..................
java.lang.Thread.run(Thread.java:619)
One connection is opened!
..................
Total opened connection:61
Total closed connection:57

  

 

部分无用内容有删减,发现总共获取了61connection,释放了57connectioncom.***************************.dao.UserDAO.checkUserState(UserDAO.java:142)该方法没有释放连接,最终定位出了有问题的方法。

 

 

其他相关博文

BTrace工具简介http://mgoann.iteye.com/blog/1409667
BTrace实例应用http://mgoann.iteye.com/blog/1409676
BTrace实际案例分析http://mgoann.iteye.com/blog/1409685

  • 大小: 26.1 KB
  • 大小: 40.4 KB
  • 大小: 30.6 KB
  • 大小: 8.2 KB
分享到:
评论
2 楼 tss0823 2014-09-02  
非常好的文章!
1 楼 youlong699 2013-03-12  
你好, 请教下, 看你btrace脚本里用了 Threads.jstack();   但是安全限制要求只能使用Utils里的方法, 我通过打开btrace脚本里的unsafe以及注解@BTrace(unsafe=true)都没能解除限制, 你这是里是怎么通过的呢? 用的又是哪个版本的btrace呢?

相关推荐

    btrace-sr:BTrace 实战学习笔记,其号称“线上问题追踪神器”

    7. **案例分析**:通过实际案例,如性能分析、内存泄漏检测或线程死锁排查,深入理解BTrace在不同场景下的应用。 8. **与其他工具的集成**:BTrace可以与其他监控和诊断工具(如VisualVM、JMX等)结合使用,增强...

    Java内存管理问题案例分享_技术大学.pdf

    Java内存管理问题是Java开发者在软件运行过程中经常会遇到的挑战之一,尤其在大型分布式系统中,内存泄漏、内存溢出...通过本分享的案例学习,可以加深对Java内存管理的认识,并能在实际遇到内存问题时快速定位和解决。

    性能资料整理.pdf

    代码级剖析工具,则可以通过分析代码执行的详细信息来帮助找出性能瓶颈,例如ContiPerf、BTrace等。 性能调优的知识不仅包括了工具的使用,还涉及性能基础理论知识。例如,了解常见接口性能压测、RPC框架、HTTPS...

    COMSOL模拟碳酸钙岩石与盐酸反应的随机孔隙酸化路径及布林克曼流动形成的分形结构

    内容概要:本文详细介绍了利用COMSOL软件模拟碳酸钙(CaCO3)在岩石中与盐酸(HCl)反应过程中产生的随机孔隙酸化路径及其形成的布林克曼流动。首先,通过蒙特卡洛方法生成随机孔隙分布,模拟真实岩石内部复杂的孔隙结构。接着,采用布林克曼方程处理多孔介质中的粘性力和渗透流动,并引入化学反应模块,模拟CaCO3与HCl之间的化学反应。随着模拟的进行,酸液流动路径逐渐形成类似雪花状的分形结构,展示了流动与溶解之间的动态博弈。最后,通过自适应网格技术和粒子追踪功能,精确捕捉并可视化这些精美的分形图案。 适合人群:从事地质工程、材料科学、化学工程等领域研究的专业人士,以及对多孔介质传输现象感兴趣的科研工作者。 使用场景及目标:适用于研究多孔介质内的化学反应和流体流动特性,特别是对于优化石油开采中的酸化压裂工艺具有重要指导意义。 其他说明:文中提供了详细的MATLAB和COMSOL代码片段,帮助读者理解和重现模拟过程。此外,强调了随机性和确定性在微观尺度上的相互作用,揭示了自然界深层次的规律。

    基于滑模控制的永磁同步电机直接转矩控制仿真建模与实现

    内容概要:本文详细介绍了将滑模控制(SMC)应用于永磁同步电机(PMSM)直接转矩控制(DTC)的技术细节。首先解释了转矩和磁链误差计算方法,接着探讨了滑模面的设计及其对系统抖振的影响。文中还提供了扇区矢量选择的具体实现方式,并深入讨论了磁链观测器的改进措施。此外,文章分析了滑模控制器的设计要点以及仿真过程中需要注意的关键参数配置。通过对比传统PI控制,验证了滑模控制在提高系统鲁棒性和快速响应方面的优势。 适合人群:从事电机控制系统研究的专业人士,尤其是对永磁同步电机直接转矩控制感兴趣的科研工作者和技术人员。 使用场景及目标:适用于希望深入了解并掌握滑模控制理论及其在PMSM-DTC应用中的具体实现方法的研究人员。目标是在实际项目中能够运用滑模控制提升系统的稳定性和性能。 其他说明:文中提供的MATLAB/Simulink代码片段有助于读者更好地理解和复现实验结果。同时提醒读者关注一些常见的陷阱,如参数选择不当可能导致的问题。

    北京大学网络安全工作人员管理规定:涵盖人员职责、聘用、转岗离岗、教育培训及第三方管理

    内容概要:本文详细介绍了北京大学针对网络安全工作人员的管理规定,旨在加强网络安全管理和明确不同角色的责任。全文分为九章,涵盖了网络安全工作人员及其职责、聘用管理、转岗和离岗管理、教育培训、第三方人员管理及奖惩措施等方面的内容。重点在于明确各级单位和人员的具体职责,确保网络安全制度的有效执行,并强调了对第三方人员的严格管控和保密要求。 适合人群:适用于高校网络安全管理人员及相关技术人员,尤其是北京大学及其下属单位的网络安全工作者。 使用场景及目标:①帮助高校建立健全网络安全管理体系;②指导网络安全工作人员明确自身职责,提高工作效率;③规范第三方人员的访问和操作,降低安全风险。 其他说明:本文还提供了多个附件,如网络安全承诺书、访问申请表和保密协议模板,便于实际操作和管理。

    网络设备市场现状与发展趋势分析(2024-2030年)-技术革新与智能化应用

    内容概要:本文深入探讨了中国网络设备市场的现状及其未来发展潜力。首先介绍了网络设备的基本概念及其作为现代通信网络基础设施的重要地位,随后分析了当前市场面临的挑战和技术进步带来的机遇。文中特别强调了5G、物联网、云计算等新兴技术对网络设备性能和安全性的更高要求,以及由此催生的高带宽、低延迟产品的市场需求。此外,还讨论了软件定义网络(SDN)、网络功能虚拟化(NFV)、边缘计算等新技术的应用前景,指出未来网络设备将更加智能化、自动化,并能更好地支持AI和ML技术。最后,通过对多家领先企业的案例研究,展示了行业内竞争态势及各公司在技术创新方面的努力。 适用人群:从事网络设备相关领域的研究人员、工程师、管理人员,以及关注该领域发展的投资者。 使用场景及目标:帮助读者了解网络设备行业的最新动态和技术趋势,为制定战略决策提供依据;同时为企业和个人投资者提供市场洞察,辅助其做出合理的投资选择。 其他说明:报告基于详实的数据分析和专家意见撰写而成,旨在为专业人士提供有价值的参考资料。

    西门子1200 PLC码垛系统的SCL编程详解:涵盖变频器、机器人、视觉系统集成

    内容概要:本文详细介绍了基于西门子1200 PLC的码垛系统的设计与实现,涵盖了多个关键技术点。首先,文章讲解了Modbus TCP通讯的实现方法,展示了如何通过TSEND_C和TRCV_C功能块进行工业相机和机器人之间的数据传输,并提供了具体的报文处理代码。接着,文章深入探讨了SCL编程的优势及其在复杂逻辑处理中的应用,如托盘堆叠算法,该算法能够根据当前层数动态调整机械手的高度,确保堆叠的安全性和稳定性。此外,文章还介绍了机器人控制中的移位寄存器实现的动作队列管理和变频器的速度平滑处理,以及视觉系统的坐标解析和异常处理机制。最后,文章强调了良好的注释规范和异常处理链的重要性,确保程序的可维护性和可靠性。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是熟悉西门子PLC编程和SCL语言的从业者。 使用场景及目标:适用于需要深入了解和掌握西门子1200 PLC在码垛系统中的具体应用的技术人员。目标是帮助读者理解并实现多设备联动的复杂控制系统,提高系统的稳定性和效率。 其他说明:文中提供的代码示例和详细的解释有助于读者更好地理解和应用相关技术,同时也为后续的维护和优化提供了宝贵的参考资料。

    ZYNQ平台PS与PL端驱动程序编写

    适合从入门到进阶的驱动程序爱好者

    计算机二级上机题库答案.pdf

    计算机二级上机题库答案.pdf

    深信服下一代防火墙:构建全方位立体网络安全监测与响应体系

    内容概要:本文介绍了深信服科技推出的下一代防火墙(NGAF)网络安全监测解决方案。随着网络安全成为国家战略的一部分,企业不仅需要遵守法律法规,还需增强自身的网络安全防护能力。传统的安全措施难以应对复杂的新型威胁,如APT攻击。深信服的NGAF通过多维度的安全监测,包括入侵风险、僵尸主机、实时漏洞、数据风险、黑链风险以及对外DoS攻击监测等功能,结合云端威胁情报共享,为企业提供了一套立体化的主动防御体系。该方案不仅可以旁路或串接部署,不影响现有业务系统,还能通过外置数据中心进行日志管理和综合分析,帮助用户快速定位和解决安全问题。 适合人群:IT管理人员、网络安全专家、企业信息安全负责人。 使用场景及目标:适用于各类企业的网络安全建设,特别是需要应对复杂网络攻击的企业。目标是构建一个多层次、全方位、智能化的网络安全监测和响应体系,提高企业的安全防护能力和应急响应速度。 其他说明:深信服NGAF不仅提升了网络安全监测的效果,还降低了运维成本,改变了传统的被动防护模式,使得安全运维更加高效和智能化。

    COMSOL超表面偏振转换技术:介质半波片与1/4波片的设计与仿真

    内容概要:本文详细介绍了利用COMSOL软件进行超表面偏振转换的设计方法,主要聚焦于介质半波片和1/4波片的实现。文中首先解释了超表面的基本原理及其在光学调控中的重要作用,随后具体阐述了如何在COMSOL中设置材料属性、创建几何结构并施加适当的边界条件。针对半波片和1/4波片的不同需求,分别探讨了它们各自的设计要点、模拟步骤及优化策略。此外,还分享了一些实用的编码示例和技术诀窍,帮助研究人员更好地理解和掌握相关技能。 适合人群:从事光学工程、光电子学等领域研究的专业人士,尤其是那些希望深入了解超表面偏振转换机制并对COMSOL有一定使用经验的技术人员。 使用场景及目标:适用于需要设计高性能偏振转换器件的研究项目,旨在提高对超表面特性的认识水平,推动新型光学组件的研发进程。通过学习本文提供的理论知识和实践经验,读者可以在实际工作中运用COMSOL完成高质量的仿真实验。 其他说明:文中不仅涵盖了基本的概念介绍,还包括了许多具体的实施细节,如参数选择、模型构建、边界条件设定等,这些都是成功搭建有效仿真的关键因素。同时,作者也强调了实验过程中可能出现的问题及解决方案,为后续研究提供了宝贵的参考资料。

    机器学习中萤火虫算法优化SVM模型参数的技术解析与应用

    内容概要:本文详细介绍了将萤火虫算法应用于支持向量机(SVM)模型参数优化的方法和技术细节。首先解释了萤火虫算法的基本原理及其在参数空间中的应用方式,然后展示了具体的Python实现代码,包括萤火虫移动规则、适应度评价函数以及主循环逻辑。文中还讨论了参数范围设定、随机扰动的作用、目标函数设计等多个关键技术点,并提供了多个数据集上的实验结果对比,证明了该方法的有效性和优越性。 适合人群:对机器学习尤其是SVM模型有一定了解的研究人员和工程师,希望掌握先进的超参数优化技术。 使用场景及目标:适用于需要提高SVM模型性能的项目中,特别是在面对大规模数据集或复杂特征空间的情况下。通过使用萤火虫算法进行参数寻优,可以显著减少调参时间和成本,获得更好的分类效果。 其他说明:文章不仅提供了理论依据,还有详细的代码示例可供参考。此外,作者强调了一些实用技巧如参数范围的选择、随机扰动的应用等,有助于读者更好地理解和应用这一技术。

    软考高级信息系统项目管理师考试题型解析与备考指南

    内容概要:本文详细介绍了软考高级信息系统项目管理师考试的内容,

    网络中间设备的发展及其在SDN/NFV环境下的角色转变与挑战

    内容概要:本文探讨了网络中间设备(middlebox)在现代网络架构中的地位和发展方向。首先介绍了网络中间设备的基本概念及其与传统转发设备的区别,强调了中间设备在网络安全、流量管理和优化方面的作用。接着讨论了软件定义网络(SDN)和网络功能虚拟化(NFV)背景下,中间设备面临的机遇和挑战,以及两者融合的趋势。最后展望了未来网流监控技术的发展前景,特别是在高效载荷过滤算法和敏捷策略管理机制方面的突破。 适合人群:从事网络工程、信息安全、云计算等领域工作的技术人员,以及对网络技术和架构感兴趣的科研人员。 使用场景及目标:帮助读者理解网络中间设备的关键作用和技术发展趋势,指导他们在实际工作中更好地规划和部署相关设备和服务。 其他说明:文中引用了SIGCOMM 2012和CoNEXT 2013的相关研究成果,提供了丰富的理论依据和技术背景支持。

    计算机二级各章考点.pdf

    计算机二级各章考点.pdf

    Tomcat 部署配置指南安全配置性能调优

    Tomcat 部署配置指南安全配置性能调优

    计算机辅助光学设计.pdf

    计算机辅助光学设计.pdf

    计算机二级考试机试(南开100题全).pdf

    计算机二级考试机试(南开100题全).pdf

Global site tag (gtag.js) - Google Analytics