亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 服務器 > Web服務器 > 正文

Tomcat啟動失敗的問題排查與解決

2024-09-01 13:51:38
字體:
來源:轉載
供稿:網友

前言

最近在某應用更新代碼后部分機器發布失敗,發布失敗的機器上Tomcat一直沒有啟動成功,日志卡在Deploying web application,重啟數次之后仍然是一樣的情況。所以進行排查問題,下面記錄了所有的排查過程,需要的朋友們可以參考學習。

排查過程

1. Tomcat啟動線程卡住

下文中Tomcat啟動線程代指線程名為localhost-startStop-$id的線程。

使用jstack打印出Tomcat的線程堆棧:

jstack `jps |grep Bootstrap |awk '{print $1}'` > jstack.log

從jstack.log里面可以看到線程localhost-startStop-1處于WAITING狀態,堆棧如下:

"localhost-startStop-1" #26 daemon prio=5 os_prio=0 tid=0x00007fe6c8002000 nid=0x3dc1 waiting on condition [0x00007fe719c1e000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x00000007147be150> (a xxx.heartbeat.network.client.FutureResult) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175) at java.util.concurrent.FutureTask.awaitDone(FutureTask.java:429) at java.util.concurrent.FutureTask.get(FutureTask.java:191) at xxx.HeartBeatContainer.invoke(HeartBeatContainer.java:183) at xxx.HeartBeatContainer.registry(HeartBeatContainer.java:130)

對應的代碼如下:

final ResponseFuture<XxxMessage<Result>> future = responseFutureFactory.newResponseFuture(request);channel.writeAndFlush(request);XxxMessage<Result> response = future.get();

線程一直卡在future.get()沒有返回。這個步驟是在等待客戶端向Xxx-Server發送的注冊請求的返回。

2. Xxx注冊請求沒返回

用tcpdump抓了下包(Xxx-Server的服務端口是yyy):

tcpdump -X -s0 -i bond0 port yyy

發現只有建連接的包,沒有length != 0的數據包:

IP app-ip.56599 > xxx-server-ip.yyy: Flags [S], seq 3536490816, win 14600, options [mss 1460,sackOK,TS val 3049061547 ecr 0], length 0IP xxx-server-ip.yyy > app-ip.56599: Flags [S.], seq 2500877640, ack 3536490817, win 14480, options [mss 1460,sackOK,TS val 1580197458 ecr 3049061547], length 0IP app-ip.56599 > xxx-server-ip.yyy: Flags [.], ack 1, win 14600, options [nop,nop,TS val 3049061548 ecr 1580197458], length 0

所以,推斷注冊請求沒返回的原因是請求壓根兒沒有發送出去。

3. Xxx注冊請求沒發送出去

Xxx代碼里面調用了channel.writeAndFlush,但是數據卻沒有發送出去。這塊的代碼,更友好的做法應該是writeAndFlush之后對返回的ChannelFuture注冊一個Listener,在write操作完成之后的回調里面判斷狀態。

在Netty大神 – @yh的指導下用BTrace跟了一下Netty的代碼。

在Tomcat啟動邏輯相關腳本bin/catalina.sh里面加上參數讓Btrace agent和Tomcat一起啟動:

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.jarnetty-all-4.1.4.Final.jarnetty-buffer-4.1.5.Final.jarnetty-codec-4.1.5.Final.jarnetty-codec-http-4.1.5.Final.jarnetty-common-4.1.5.Final.jarnetty-handler-4.1.5.Final.jarnetty-resolver-4.1.5.Final.jarnetty-transport-4.1.5.Final.jartransport-netty3-client-5.0.0.jartransport-netty4-client-5.0.0.jar

比較扎眼的是netty-all-4.1.4.Final.jar的版本和其它jar包版本不太一致。需要進一步確認一下,io.netty.buffer.PoolThreadCache$MemoryRegionCacheio.netty.util.internal.MathUtil這兩個類分別是從哪個jar包中加載的。

在Tomcat啟動邏輯相關腳本bin/catalina.sh里面加上啟動參數,打印Class加載的日志:

JAVA_OPTS="$JAVA_OPTS -verbose:class"

可以看到:

...[Loaded io.netty.buffer.PoolThreadCache$MemoryRegionCache from file:$WEBAPP-DIR/WEB-INF/lib/WEB-INF/lib/netty-buffer-4.1.5.Final.jar]...[Loaded io.netty.util.internal.MathUtil from file:$WEBAPP-DIR/WEB-INF/lib/netty-all-4.1.4.Final.jar]...

從netty-all-4.1.4.Final.jar中加載的io.netty.util.internal.MathUtil,是沒有safeFindNextPositivePowerOfTwo這個方法的(正常情況下,應該從netty-common-4.1.5.Final.jar中加載這個類)。

至此為止,弄清楚了啟動卡住的原因:

Netty包加載問題 => Xxx調用channel.writeAndFlush發送注冊請求時異常 => 沒有回包,future.get()一直卡住 => Tomcat啟動線程卡住

還有一個令人費解的現象:為什么有的機器啟動正常,有的機器啟動不正常呢?

5. 不同機器表現不同

再回頭看一下啟動有問題的機器上Netty相關jar包的順序,這里我們使用ls -f命令(只關注和問題相關的jar包):

$ ls -f |grep nettynetty-buffer-4.1.5.Final.jarnetty-all-4.1.4.Final.jar...netty-common-4.1.5.Final.jar...

ls加-f參數的含義可以通過man手冊看到:

-f do not sort, enable -aU, disable -ls --color

意思是直接使用系統調用getdents的返回,不再做排序。從man手冊可以看到,ls默認排序方法是Sort entries alphabetically if none。

NoSuchMethodError的原因是:從netty-buffer-4.1.5.Final.jar中加載了io.netty.buffer.PoolThreadCache$MemoryRegionCache,這個類是會調用io.netty.util.internal.MathUtil.safeFindNextPositivePowerOfTwo這個方法的;從netty-all-4.1.4.Final.jar加載的io.netty.util.internal.MathUtil沒有這個方法。

對比看下啟動正確的機器上的Netty相關jar包的順序:

$ ls -f |grep netty...netty-all-4.1.4.Final.jar...netty-common-4.1.5.Final.jarnetty-buffer-4.1.5.Final.jar...

由此可以看出所有Netty相關的Class均從netty-all-4.1.4.Final.jar中加載,不會有不兼容的問題產生。

要么問題來了:為什么在ext4中,擁有相同目錄項的目錄,ls -f出來的順序是不一樣的呢?

這個問題我暫時也回答不上來,至少我還沒有拿到令自己信服的代碼級別的解釋。

嗯,沒有代碼的解釋不是解釋,沒有deadline的任務不是任務,沒有流程圖或分享的源碼閱讀不是源碼閱讀,沒有報告的性能測試不是性能測試。

這里有一個基于現象的解釋,我覺得還比較靠譜:

On modern filesystems where directory data structures are based on a search tree or hash table, the order is practically unpredictable.

我們可以做的

事后諸葛亮時間 :) 開玩笑的,遇事多review下才能少犯錯誤。

  • 基礎組件:多考慮失敗的情況,不吞異常;可能阻塞的操作考慮超時時間(自勉)
  • 發布系統:能夠添加一些規則,哪些包不能共存,比如上述問題中的netty-all和netty-common這些
  • 容器隔離:隔離中間件使用的三方包和業務使用的三方包

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網的支持。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久亚洲影院你懂的| 久久香蕉频线观| www.久久草.com| 97超级碰碰碰久久久| 中文日韩在线观看| 日韩精品免费一线在线观看| 亚洲国产精品成人精品| 欧美激情精品久久久久久免费印度| 国产视频精品在线| 91免费国产网站| 国产成人短视频| 欧美日韩中国免费专区在线看| 国产精品久久久久久久久男| 色多多国产成人永久免费网站| 精品久久久久久久久久久久久| 国产精品入口日韩视频大尺度| 91精品国产综合久久香蕉922| 国产欧美日韩中文| 欧美xxxx14xxxxx性爽| 成人精品久久一区二区三区| 精品欧美aⅴ在线网站| 亚洲永久免费观看| 欧美亚洲另类制服自拍| 91免费综合在线| 日本中文字幕不卡免费| 日韩av在线一区二区| 亚洲国产精品小视频| 欧美在线观看日本一区| 亚洲无限av看| 久久久综合av| 日韩欧美极品在线观看| 中文字幕欧美日韩va免费视频| 国产精品精品一区二区三区午夜版| 日韩美女视频在线观看| 日本19禁啪啪免费观看www| 91在线直播亚洲| 亚洲精品国产精品久久清纯直播| 国产精品高潮呻吟久久av野狼| 91在线免费网站| 成人黄色免费网站在线观看| 91久久精品日日躁夜夜躁国产| 亚洲自拍偷拍第一页| 精品人伦一区二区三区蜜桃免费| 亚洲国产精品成人va在线观看| 亚洲一区二区在线| 国产做受69高潮| 久久久精品一区二区| 日韩美女写真福利在线观看| 久久精品国产欧美亚洲人人爽| 国产精品流白浆视频| www.国产精品一二区| 国产精品亚洲一区二区三区| 97在线日本国产| 久久久免费av| 亚洲精品电影久久久| 亚洲韩国日本中文字幕| 国产精品一区二区女厕厕| 青草青草久热精品视频在线网站| 欧美激情久久久| 中文字幕最新精品| 亚洲人午夜色婷婷| 久久777国产线看观看精品| 欧美成人小视频| 欧美亚州一区二区三区| 欧美在线观看视频| 亚洲精品在线看| 欧美黑人视频一区| 日韩电影免费观看在线观看| 欧美在线中文字幕| 欧美性xxxx在线播放| 亚洲美女免费精品视频在线观看| 久久久伊人日本| 久久久久免费视频| 91亚洲精品在线观看| 欧美乱大交xxxxx另类电影| 成人国产在线激情| 91天堂在线视频| 国产一区二区三区在线播放免费观看| 日韩中文字幕在线免费观看| 91麻豆国产语对白在线观看| 九九热在线精品视频| 久久精视频免费在线久久完整在线看| 97在线观看免费高清| 国产精品久久久久久久午夜| 亚洲国产精品一区二区三区| 欧美激情一区二区三级高清视频| 国产精品444| 国产在线一区二区三区| 国产香蕉97碰碰久久人人| 69精品小视频| 欧美成人三级视频网站| 日韩一区二区av| 久久久久一本一区二区青青蜜月| 久久久久久91| 久久91亚洲人成电影网站| 国产精品羞羞答答| 欧美最猛黑人xxxx黑人猛叫黄| 日韩中文理论片| 欧美极品在线视频| 92版电视剧仙鹤神针在线观看| 欧美日韩国产一区二区三区| 日本国产欧美一区二区三区| 欧美精品在线极品| 久久天天躁狠狠躁夜夜爽蜜月| 国产福利视频一区二区| 黄色精品在线看| 国产成人精品免费视频| 高潮白浆女日韩av免费看| 最近2019好看的中文字幕免费| 伊人伊成久久人综合网站| 久久久www成人免费精品| 国产精品入口夜色视频大尺度| 福利视频一区二区| 亚洲国产另类久久精品| 亚洲午夜未满十八勿入免费观看全集| 国产免费一区视频观看免费| 亚洲一区二区三区xxx视频| zzijzzij亚洲日本成熟少妇| 国产视频观看一区| 国产精品h片在线播放| 国产精品一区二区久久国产| 日韩av大片在线| 亚洲一区二区三区777| 国产精品久久一区主播| 欧美久久精品一级黑人c片| 久久久视频免费观看| 国产免费一区二区三区在线观看| 国产精品美女视频网站| 日韩av在线网站| 在线成人中文字幕| 精品久久久香蕉免费精品视频| 国产97在线亚洲| 国产精品久久电影观看| 中文字幕日韩精品在线| 亚洲国产女人aaa毛片在线| 亚洲欧美激情在线视频| 亚洲专区中文字幕| 91大神在线播放精品| 日韩成人中文电影| 精品国产福利视频| 欧美成人性生活| 亚洲成人1234| 午夜精品久久久久久久久久久久久| 欧美日韩国产二区| 国产成一区二区| 中文日韩电影网站| 日韩成人在线视频| 日本一区二区在线免费播放| 91精品成人久久| 欧美日韩国产中文精品字幕自在自线| 91亚洲精华国产精华| 北条麻妃99精品青青久久| 国产精品久久一区主播| 色噜噜亚洲精品中文字幕| 日韩欧美国产中文字幕| 久久成人精品电影| 亚洲一区二区中文| 亚洲精品成a人在线观看| 日产精品久久久一区二区福利| 亚洲欧美中文另类| 欧美放荡办公室videos4k| 国产亚洲精品va在线观看| 国产精品久久久久久久久| 91av在线不卡|