上周五接近6个小时都在开会,悲剧阿。 美好的一天又这样被浪费了。
还好开会的时候自带了笔记本,闲来无聊又重新把btrace的内容重新梳理了一遍。
ps : 以前虽然看过btrace的使用,但根本是一种阅读者的态度,并没有反编译btrace源码进行查看。 还有就是实际也没写过几个btrace脚本,很多使用就显得很生疏。所以需要多加强下,只能多看过个2,3遍。
更详细,更精彩的一些btrace内容,请查看: btrace一些你不知道的事(源码入手)
几个常用url :
1. javadoc文档: http://btrace.kenai.com/javadoc/1.2/index.html
2. UserGuide : http://kenai.com/projects/btrace/pages/UserGuide
3. DeveloperGuide : http://kenai.com/projects/btrace/pages/DeveloperGuide
4. jvisualvm plugins : http://visualvm.java.net/pluginscenters.html , http://visualvm.java.net/plugins.html
1. Kind.CALL 和 Kind.ENTRY的使用理解
3. @TargetInstance 和 @TargetMethodOrField的理解
这个可以结合Kind.CALL进行说明,如果是probe A class的方法中调用了匹配B class。 @TargetInstance 返回的就是B class的实例,@Self返回的就是A class
Please enter your option: 1. exit 2. send an event 3. send a named event
@OnEvent public static void event() { println("event"); } @OnEvent("A") // 相应name A event public static void eventA() { println("eventA"); } @OnEvent("B") // 相应name B event public static void eventB() { println("eventB"); }
@OnExit public static void onexit(int code) { println("exit"); } @OnTimer(1000) public static void ontime() { println(i++); if (i == 5) { println("do exit"); exit(0); } }
1. Jetty监控request/response buffer,有项目在使用中发现出现http 413错误(Request entity too large) , http://www.checkupdown.com/status/E413_cn.html
初步怀疑是和buffer参数有关,原先使用jboss的参数为maxHttpHeadSize=8196,所以写了脚本提取了下线上的jetty参数,后面就修改了jetty参数为8k,解决了问题
@BTrace public class JettyHeadBufferTracer { @OnMethod(clazz = "org.eclipse.jetty.http.HttpBuffers", method = "/.*get.*Buffers/", location = @Location(value = Kind.ENTRY)) public static void bufferMonitor(@Self Object self) { Field requestBuffersField = field("org.eclipse.jetty.http.HttpBuffers", "_requestBuffers"); Field responseBuffersField = field("org.eclipse.jetty.http.HttpBuffers", "_responseBuffers"); Field bufferSizeField = field("org.eclipse.jetty.io.ThreadLocalBuffers", "_bufferSize"); Field headerSizeField = field("org.eclipse.jetty.io.ThreadLocalBuffers", "_headerSize"); Object requestBuffers = get(requestBuffersField, self); int requestBufferSize = (Integer) get(bufferSizeField, requestBuffers); int requestHeaderSize = (Integer) get(headerSizeField, requestBuffers); Object responseBuffers = get(responseBuffersField, self); int responseBufferSize = (Integer) get(bufferSizeField, responseBuffers); int responseHeaderSize = (Integer) get(headerSizeField, responseBuffers); println(strcat(strcat(strcat("requestBufferSize : ", str(requestBufferSize)), " requestHeaderSize : "), str(requestHeaderSize))); println(strcat(strcat(strcat("responseBufferSize : ", str(responseBufferSize)), " responseHeaderSize : "), str(responseHeaderSize))); } }
结果:
requestBufferSize : 8192 requestHeaderSize : 6144 responseBufferSize : 12288 responseHeaderSize : 6144
2. 项目中使用了dbcp做为数据库连接池,但对于连接池大小是否够用没有很直观的数据可以提供,所以写了个脚本提取一下数据
主要的数据内容:
* maxActive(最大连接池大小),numActive(目前处于使用中),numIdle(处于空闲状态的连接数)
* maxTotal(开启ps的最大值),totalActive(目前处于使用ps的总数),keyActive(当前sql的ps使用数),keyIdle(当前sql的ps空闲数) 针对开启了ps cache
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> .... <property name="poolPreparedStatements" value="true" /> <property name="maxOpenPreparedStatements" value="10" /> .... </bean>
@BTrace public class DbcpTracer { @OnMethod(clazz = "org.apache.commons.pool.impl.GenericObjectPool", method = "/.*Object/", location = @Location(value = Kind.ENTRY)) public static void poolMonitor(@Self Object self) { Field maxActiveField = field("org.apache.commons.pool.impl.GenericObjectPool", "_maxActive"); Field numActiveField = field("org.apache.commons.pool.impl.GenericObjectPool", "_numActive"); Field poolField = field("org.apache.commons.pool.impl.GenericObjectPool", "_pool"); Field sizeField = field("org.apache.commons.pool.impl.CursorableLinkedList", "_size"); int maxActive = (Integer) get(maxActiveField, self); int numActive = (Integer) get(numActiveField, self); int numIdle = (Integer) get(sizeField, get(poolField, self)); println(strcat(strcat(strcat(strcat(strcat("maxActive : ", str(maxActive)), " numActive : "), str(numActive)), " numIdle : "), str(numIdle))); } @OnMethod(clazz = "org.apache.commons.pool.impl.GenericKeyedObjectPool", method = "/.*Object/", location = @Location(value = Kind.ENTRY)) public static void psMonitor(@Self Object self, Object key) { Field maxTotalField = field("org.apache.commons.pool.impl.GenericKeyedObjectPool", "_maxTotal"); // connectio的maxActive Field totalActiveField = field("org.apache.commons.pool.impl.GenericKeyedObjectPool", "_totalActive"); // connectio的active Field poolMapField = field("org.apache.commons.pool.impl.GenericKeyedObjectPool", "_poolMap"); // connectio的active Field keyActiveField = field("org.apache.commons.pool.impl.GenericKeyedObjectPool$ObjectQueue", "activeCount"); // key的active Field keyIdleField = field("org.apache.commons.pool.impl.GenericKeyedObjectPool$ObjectQueue", "queue"); // key的idle Field keyIdleSizeField = field("org.apache.commons.pool.impl.CursorableLinkedList", "_size"); Field sqlField = field("org.apache.commons.dbcp.PoolingConnection$PStmtKey", "_sql"); int maxTotal = (Integer) get(maxTotalField, self); int totalActive = (Integer) get(totalActiveField, self); Map<Object, Object> poolMap = (Map<Object, Object>) get(poolMapField, self); int keyActive = 0, keyIdle = 0; if (poolMap != null) { Object queue = get(poolMap, key); if (queue != null) { // ObjectQueue keyActive = (Integer) get(keyActiveField, queue); keyIdle = (Integer) get(keyIdleSizeField, get(keyIdleField, queue)); } } println(strcat(strcat(strcat(strcat(strcat(strcat(strcat("maxTotal : ", str(maxTotal)), " totalActive : "), str(totalActive)), " keyActive : "), str(keyActive)), " keyIdle "), str(keyIdle))); println(strcat("Ps Key: ", str(get(sqlField, key)))); } }