www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 架構(gòu)師社區(qū)
[導(dǎo)讀]來自:匠心Java 情景 項(xiàng)目上線了一個(gè)接口,先灰度一臺(tái)機(jī)器觀察調(diào)用情況;接口不斷的調(diào)用,過了一段時(shí)間,發(fā)現(xiàn)機(jī)器上的接口調(diào)用開始報(bào) OOM異常 ! 當(dāng)天就是上線deadline了,刺激。。 發(fā)現(xiàn)問題 第一步,使用?jps命令獲取出問題jvm進(jìn)程的進(jìn)程ID 使用 jps-l-m獲取

事務(wù)處理不當(dāng),線上接口又雙叒內(nèi)存泄漏了!(附圖解問題全過程)

來自:匠心Java


情景

項(xiàng)目上線了一個(gè)接口,先灰度一臺(tái)機(jī)器觀察調(diào)用情況;接口不斷的調(diào)用,過了一段時(shí)間,發(fā)現(xiàn)機(jī)器上的接口調(diào)用開始報(bào) OOM異常 !

當(dāng)天就是上線deadline了,刺激。。事務(wù)處理不當(dāng),線上接口又雙叒內(nèi)存泄漏了!(附圖解問題全過程)

發(fā)現(xiàn)問題

第一步,使用 jps命令獲取出問題jvm進(jìn)程的進(jìn)程ID

使用 jps-l-m獲取到當(dāng)前jvm進(jìn)程的pid,通過上述命令獲取到了服務(wù)的進(jìn)程號(hào):427726 (此處假設(shè)為這個(gè))事務(wù)處理不當(dāng),線上接口又雙叒內(nèi)存泄漏了!(附圖解問題全過程)jps命令

jps(JVM Process Status Tool):顯示指定系統(tǒng)內(nèi)所有的HotSpot虛擬機(jī)進(jìn)程

jps-l-m :參數(shù)-l列出機(jī)器上所有jvm進(jìn)程,-m顯示出JVM啟動(dòng)時(shí)傳遞給main()的參數(shù)

第二步,使用 jstat觀察jvm狀態(tài),發(fā)現(xiàn)問題

因?yàn)槭荗OM異常,所以我們首先重啟機(jī)器觀察了JVM的運(yùn)行情況;

我們使用 jstat-gc pid time命令觀察GC,發(fā)現(xiàn)GC在YGC后,GC掉的內(nèi)存并不多,每次YGC后都有一部分內(nèi)存未回收,導(dǎo)致在多次YGC后回收不掉的內(nèi)存被挪到堆的old區(qū),old滿了之后FGC發(fā)現(xiàn)也是回收不掉;

這里基本可以確定是內(nèi)存泄漏的問題了,下面我們有簡(jiǎn)單看了下機(jī)器的cpu、內(nèi)存、磁盤狀態(tài)

jstat命令:

jstat(JVM statistics Monitoring)是用于監(jiān)視虛擬機(jī)運(yùn)行時(shí)狀態(tài)信息的命令,它可以顯示出虛擬機(jī)進(jìn)程中的類裝載、內(nèi)存、垃圾收集、JIT編譯等運(yùn)行數(shù)據(jù)。

jstat-gc pid time :-gc 監(jiān)控jvm的gc信息,pid 監(jiān)控的jvm進(jìn)程id,time每個(gè)多少毫秒刷新一次

jstat-gccause pid time :-gccause 監(jiān)控gc信息并顯示上次gc原因,pid 監(jiān)控的jvm進(jìn)程id,time每個(gè)多少毫秒刷新一次

jstat-classpid time:-class 監(jiān)控jvm的類加載信息,pid 監(jiān)控的jvm進(jìn)程id,time每個(gè)多少毫秒刷新一次

在這里先簡(jiǎn)單說一下,堆的GC:

在GC開始的時(shí)候,對(duì)象只會(huì)存在于Eden區(qū)和名為“From”的Survivor區(qū),Survivor區(qū)“To”是空的。緊接著進(jìn)行GC,Eden區(qū)中所有存活的對(duì)象都會(huì)被復(fù)制到“To”,而在“From”區(qū)中,仍存活的對(duì)象會(huì)根據(jù)他們的年齡值來決定去向。

年齡達(dá)到一定值(年齡閾值,可以通過-XX:MaxTenuringThreshold來設(shè)置)的對(duì)象會(huì)被移動(dòng)到年老代中,沒有達(dá)到閾值的對(duì)象會(huì)被復(fù)制到“To”區(qū)域。經(jīng)過這次GC后,Eden區(qū)和From區(qū)已經(jīng)被清空。這個(gè)時(shí)候,“From”和“To”會(huì)交換他們的角色,也就是新的“To”就是上次GC前的“From”,新的“From”就是上次GC前的“To”。不管怎樣,都會(huì)保證名為To的Survivor區(qū)域是空的,minor GC會(huì)一直重復(fù)這樣的過程。

第三步,觀察機(jī)器狀態(tài),確認(rèn)問題

使用 top-p pid獲取進(jìn)程的cpu和內(nèi)存使用率;查看RES 和 %CPU %MEM三個(gè)指標(biāo):事務(wù)處理不當(dāng),線上接口又雙叒內(nèi)存泄漏了?。ǜ綀D解問題全過程)

在這里先簡(jiǎn)單說一下,top命令展示的內(nèi)容:

VIRT:virtual memory usage 虛擬內(nèi)存 1、進(jìn)程“需要的”虛擬內(nèi)存大小,包括進(jìn)程使用的庫(kù)、代碼、數(shù)據(jù)等 2、假如進(jìn)程申請(qǐng)100m的內(nèi)存,但實(shí)際只使用了10m,那么它會(huì)增長(zhǎng)100m,而不是實(shí)際的使用量

RES:resident memory usage 常駐內(nèi)存 1、進(jìn)程當(dāng)前使用的內(nèi)存大小,但不包括swap out 2、包含其他進(jìn)程的共享 3、如果申請(qǐng)100m的內(nèi)存,實(shí)際使用10m,它只增長(zhǎng)10m,與VIRT相反 4、關(guān)于庫(kù)占用內(nèi)存的情況,它只統(tǒng)計(jì)加載的庫(kù)文件所占內(nèi)存大小

SHR:shared memory 共享內(nèi)存 1、除了自身進(jìn)程的共享內(nèi)存,也包括其他進(jìn)程的共享內(nèi)存 2、雖然進(jìn)程只使用了幾個(gè)共享庫(kù)的函數(shù),但它包含了整個(gè)共享庫(kù)的大小 3、計(jì)算某個(gè)進(jìn)程所占的物理內(nèi)存大小公式:RES – SHR 4、swap out后,它將會(huì)降下來

DATA 1、數(shù)據(jù)占用的內(nèi)存。如果top沒有顯示,按f鍵可以顯示出來。2、真正的該程序要求的數(shù)據(jù)空間,是真正在運(yùn)行中要使用的。

ps : 如果程序占用實(shí)存比較多,說明程序申請(qǐng)內(nèi)存多,實(shí)際使用的空間也多。如果程序占用虛存比較多,說明程序申請(qǐng)來很多空間,但是沒有使用。

發(fā)現(xiàn)機(jī)器的自身狀態(tài)不存在問題, so毋庸置疑,發(fā)現(xiàn)問題了,典型的內(nèi)存泄漏。。

第四步,使用jmap獲取jvm進(jìn)程dump文件

我們使用 jmap-dump:format=b,file=dump_file_name pid 命令,將當(dāng)前機(jī)器的jvm的狀態(tài)dump下來或缺的一份dump文件,用做下面的分析

jmap命令:

jmap(JVM Memory Map)命令用于生成heap dump文件,還可以查詢finalize執(zhí)行隊(duì)列、Java堆和永久代的詳細(xì)信息,如當(dāng)前使用率、當(dāng)前使用的是哪種收集器等。

jmap-dump:format=b,file=dump_file_name pid :file=指定輸出數(shù)據(jù)文件名, pid jvm進(jìn)程號(hào)

接下來,回滾灰度的機(jī)器,開始解決問題=.=

解決問題

第一步,dump文件分析

在這里,我們分析dump文件,使用的 Jprofiler軟件,就是下面這個(gè)東東:事務(wù)處理不當(dāng),線上接口又雙叒內(nèi)存泄漏了?。ǜ綀D解問題全過程)

具體的使用方法,在這就不再贅述了,下面將dump文件導(dǎo)入到 Jprofiler中:選擇 HeapWalker 中的 CurrentObjectSet,這里面顯示的是當(dāng)前的類的占用資源,從占用空間從大到小排序;事務(wù)處理不當(dāng),線上接口又雙叒內(nèi)存泄漏了?。ǜ綀D解問題全過程)從上圖中,沒有觀察出什么問題,我們點(diǎn)擊 BiggestObjects,查看哪個(gè)對(duì)象的占用的內(nèi)存高:事務(wù)處理不當(dāng),線上接口又雙叒內(nèi)存泄漏了?。ǜ綀D解問題全過程)從上圖中,我們發(fā)現(xiàn) org.janusgraph.graphdb.database.StandardJanusGraph這個(gè)對(duì)象居然占用了高達(dá)724M的內(nèi)存!

看來內(nèi)存泄漏八九不離十就是這個(gè)對(duì)象的問題了!再點(diǎn)開看看 ,如下圖,可以發(fā)現(xiàn)是一個(gè) openTransactions的類型為 ConcurrentHashMap的數(shù)據(jù)結(jié)構(gòu):事務(wù)處理不當(dāng),線上接口又雙叒內(nèi)存泄漏了?。ǜ綀D解問題全過程)

第二步,源碼查找定位代碼

這到底是什么對(duì)象呢,去項(xiàng)目中查找一下,打開idea-打開項(xiàng)目-雙擊shift鍵-打開全局類查找-輸入 StandardJanusGraph,如下圖:事務(wù)處理不當(dāng),線上接口又雙叒內(nèi)存泄漏了?。ǜ綀D解問題全過程)發(fā)現(xiàn)是我們項(xiàng)目使用的圖數(shù)據(jù)庫(kù) janusgraph的一個(gè)類,找到對(duì)應(yīng)的數(shù)據(jù)結(jié)構(gòu):類型定義:

   
  1. private Set<StandardJanusGraphTx> openTransactions;

初始化為一個(gè)ConcurrentHashMap:

   
  1. openTransactions = Collections.newSetFromMap(new

  2. ConcurrentHashMap<StandardJanusGraphTx, Boolean>(100,

  3. 0.75f, 1));

觀察上述代碼,我們可以看到,里面的存儲(chǔ)的 StandardJanusGraphTx從字面意義上理解是janusgraph框架中的事務(wù)對(duì)象,下面往上追一下代碼,看看什么時(shí)候會(huì)往這個(gè)Map中賦值:

   
  1. // 找到執(zhí)行openTransactions.add()的方法

  2. public StandardJanusGraphTx newTransaction(final TransactionConfiguration configuration) {

  3. if (!isOpen) ExceptionFactory.graphShutdown();

  4. try {

  5. StandardJanusGraphTx tx = new StandardJanusGraphTx(this, configuration);

  6. tx.setBackendTransaction(openBackendTransaction(tx));

  7. openTransactions.add(tx); // 注意!此處對(duì)上述的map對(duì)象進(jìn)行了add

  8. return tx;

  9. } catch (BackendException e) {

  10. throw new JanusGraphException("Could not start new transaction", e);

  11. }

  12. }

  13. // 上述發(fā)現(xiàn),是一個(gè)newTransaction,創(chuàng)建事務(wù)的一個(gè)方法,為確保起見,再往上跟找到調(diào)用上述方法的類:

  14. public JanusGraphTransaction start() {

  15. TransactionConfiguration immutable = new ImmutableTxCfg(isReadOnly, hasEnabledBatchLoading,

  16. assignIDsImmediately, preloadedData, forceIndexUsage, verifyExternalVertexExistence,

  17. verifyInternalVertexExistence, acquireLocks, verifyUniqueness,

  18. propertyPrefetching, singleThreaded, threadBound, getTimestampProvider(), userCommitTime,

  19. indexCacheWeight, getVertexCacheSize(), getDirtyVertexSize(),

  20. logIdentifier, restrictedPartitions, groupName,

  21. defaultSchemaMaker, customOptions);

  22. return graph.newTransaction(immutable); // 注意!此處調(diào)用了上述的newTransaction方法

  23. }

  24. // 接著找上層調(diào)用,發(fā)現(xiàn)了最上層的方法

  25. public JanusGraphTransaction newTransaction() {

  26. return buildTransaction().start(); // 此處調(diào)用了上述的start方法

  27. }

在我們對(duì)圖數(shù)據(jù)庫(kù)中圖數(shù)據(jù)操作的過程中,采用的是手動(dòng)創(chuàng)建事務(wù)的方式,在每次查詢圖數(shù)據(jù)庫(kù)之前,我們都會(huì)調(diào)用類似于 dataDao.begin()代碼, 其中就是調(diào)用的 publicJanusGraphTransactionnewTransaction()這個(gè)方法;

最后,我們簡(jiǎn)單的看下源碼可以發(fā)現(xiàn),從上述內(nèi)存泄漏的map中去除數(shù)據(jù)的邏輯就是 commit事務(wù)的接口,調(diào)用鏈如下:

   
  1. public void closeTransaction(StandardJanusGraphTx tx) {

  2. openTransactions.remove(tx); // 從map中刪除StandardJanusGraphTx對(duì)象

  3. }


  4. private void releaseTransaction() {

  5. isOpen = false;

  6. graph.closeTransaction(this); // 調(diào)用上述closeTransaction方法

  7. vertexCache.close();

  8. }


  9. public synchronized void commit() {

  10. Preconditions.checkArgument(isOpen(), "The transaction has already been closed");

  11. boolean success = false;

  12. if (null != config.getGroupName()) {

  13. MetricManager.INSTANCE.getCounter(config.getGroupName(), "tx", "commit").inc();

  14. }

  15. try {

  16. if (hasModifications()) {

  17. graph.commit(addedRelations.getAll(), deletedRelations.values(), this);

  18. } else {

  19. txHandle.commit(); // 這個(gè)commit方法中釋放事務(wù)也是調(diào)用releaseTransaction

  20. }

  21. success = true;

  22. } catch (Exception e) {

  23. try {

  24. txHandle.rollback();

  25. } catch (BackendException e1) {

  26. throw new JanusGraphException("Could not rollback after a failed commit", e);

  27. }

  28. throw new JanusGraphException("Could not commit transaction due to exception during persistence", e);

  29. } finally {

  30. releaseTransaction(); // // 調(diào)用releaseTransaction

  31. if (null != config.getGroupName() && !success) {

  32. MetricManager.INSTANCE.getCounter(config.getGroupName(), "tx", "commit.exceptions").inc();

  33. }

  34. }

  35. }

終于,我們找到了內(nèi)存泄漏的根源所在:項(xiàng)目代碼中存在調(diào)用了事務(wù) begin但是沒有 commit的代碼!

第三步,修復(fù)問題驗(yàn)證

解決問題:找到內(nèi)存泄漏接口的代碼,并發(fā)現(xiàn)了沒有commit()的位置,try-catch-finally中添加上了commit()代碼;

提交-部署-發(fā)布-灰度一臺(tái)機(jī)器后觀察內(nèi)存泄漏的現(xiàn)象消失,GC回收正常;

內(nèi)存泄漏問題解決,項(xiàng)目如期上線~

最后

大家,有沒有遇到過內(nèi)存泄漏的情況,歡迎在評(píng)論區(qū)說出你的故事=.=

寫這篇文章耗費(fèi)的時(shí)間超出了我的預(yù)料,預(yù)計(jì)2個(gè)小時(shí)寫完,結(jié)果花了一下午的時(shí)間...

原創(chuàng)不易,如果大家有所收獲,希望大家可以在看支持一下~

特別推薦一個(gè)分享架構(gòu)+算法的優(yōu)質(zhì)內(nèi)容,還沒關(guān)注的小伙伴,可以長(zhǎng)按關(guān)注一下:

事務(wù)處理不當(dāng),線上接口又雙叒內(nèi)存泄漏了?。ǜ綀D解問題全過程)

長(zhǎng)按訂閱更多精彩▼

事務(wù)處理不當(dāng),線上接口又雙叒內(nèi)存泄漏了?。ǜ綀D解問題全過程)

如有收獲,點(diǎn)個(gè)在看,誠(chéng)摯感謝

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉