JAVA_OPTS="$JAVA_OPTS -javaagent:${BTRACE_HOME}/build/btrace-agent.jar=script=${BTRACE_HOME}/scripts/HangDebug.class,stdout=true,debug=true,noServer=true"
HangDebug.class里面包含了一些需要查看的方法,下面是排查没有发送请求原因的步骤:
首先发现没有调用接口io.netty.channel.Channel.Unsafe的write方法,验证了请求没有发送出去的推论;
然后发现调用接口io.netty.channel.ChannelOutboundHandler的write方法时报错;
最后定位到调用类io.netty.handler.codec.MessageToByteEncoder的write方法时抛出了异常,异常堆栈为:
io.netty.handler.codec.EncoderException: java.lang.NoSuchMethodError: io.netty.util.internal.MathUtil.safeFindNextPositivePowerOfTwo(I)I io.netty.handler.codec.MessageToByteEncoder.write(MessageToByteEncoder.java:125) ... Caused by: java.lang.NoSuchMethodError: io.netty.util.internal.MathUtil.safeFindNextPositivePowerOfTwo(I)I io.netty.buffer.PoolThreadCache$MemoryRegionCache.<init>(PoolThreadCache.java:372) ...
这个时候,问题的原因比较明确了:
io.netty.util.internal.MathUtil.safeFindNextPositivePowerOfTwo这个方法没有找到。
最后找到问题的BTrace Method如下:
@OnMethod(
clazz = "+io.netty.channel.ChannelOutboundHandler",
method = "write",
location = @Location(value = Kind.ERROR)
)
public static void errorChannelOutboundHandlerWrite(@ProbeClassName String className, Throwable cause) {
println("error ChannelOutboundHandler.write, real class: " + className);
Threads.jstack(cause);
println("=====================");
}
这里有一个问题:为什么这个异常日志里面没有打印呢?
这个问题可以从io.netty.channel.AbstractChannelHandlerContext代码里找到答案:
private void invokeWrite(Object msg, ChannelPromise promise) {
try {
((ChannelOutboundHandler)this.handler()).write(this, msg, promise);
} catch (Throwable var4) {
notifyOutboundHandlerException(var4, promise);
}
}
notifyOutboundHandlerException会去通知对应的Listener,Xxx的这段老代码没有注册Listener,所以没有打印出这个异常。
4. NoSuchMethodError原因
再次查看了下$WEBAPP-DIR/WEB-INF/lib下Netty的版本:
netty-3.10.6.Final.jar netty-all-4.1.4.Final.jar netty-buffer-4.1.5.Final.jar netty-codec-4.1.5.Final.jar netty-codec-http-4.1.5.Final.jar netty-common-4.1.5.Final.jar netty-handler-4.1.5.Final.jar netty-resolver-4.1.5.Final.jar netty-transport-4.1.5.Final.jar transport-netty3-client-5.0.0.jar transport-netty4-client-5.0.0.jar
比较扎眼的是netty-all-4.1.4.Final.jar的版本和其它jar包版本不太一致。需要进一步确认一下,io.netty.buffer.PoolThreadCache$MemoryRegionCache和io.netty.util.internal.MathUtil









