日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

Tomcat进程假死问题排查

發(fā)布時(shí)間:2024/3/24 编程问答 66 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Tomcat进程假死问题排查 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄

1.網(wǎng)絡(luò)

1.1 檢查nginx的網(wǎng)絡(luò)情況

1.2 檢查tomcat的網(wǎng)絡(luò)情況

2.Jvm內(nèi)存溢出

2.1為什么會(huì)發(fā)生內(nèi)存泄漏

2.2快速定位問(wèn)題

2.3 jstack查看tomcat是否出現(xiàn)死鎖

2.4 jstat查看gc運(yùn)行情況

?2.5 jmap獲取內(nèi)存快照

3. jvm GC 時(shí)間過(guò)長(zhǎng),導(dǎo)致應(yīng)用暫停

4. load 太高,已經(jīng)超出服務(wù)的極限

5. 大量tcp 連接 TIME_WAIT

6. tomcat長(zhǎng)連接數(shù)超過(guò)最大連接數(shù)

1.網(wǎng)絡(luò)

1.1 檢查nginx的網(wǎng)絡(luò)情況

? ? 更改nginx的配置,讓該臺(tái)nginx請(qǐng)求只轉(zhuǎn)到本機(jī)器的出現(xiàn)問(wèn)題的tomcat應(yīng)用上面,在access.log里看是否有網(wǎng)絡(luò)請(qǐng)求,結(jié)果可以查看到當(dāng)前所有的網(wǎng)絡(luò)請(qǐng)求,也就是說(shuō)可以排除是網(wǎng)絡(luò)的問(wèn)題。

1.2 檢查tomcat的網(wǎng)絡(luò)情況

? ? 分析業(yè)務(wù)配置的tomcat訪問(wèn)日志xxxx.log上是否有日志訪問(wèn)記錄,經(jīng)過(guò)查詢?cè)撆_(tái)tomcat應(yīng)用日志完全沒(méi)有任何訪問(wèn)記錄,由于我們的部署是本機(jī)的nginx轉(zhuǎn)到本機(jī)的tomcat應(yīng)用,所以可以排除不是網(wǎng)絡(luò)問(wèn)題。 到此基本可以斷定網(wǎng)絡(luò)沒(méi)有問(wèn)題,tomcat 本身出現(xiàn)了假死的情況。在tomcat的日志里有報(bào)過(guò)OutOfMemoryError的異常,所以可以肯定tomcat假死的原因是OOM

2.Jvm內(nèi)存溢出

2.1為什么會(huì)發(fā)生內(nèi)存泄漏

? ? 在我們學(xué)習(xí)Java的時(shí)候就知道它最為方便的地方就是我們不需要管理內(nèi)存的分配和釋放,一切由JVM自己來(lái)進(jìn)行處理,當(dāng)Java對(duì)象不再被應(yīng)用時(shí),等到堆內(nèi)存不夠用時(shí)JVM會(huì)進(jìn)行GC處理, 清除這些對(duì)象占用的堆內(nèi)存空間,但是如果對(duì)象一直被應(yīng)用,那么JVM是無(wú)法對(duì)其進(jìn)行GC處理的,那么我們創(chuàng)建新的對(duì)象時(shí),JVM就沒(méi)有辦法從堆中獲取足夠的內(nèi)存分配給此對(duì)象,這時(shí)就會(huì)導(dǎo)致OOM。 我們出現(xiàn)OOM原因,一般都是因?yàn)槲覀儾粩嗟耐萜骼锎娣艑?duì)象,然而容器沒(méi)有相應(yīng)的大小限制或清除機(jī)制,這樣就容易導(dǎo)致OOM。

2.2快速定位問(wèn)題

當(dāng)我們的應(yīng)用服務(wù)器占用了過(guò)多內(nèi)存的時(shí)候,我們?cè)趺礃硬拍芸焖俚亩ㄎ粏?wèn)題呢?要想快速定位問(wèn)題,首先我們必需獲取服務(wù)器JVM某時(shí)刻的內(nèi)存快照。 Jdk里面提供了很多相應(yīng)的命令比如:jstack,jstat,jmap,jps等等. 在出現(xiàn)問(wèn)題后我們應(yīng)該快速保留現(xiàn)場(chǎng)。


2.3 jstack查看tomcat是否出現(xiàn)死鎖

? ? 可以觀察到j(luò)vm中當(dāng)前所有線程的運(yùn)行情況和線程當(dāng)前狀態(tài).

sudo jstack -F 進(jìn)程ID

輸出內(nèi)容如下: 從上面的圖我們可以看到tomcat進(jìn)程里面沒(méi)有死鎖的情況,而且每個(gè)線程都處理等待的狀態(tài)。這個(gè)時(shí)候我們可以telnet命令連上tomcat的端口查看tomcat進(jìn)程是否有任務(wù)回應(yīng)。這時(shí)發(fā)現(xiàn)tomcat沒(méi)有任何回應(yīng)可以證明tomcat應(yīng)用已沒(méi)有響應(yīng)處理假死狀態(tài)。

在thread dump中,要留意下面幾種狀態(tài) 死鎖, ? Deadlock(重點(diǎn)關(guān)注) 等待資源, ? Waiting on condition(重點(diǎn)關(guān)注) ? 等待獲取監(jiān)視器,Waiting on monitor entry(重點(diǎn)關(guān)注) ? 阻塞,Blocked(重點(diǎn)關(guān)注) ? 執(zhí)行中,Runnable ? 暫停,Suspended ? 對(duì)象等待中,Object.wait() 或 TIMED_WAITING ? 停止,Parked

2.4 jstat查看gc運(yùn)行情況

?2.5 jmap獲取內(nèi)存快照

Jdk自帶的jmap可以獲取內(nèi)在某一時(shí)刻的快照

命令:

jmap -dump:format=b,file=heap.bin?file:保存路徑及文件名 pid:進(jìn)程編號(hào)(windows通過(guò)任務(wù)管理器查看,linux通過(guò)ps aux查看)

dump文件可以通過(guò)MemoryAnalyzer分析查看,網(wǎng)址:http://www.eclipse.org/mat/,可以查看dump時(shí)對(duì)象數(shù)量,內(nèi)存占用,線程情況等。
?

3. jvm GC 時(shí)間過(guò)長(zhǎng),導(dǎo)致應(yīng)用暫停

查看gc.log回收時(shí)間,以下為例子:

7581088.402: [Full GC (System) 7581088.402: [CMS: 661091K->669762K(7340032K), 1.7206330 secs] 848607K->669762K(8238848K), [CMS Perm : 34999K->34976K(58372K)], 1.7209480 secs] [Times: user=1.72 sys=0.00, real=1.72 secs]

最近的一次full gc 顯示,也不應(yīng)該會(huì)暫停幾分鐘的情況,這種假死可能可以排除。

4. load 太高,已經(jīng)超出服務(wù)的極限

使用top 命令查看資源使用情況,都在合理范圍,排除。

5. 大量tcp 連接 TIME_WAIT

Linux:

使用 ss -s 命令查看 tcp 鏈接狀態(tài), 發(fā)現(xiàn)TIME_WAIT 1800+, 有點(diǎn)高,需要修改。

打開(kāi) sysctl.conf 文件,修改以下幾個(gè)參數(shù):

[root@web01 ~]# vim /etc/sysctl.confnet.ipv4.tcp_tw_reuse = 1net.ipv4.tcp_tw_recycle = 1net.ipv4.tcp_timestamps = 1net.ipv4.tcp_syncookies = 1net.ipv4.tcp_fin_timeout = 30

開(kāi)啟tcp_tw_reuse 和 tcp_tw_recycle 需要timestamps的支持,而且這些配置一般不建議開(kāi)啟,但是對(duì)解決TIME_WAIT過(guò)多問(wèn)題有效果。謹(jǐn)慎操作!!!

然后又發(fā)現(xiàn),nginx 沒(méi)有開(kāi)啟長(zhǎng)連接。

當(dāng)使用nginx作為反向代理時(shí),為了支持長(zhǎng)連接,需要做到兩點(diǎn):

  • 從client到nginx的連接是長(zhǎng)連接
  • 從nginx到server的連接是長(zhǎng)連接

Windows:

netstat -ano -p tcpnetstat -ano | find "ESTABLISHED"

5.1、保持和client的長(zhǎng)連接:

http {keepalive_timeout 120s 120s;keepalive_requests 10000; }

1)keepalive_timeout
語(yǔ)法:

keepalive_timeout timeout [header_timeout];
  • 第一個(gè)參數(shù):設(shè)置keep-alive客戶端連接在服務(wù)器端保持開(kāi)啟的超時(shí)值(默認(rèn)75s);值為0會(huì)禁用keep-alive客戶端連接;
  • 第二個(gè)參數(shù):可選、在響應(yīng)的header域中設(shè)置一個(gè)值“Keep-Alive: timeout=time”;通常可以不用設(shè)置;
  • 注:keepalive_timeout默認(rèn)75s,一般情況下也夠用,對(duì)于一些請(qǐng)求比較大的內(nèi)部服務(wù)器通訊的場(chǎng)景,適當(dāng)加大為120s或者300s;

    2)keepalive_requests:

    keepalive_requests指令用于設(shè)置一個(gè)keep-alive連接上可以服務(wù)的請(qǐng)求的最大數(shù)量,當(dāng)最大請(qǐng)求數(shù)量達(dá)到時(shí),連接被關(guān)閉。默認(rèn)是100。這個(gè)參數(shù)的真實(shí)含義,是指一個(gè)keep alive建立之后,nginx就會(huì)為這個(gè)連接設(shè)置一個(gè)計(jì)數(shù)器,記錄這個(gè)keep alive的長(zhǎng)連接上已經(jīng)接收并處理的客戶端請(qǐng)求的數(shù)量。如果達(dá)到這個(gè)參數(shù)設(shè)置的最大值時(shí),則nginx會(huì)強(qiáng)行關(guān)閉這個(gè)長(zhǎng)連接,逼迫客戶端不得不重新建立新的長(zhǎng)連接。

    大多數(shù)情況下當(dāng)QPS(每秒請(qǐng)求數(shù))不是很高時(shí),默認(rèn)值100湊合夠用。但是,對(duì)于一些QPS比較高(比如超過(guò)10000QPS,甚至達(dá)到30000,50000甚至更高) 的場(chǎng)景,默認(rèn)的100就顯得太低。

    簡(jiǎn)單計(jì)算一下,QPS=10000時(shí),客戶端每秒發(fā)送10000個(gè)請(qǐng)求(通常建立有多個(gè)長(zhǎng)連接),每個(gè)連接只能最多跑100次請(qǐng)求,意味著平均每秒鐘就會(huì)有100個(gè)長(zhǎng)連接因此被nginx關(guān)閉。同樣意味著為了保持QPS,客戶端不得不每秒中重新新建100個(gè)連接。因此,就會(huì)發(fā)現(xiàn)有大量的TIME_WAIT的socket連接(即使此時(shí)keep alive已經(jīng)在client和nginx之間生效)。因此對(duì)于QPS較高的場(chǎng)景,非常有必要加大這個(gè)參數(shù),以避免出現(xiàn)大量連接被生成再拋棄的情況,減少TIME_WAIT。

    5.2、保持和server的長(zhǎng)連接:

    nginx訪問(wèn)后端默認(rèn)都是用的短連接(HTTP1.0)

    為了讓nginx和后端server(nginx稱為upstream)之間保持長(zhǎng)連接,location中有兩個(gè)參數(shù)需要設(shè)置:

    http {server {location / {proxy_http_version 1.1;proxy_set_header Connection "";}} }

    5.3、 proxy_set_header 配置注意事項(xiàng)

    在當(dāng)前級(jí)別的配置中沒(méi)有定義 proxy_set_header 指令時(shí),這些指令從上級(jí)繼承。
    如果當(dāng)前級(jí)別的配置中已經(jīng)定義了 proxy_set_header 指令,在上級(jí)中定義的proxy_set_header 指令在當(dāng)前級(jí)別都會(huì)失效。

    舉個(gè)例子:

    http {...proxy_http_version 1.1;proxy_set_header Host $host;proxy_set_header Connection "";proxy_set_header X-Real-IP $remote_addr;upstream example.com_test {server 127.0.0.1:8080;keepalive 16;}server {server_name example.com;location ^~ /test/ {proxy_set_header test test;proxy_pass http://example.com_test;}} }

    這里后端服務(wù)器不能從 Header 中獲取到 X-Real-IP。location ^~/test/ 中的proxy_set_header會(huì)覆蓋上面的配置。

    正確的做法,在location 中重復(fù)配置一遍:

    http {...proxy_http_version 1.1;proxy_set_header Host $host;proxy_set_header Connection "";proxy_set_header X-Real-IP $remote_addr;upstream example.com_test {server 127.0.0.1:8080;keepalive 180;}server {server_name example.com;location ^~ /test/ {proxy_set_header test test;proxy_set_header Host $host;proxy_set_header Connection "";proxy_set_header X-Real-IP $remote_addr;proxy_pass http://example.com_test;}} }

    6. tomcat長(zhǎng)連接數(shù)超過(guò)最大連接數(shù)

    發(fā)現(xiàn)tomcat 使用的是默認(rèn)配置

    tomcat默認(rèn)最大連接數(shù)(線程數(shù))200個(gè),默認(rèn)每一個(gè)連接的生命周期2小時(shí)(7200秒),tomcat使用http 1.1協(xié)議,而http1.1默認(rèn)是長(zhǎng)連接。tomcat接受處理完請(qǐng)求后,socket沒(méi)有主動(dòng)關(guān)閉,因此如果在2小時(shí)內(nèi),請(qǐng)求數(shù)超過(guò)200個(gè),服務(wù)器就會(huì)出現(xiàn)上述假死現(xiàn)象。

    解決辦法:

    (1)檢查代碼,及時(shí)斷開(kāi)socket

    (2)修改tomcat配置文件,修改最大連接數(shù)(增大)

    ?(3)修改linux的TCP超時(shí)時(shí)間(socket生命周期)限制

    ?

    總結(jié)

    以上是生活随笔為你收集整理的Tomcat进程假死问题排查的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。