1 问题的现象
经过第一轮数据库的优化,微服务的请求响应耗时都比较能接受了。然而网络请求的总耗时还是很慢。
这个问题的关键就在网关层了。
2 问题的分析
至于机器为啥会慢,分析完机器的运行状态数据感觉,除了CPU高点以外,其他指标都还比较正常。
第一时间怀疑到的自然是GC问题,结果打印了GC日志发现极其正常。
第二步就考虑还是打印一下jstack(中间有个乌龙事件,jstack只能使用当前用户执行,root权限并不能打印其他用户的栈)
结果打印结果来看全部卡在了logback输出日志。
"http-nio-20070-exec-1480" #33017 daemon prio=5 os_prio=0 tid=0x00007f38a8268800 nid=0x5c57 waiting on condition [0x00007f388330d000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000c0129698> (a java.util.concurrent.locks.ReentrantLock$FairSync)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199)
at java.util.concurrent.locks.ReentrantLock$FairSync.lock(ReentrantLock.java:224)
at java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:285)
at ch.qos.logback.core.OutputStreamAppender.subAppend(OutputStreamAppender.java:210)
at ch.qos.logback.core.rolling.RollingFileAppender.subAppend(RollingFileAppender.java:228)
at ch.qos.logback.core.OutputStreamAppender.append(OutputStreamAppender.java:100)
at ch.qos.logback.core.UnsynchronizedAppenderBase.doAppend(UnsynchronizedAppenderBase.java:84)
at ch.qos.logback.core.spi.AppenderAttachableImpl.appendLoopOnAppenders(AppenderAttachableImpl.java:48)
at ch.qos.logback.classic.Logger.appendLoopOnAppenders(Logger.java:270)
at ch.qos.logback.classic.Logger.callAppenders(Logger.java:257)
at ch.qos.logback.classic.Logger.buildLoggingEventAndAppend(Logger.java:421)
at ch.qos.logback.classic.Logger.filterAndLog_0_Or3Plus(Logger.java:383)
at ch.qos.logback.classic.Logger.info(Logger.java:579)
然而用iostat来看确实磁盘的性能还有很足的空余,难道是程序慢?
3 问题的解决
找到一个栈信息分析的网站https://fastthread.io/
分析完之后发现,很多都有锁在同一个对象上。刚好有一个栈文件能看到这个锁是logback程序持有的。
然后去查源码,看了一下发现,日志输出肯定要有一个锁来实现打印内容的同步。
仔细看完代码,发现logback 1.1.7的版本,采用的是一个公平锁。极端并发场景会导致严重的性能问题。
然后,我们又发现在logback最新的1.2.3版本把这个改成了非公平锁。
把logback版本升级后发现,性能问题解决。