<!----><!----><!----> <!---->
技术支持工作过程中,我们通常碰到这样两种情况:第一,访问业务数据慢,但又不知慢在何处;第二,写入的业务数据出错,但又不知为何出错。其实, Apusic Admin Console 工具中,包含了数据源连接监控和数据源事件跟踪两大功能,特别是后者,能够有效帮助我们去分析解决以上两种问题。本文将简要介绍如何使用 Admin Console 中的这两大功能。
数据源连接监控需要在 Apusic Admin Console 中添加 Apusic 应用服务器。下面描述 Step by Step 的添加过程。
1 )切换到“ Apusic 管理”透视图。
<!----><!----> <!---->
2 )在“ Apusic 服务器列表”视图中,点击鼠标右键,点击“增加服务器”。
<!----><!----> <!---->
3 )在弹出窗体,选择“ Apusic 应用服务器”。
<!----><!----> <!---->
4 )然后,选择“远程服务器”,输入主机、端口、用户、密码等信息,点击“ finish ”按钮完成。
<!----><!----> <!---->
一般情况下,启动 Apusic 应用服务器这个步骤不是必须的,因这个时候 Apusic 应用服务器可能已经正在运行了。如在测试或者调试环境,需要确认 Apusic 应用服务器已经启动。
在“ Apusic 服务器列表”视图中,点中刚添加的 Apusic ,点击鼠标右键,在弹出菜单中,点击“连接”。
<!----><!----> <!---->
然后再弹出窗体,输入用户、密码,点击“ ok ”按钮。
<!----><!----> <!---->
如有防火墙,请允许 eclipse 的连接。
<!----><!----> <!---->
<!----><!----> <!---->
连接上 Apusic 后,在 Apusic Admin Console 中,选择“数据源连接监控”透视图。
<!----><!----> <!---->
在“数据源连接监控”视图,双击所要监控的 Apusic 下的数据源。
<!----><!----> <!---->
在该数据源的视图中,我们就可以查看详细的连接使用的统计情况,包括创建数、关闭数、空闲连接数、总连接数、等待线程数等。
<!----><!----> <!---->
需要注意以下几点:
<!---->(1) <!---->如等待线程数不为 0 ,则表示数据库连接池可能设置得不够大
<!---->(2) <!---->如创建数明显大于关闭数,超出合理的水平,则表现可能存在连接泄漏
<!---->(3) <!---->等待时间或使用时间峰值过大,表明可能存在数据库访问方面的瓶颈
除了统计数据外,还可以查看活动连接 / 非活动连接的调用栈。那些活动时间过长的连接,特别需要加于留意。
连接上 Apusic 后,在 Apusic Admin Console 中,选择“数据源事件跟踪”透视图。
<!----><!----> <!---->
选择菜单中的“文件” -> “ New ” -> “跟踪”。
<!----><!----> <!---->
在“新建跟踪”窗体,输入跟踪名,选择服务器,并选中需要跟踪的数据源,点“ Next ”按钮。
<!----><!----> <!---->
下一步需要将跟踪到的事件信息暂存到数据库中。添加 URL 、驱动类名、驱动类路径、表名等信息,点击“ Next ”按钮。
<!----><!----> <!---->
下一步比较关键,我们可以选定跟踪的事件类型,包括 SQL 的语句执行、连接获取、设置自动提交、连接提交、连接回滚、连接关闭等事件,以及事务的开始、完成事件。
<!----><!----> <!---->
我们也可以选择感兴趣的数据列进行查看,最后,点击“ Finish ”按钮,完成。。
<!----><!----> <!---->
数据源事件跟踪将自动启动,在数据源跟踪视图中,将可以看到 SQL 语句,执行时间,堆栈等非常重要的信息了。
<!----><!----> <!---->
某客户应用,数据库为 SQL Server ,反馈访问缓慢。通过数据源事件跟踪,定位到问题。为了便于阅读,剥离应用场景,演示代码如下:
<%@ page import="java.sql.*"%> <%@ page import="javax.sql.*"%> <%@ page import="javax.naming.*"%> <% Context ctx = null; DataSource ds = null; Connection conn = null; Statement stmt = null; ResultSet rs = null; String jndi = "cyDataSource"; String sql_insert = "insert into test(id,name,code) values(1,'1','1')"; String sql_update = "update test set name='2'"; String sql_query = "select * from test"; try { ctx = new InitialContext(); ds = (DataSource)ctx.lookup(jndi); conn = ds.getConnection();
conn.setAutoCommit(false); stmt = conn.createStatement(); stmt.executeUpdate(sql_insert); stmt.close();
conn.setAutoCommit(true); stmt = conn.createStatement(); stmt.executeUpdate(sql_update);
stmt = conn.createStatement(); rs = stmt.executeQuery(sql_query); while(rs.next()) { System.out.println("id:" + rs.getObject(1) + " |name:" + rs.getObject(2) + " |code:" + rs.getObject(3)); out.println("id:" + rs.getObject(1) + " |name:" + rs.getObject(2) + " |code:" + rs.getObject(3)); } } catch (Exception e) { e.printStackTrace(); } finally{ } %> |
代码很简单,大意是对某个表进行插入操作后,因连接被传来传去,中间处理比较混乱,事务并未提交,这时同一连接又去访问该表进行更新操作。
我们依照上节的介绍,依样画瓢,开始数据源事件跟踪。然后,当访问演示页面时,发现页面半天不动,后台也没啥动静, JVM 也很正常,究竟发生什么事?代码执行到何处被阻塞了?
看起来好像很难,不过,这时候或者就是数据源事件跟踪工具发挥作用的时候了。通过观察数据源事件跟踪工具的输出,我们发现,连接在执行完第二次 setAutoCommit 后,未能继续执行后续的 Update 语句,显然,该语句涉及的表给锁住了。例子很简单,大家感兴趣的话可以动手做做。或者爱动手的你,把 SQL Server 换成 Oracle ,结果又会是如何呢?