一个线上服务偶尔卡顿,分析发现是loadClass导致的线程阻塞,而loadClass的原因与Feign配置有关。
1.现象
最近线上的一个服务偶尔出现卡顿,表现为不特定时刻出现几分钟的异常,在这段时间内响应时间激增,如图:
2.分析
首先查看日志,找到慢请求,发现在服务间Feign调用后会出现一段时间的间隔。对Feign的Logger和HttpMessageConverterExtractor开启DEBUG日志,看到在Feign输出HTTP返回数据后到Jackson反序列化之间有几秒的间隔。
2019-12-2010:25:55.493|*,*,*|DEBUG|feign.slf4j.Slf4jLogger:(72)|[ServiceName#methodName]
2019-12-2010:25:56.830|*,*,*|DEBUG|org.springframework.web.client.HttpMessageConverterExtractor:(100)|Readingto[com.*.DataModel]
这点很奇怪,在GC日志中也没有Stop-The-World出现。用jstack打印堆栈,发现有几个和Feign相关的线程处于BLOCKED状态:
"http-nio-8080-exec-276"#3021 daemon prio=5 os_prio=0 tid=0x00007fbd501a8800 nid=0xdea waiting for monitor entry [0x00007fbcbd76d000]
java.lang.Thread.State:BLOCKED(onobjectmonitor)
at java.lang.ClassLoader.loadClass(ClassLoader.java:404)
-waiting tolock<0x00000006c6ed91d0>(a java.lang.Object)
at org.springframework.boot.loader.LaunchedURLClassLoader.loadClass(LaunchedURLClassLoader.java:93)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(NativeMethod)
at java.lang.Class.forName(Class.java:348)
at org.springframework.util.ClassUtils.forName(ClassUtils.java:276)
at org.springframework.http.converter.json.Jackson2ObjectMapperBuilder.registerWellKnownModulesIfAvailable(Jackson2ObjectMapperBuilder.java:797)
at org.springframework.http.converter.json.Jackson2ObjectMapperBuilder.configure(Jackson2ObjectMapperBuilder.java:650)
at org.springframework.http.converter.json.Jackson2ObjectMapperBuilder.build(Jackson2Ob