<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          SpringBoot線上服務(wù)假死,CPU內(nèi)存正常,什么情況?

          共 6459字,需瀏覽 13分鐘

           ·

          2023-06-22 14:44

          背景

          開發(fā)小伙伴都知道線上服務(wù)掛掉,基本都是因為cpu或者內(nèi)存不足,出現(xiàn)GC頻繁O(jiān)OM之類的情況。本篇文章區(qū)別以上的情況給小伙伴們帶來不一樣的服務(wù)掛掉。

          還記得嗶哩嗶哩713事故中那場詭計多端的0嗎?

          對就是這個0,和本次事故沒關(guān)系,但深受啟發(fā)。

          問題排查

          老規(guī)矩在集群環(huán)境中同一個服務(wù)幾個節(jié)點無響應(yīng)。如不及時解決會可能形成雪崩效應(yīng)。

          優(yōu)先查看服務(wù)日志是否有報錯,禮貌習(xí)慣性查看服務(wù)cpu及內(nèi)存情況。先復(fù)習(xí)下,若服務(wù)無報錯。cpu或內(nèi)存出現(xiàn)異常,按如下步驟排查。

          常規(guī)排查

          1、查看服務(wù)進程中線程情況

          top?-H?-p?pid

          ps?-mp?pid?-o?THREAD,tid,time

          2、查看系統(tǒng)異常線程16進制

          printf?“%x\n”?nid

          3、查看異常線程堆棧信息

          jstack?pid?|?grep?number

          查看占用最大內(nèi)存對象前一百

          jmap?-histo?pid|head?-100

          導(dǎo)出到文件

          jstack?-l?PID?>>?a.log

          或dump信息使用工具Mat或JProfiler查看

          jmap?-dump:live,format=b,file=/dump.bin?pid

          經(jīng)過上面一通手法操作,足以解決此類常規(guī)報錯了,通常大多是原因各種循環(huán)遞歸、或數(shù)據(jù)庫慢查詢等。

          Mat使用

          在MAT中,會有兩種大小表示:

          • Shallow Size:表示對象自身占用的內(nèi)存大小,不包括它引用的對象。

          • Retained size:當前對象內(nèi)存大小+當前對象直接或間接引用的對象大小,全部的總和,簡單理解,就是當前對象被GC后,總共能釋放的內(nèi)存大小。

          Histogram視圖

          以Class Name為維度,分別展示各個類的對象數(shù)量。它默認是以byte為單位的,

          要顯示讓單位展示出來,點擊Window->Preferences選擇最后一項,點擊Apply and Close

          再重新打開Histogram視圖,就會生效了。

          Leak Suspects

          報表很直觀地展現(xiàn)了一個餅圖,圖中顏色深的部分表示可能存在內(nèi)存泄漏的嫌疑。

          通過這個指標可以快速定位內(nèi)存泄漏地方出現(xiàn)在哪個類方法里的哪行代碼。

          本次問題排查

          1、 信息收集分析

          因服務(wù)健康監(jiān)測無響應(yīng),cpu及內(nèi)存情況正常,直接查看堆棧信息,看看線程都在干什么

          jstack?-l?PID?>>?a.log

          Jstack的輸出中,Java線程狀態(tài)主要是以下幾種:

          • RUNNABLE 線程運行中或I/O等待

          • BLOCKED 線程在等待monitor鎖(synchronized關(guān)鍵字)

          • TIMED_WAITING 線程在等待喚醒,但設(shè)置了時限

          • WAITING 線程在無限等待喚醒

          發(fā)現(xiàn)都是WAITING線程。

          "http-nio-8888-exec-6666"?#8833?daemon?prio=5?os_prio=0?tid=0x00001f2f0016e100?nid=0x667d?waiting?on?condition?[0x00002f1de3c5200]
          java.lang.Thread.State:?WAITING?(parking)
          at?sun.misc.Unsafe.park(Native?Method)
          -?parking?to?wait?for??<0x00000007156a29c8>?(a?java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
          at?java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
          at?java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
          at?com.alibaba.druid.pool.DruidDataSource.takeLast(DruidDataSource.java:1897)
          at?com.alibaba.druid.pool.DruidDataSource.getConnectionInternal(DruidDataSource.java:1458)
          at?com.alibaba.druid.pool.DruidDataSource.getConnectionDirect(DruidDataSource.java:1253)
          at?com.alibaba.druid.filter.FilterChainImpl.dataSource_connect(FilterChainImpl.java:4619)
          at?com.alibaba.druid.filter.stat.StatFilter.dataSource_getConnection(StatFilter.java:680)
          at?com.alibaba.druid.filter.FilterChainImpl.dataSource_connect(FilterChainImpl.java:4615)
          at?com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1231)
          at?com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1223)
          at?com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:90)
          at?com.baomidou.dynamic.datasource.ds.ItemDataSource.getConnection(ItemDataSource.java:56)
          at?com.baomidou.dynamic.datasource.ds.AbstractRoutingDataSource.getConnection(AbstractRoutingDataSource.java:48)
          at?org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111)
          at?org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77)
          at?org.mybatis.spring.transaction.SpringManagedTransaction.openConnection(SpringManagedTransaction.java:82)
          at?org.mybatis.spring.transaction.SpringManagedTransaction.getConnection(SpringManagedTransaction.java:68)
          at?org.apache.ibatis.executor.BaseExecutor.getConnection(BaseExecutor.java:336)
          at?org.apache.ibatis.executor.SimpleExecutor.prepareStatement(SimpleExecutor.java:84)
          at?org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:62)
          at?org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:324)
          at?org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:156)
          at?org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:109)
          at?com.github.pagehelper.PageInterceptor.intercept(PageInterceptor.java:143)
          at?org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:61)
          at?com.sun.proxy.$Proxy571.query(Unknown?Source)

          2、定位關(guān)鍵信息,追蹤源代碼

          ??at?java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
          ??at?com.alibaba.druid.pool.DruidDataSource.takeLast(DruidDataSource.java:1897)
          DruidConnectionHolder?takeLast()?throws?InterruptedException,?SQLException?{
          try?{
          while?(poolingCount?==?0)?{
          emptySignal();?//?send?signal?to?CreateThread?create?connection

          ??????????????if?(failFast?&&?isFailContinuous())?{
          ??????????????????throw?new?DataSourceNotAvailableException(createError);
          ??????????????}

          ??????????????notEmptyWaitThreadCount++;
          ??????????????if?(notEmptyWaitThreadCount?>?notEmptyWaitThreadPeak)?{
          ??????????????????notEmptyWaitThreadPeak?=?notEmptyWaitThreadCount;
          ??????????????}
          ??????????????try?{
          ??????????????????//?數(shù)據(jù)庫的連接都沒有釋放且被占用,連接池中無可用連接,導(dǎo)致請求被阻塞
          ??????????????????notEmpty.await();?//?signal?by?recycle?or?creator
          ??????????????}?finally?{
          ??????????????????notEmptyWaitThreadCount--;
          ??????????????}
          ??????????????notEmptyWaitCount++;

          ??????????????if?(!enable)?{
          ??????????????????connectErrorCountUpdater.incrementAndGet(this);
          ??????????????????throw?new?DataSourceDisableException();
          ??????????????}
          ??????????}
          ??????}?catch?(InterruptedException?ie)?{
          ??????????notEmpty.signal();?//?propagate?to?non-interrupted?thread
          ??????????notEmptySignalCount++;
          ??????????throw?ie;
          ??????}

          ??????decrementPoolingCount();
          ??????DruidConnectionHolder?last?=?connections[poolingCount];
          ??????connections[poolingCount]?=?null;

          ??????return?last;
          }

          結(jié)合日志報錯定位到問題代碼。因報錯可用連接沒有正常釋放,導(dǎo)致一直await卡死。

          問題代碼如下:

          try?{
          ??SqlSession?sqlSession?=?sqlSessionFactory.openSession(ExecutorType.BATCH);
          ??TestMapper?mapper?=?sqlSession.getMapper(TestMapper.class);
          ??mapper.insetList(list);
          ??sqlSession.flushStatements();
          }?catch?(Exception?e)?{
          ???e.printStackTrace();
          }

          問題復(fù)現(xiàn)

          按照以上信息在多活環(huán)境復(fù)現(xiàn)。因線程被打滿且都在等待導(dǎo)致監(jiān)控檢查無響應(yīng)。

          tomcat線程被打滿:

          tomcat默認參數(shù):

          最大工作線程數(shù),默認200。

          server.tomcat.max-threads=200

          最大連接數(shù)默認是10000

          server.tomcat.max-connections=10000

          等待隊列長度,默認100。

          server.tomcat.accept-count=100

          最小工作空閑線程數(shù),默認10。

          server.tomcat.min-spare-threads=100

          Druid連接池的默認參數(shù)如下:

          Druid連接池的配置參數(shù)如下:

          解決

          1、Druid連接池的配置超時參數(shù)

          spring:?
          ??redis:
          ????host:?localhost
          ????port:?6379
          ????password:?
          ??datasource:
          ????druid:
          ??????stat-view-servlet:
          ????????enabled:?true
          ????????loginUsername:?admin
          ????????loginPassword:?123456
          ????dynamic:
          ??????druid:
          ????????initial-size:?5
          ????????min-idle:?5
          ????????maxActive:?20
          ????????maxWait:?60000
          ????????timeBetweenEvictionRunsMillis:?60000
          ????????minEvictableIdleTimeMillis:?300000
          ????????validationQuery:?SELECT?1?FROM?DUAL
          ????????testWhileIdle:?true
          ????????testOnBorrow:?false
          ????????testOnReturn:?false
          ????????poolPreparedStatements:?true
          ????????maxPoolPreparedStatementPerConnectionSize:?20
          ????????filters:?stat,slf4j,wall
          ????????connectionProperties:?druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000

          2、異常及時關(guān)閉連接

          sqlSession.close();

          來源:blog.csdn.net/zhangcongyi420/

          article/details/131139599

          瀏覽 53
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日本大香蕉在线视频 | 人人操人人色人人 | 亚洲精品偷拍 | 一级黄色片在线观看 | 国产精品午夜在线观看 |