1. 程式人生 > >記一次臨近上執行緒序發生OOM

記一次臨近上執行緒序發生OOM

記一次臨近上執行緒序發生OOM

故事背景

最近一直在趕著應用上線,基本已經封包準備上線了,誰都不想在這時間點上出差錯~

當時應用已經上線pre,壓力測試已經通過,然而昨天下午測試組的同事突然找到我,說我的應用沒有消費kafka的資料,其他應用都已經同步消費了,搞得我一臉懵逼.

首先先上Consul上看服務的情況.發現pre上面除了我的應用,其他的都還健在!!!!(心裡有點方~)

趕緊連上伺服器檢視應用,發現日誌在停留在19號凌晨1點多.

[2019-07-19 01:46:33] [WARN ] [dc16dc8a-79d8-4ec5-adca-3f7bdff7bb7d] [http-nio-6030-exec-7] [AbstractHandlerExceptionResolver.java:140] [org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver] : Resolved [org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.OutOfMemoryError: GC overhead limit exceeded]

然後趕緊重啟讓測試同事去驗證資料同步~

排查問題

由於伺服器記憶體吃緊(8G),然後又需要部署好多個應用,預設啟動JVM引數設定得比較低(-Xms256m -Xmx512m -Xmn128m -XX:MaxPermSize=64m)~

由於沒有加上OOM dump引數,所以那時候也沒辦法去定位問題,只能是在本地將問題復現了.

  1. 首先在本地設定同樣的JVM引數,再加上發生OOM dump的路徑
-Xms256m -Xmx512m -Xmn128m -XX:MaxPermSize=64m -XX:ErrorFile=G:/heap/dump/hs_err_pid%p.log  -XX:HeapDumpPath=G:/heap/dump -XX:+HeapDumpOnOutOfMemoryError

然後讓程式跑一段時間,程式果真復現了!!!同時在我們設定好的發生OOM生成對應的堆檔案.

[2019-07-20 11:01:50] [ERROR] [c8dc279e-1e7e-4a1a-b646-0203f23e7ba6] [http-nio-6030-exec-116] [AdviceController.java:48] [com.ost.micro.scheduler.strategy.controller.AdviceController] : {}
org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.OutOfMemoryError: GC overhead limit exceeded
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1006)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:925)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:974)
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:877)

讓我們看一下現在的JVM堆圖: JVM堆

堆記憶體一直不回收,導致了OOM.

開啟Eclipse Memory Analyzer 分析生成的dump檔案.我們發現org.drools.core.impl.KnowledgeBaseImpl佔據了72%!!!

分析

解決問題

工作原因,接觸到了drools這個規則引擎,上面發現的問題明顯就是使用drools整出來的,由於程式裡面KieBase設定的是單例,那麼問題應該不是出在它身上。

先來看一下使用drools的程式碼~

public <T extends IRule> Integer execute(T t) {
    KieSession session = this.session();
    session.insert(t);
    int size = session.fireAllRules();
    if (Objects.nonNull(t.getIError())){
        throw new PayStrategyException(t.getIError());
    }
    return size;
}

此時我就在懷疑,是不是KieSession沒關閉導致的問題?看了一下獲取KieSession的描述~

/**
 * Creates a new {@link KieSession} using the default session configuration.
 * Don't forget to {@link KieSession#dispose()} session when you are done.
 *
 * @return created {@link KieSession}
 */

寫的很清楚,當執行完了之後,必須執行dispose()方法回收該session.修改程式碼如下

public <T extends IRule> Integer execute(T t) {
    KieSession session = null;
    try {
        session = this.session();
        session.insert(t);
        int size = session.fireAllRules();
        if (Objects.nonNull(t.getIError())) {
            throw new PayStrategyException(t.getIError());
        }
        return size;
    } finally {
        if (Objects.nonNull(session)) {
            session.dispose();
        }
    }
}

設定一下JVM引數(-Xmx1344M -Xms1344M -Xmn448M -XX:MaxMetaspaceSize=256M -XX:MetaspaceSize=256M -XX:+UseConcMarkSweepGC -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 -XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses -XX:+CMSClassUnloadingEnabled -XX:+ParallelRefProcEnabled -XX:+CMSScavengeBeforeRemark), 重新跑一下JVM堆如下圖: JVM堆

寫在最後

由於對Drools這個工作引擎不熟悉,所以差點搞出問題,看來還是要多看看官方的文件,記下此次事故提醒自己~

最後推薦一下生成JVM引數的網址http://xxfox.perfma.com/jvm/generate

相關推薦

臨近執行發生OOM

記一次臨近上執行緒序發生OOM 故事背景 最近一直在趕著應用上線,基本已經封包準備上線了,誰都不想在這時間點上出差錯~

python多執行+Queue的坑逼之旅

背景~ 在爬蟲中,需要用到代理ip,本人寫了一個模組來獲取和過濾代理ip(用多執行緒過濾,),,,在主執行緒中判斷可用的代理ip少於一定值了,獲取新的可用ip,問題來了。。多次呼叫代理ip模組之後報錯: can't start new thread                         !!!!!!

godaddy同一虛擬主機部署多站

題外話,專案上的一些感觸:非同步處理的目的不是為了聽起來很高階,而是為了更快速的響應客戶端且在背地裡準確的完成業務處理。 前提:你的主機支援多站部署,有的伺服器產品型別不支援。比如我的是godady的虛擬主機的旗艦版。 如果你有兩個域名,其中一個a.com已經部署在了go

伺服器配置GPU版本tensorflow的經歷

早就耳聞tensorflow-gpu與CUDA,cudnn三者之間版本匹配很複雜,今天算是見識到了。 首先看了下伺服器上的CUDA、cudnn版本,分別是CUDA8.0,cudnn7.0.4 這個匹配很奇怪,一般都是CUDA8 + cudnn6或者 CUDA9 + cudnn7 後來知

使用cmd執行java檔案遇到的坑...包括“使用java命令執行class檔案提示“錯誤:找不到或無法載入主類“的問題”

  今天寫了一個java檔案,類似聊天軟體的東西。在eclipse裡輸入輸出顯得沒感覺,於是乎就準備在cmd裡輸入和顯示輸出。如下圖,我準備執行的是ChatDemo.class檔案。路徑是:D:\workspace\Learn\bin\com\udp 。      然後我就開啟cmd,傻傻的輸入:cd D

docker傳映象到docker hub 的坑

想要上傳到docker hub 必須要先建立賬號,而docker的網站伺服器在國外 大陸的長城給攔截了導致我們申請賬號的時候顯示不出來人機互動驗證的圖片,解決辦法 :翻牆。。。。。 有了賬號後準備上傳映象,這時又碰到一個坑,那就是我提前建立了一個倉庫了,並且起了個名字叫做p

VSCodeC++的配置

軟件管理 cef task deb type spa window 訪問 方便 重點參考:這篇 其中在調試模塊出了問題,總是提示什麽進程運行時候以外退出,要安裝.Net4.6.2。 去網上下載安裝.Net4.6.2又無法安裝成功,總是說Windows Installer不能

HashMap多執行安全引起的事故

事故分析 最近一次web工程上線,上線大概半個小時,出現了報警,16核的伺服器的cpu使用了1123%,程式出異常了。 Cpu利用率過高一般是因為出現了出現了死迴圈,導致部分執行緒一直執行。佔用cpu時間。使用jstack工具dump出問題的那臺伺服器的棧資訊。死迴圈的話

【報錯記錄】Springboot 打包jar後放在伺服器執行失敗的排錯

使用mvn package -DSkipTests打包成jar包,然後上傳到伺服器。執行java -jar XXX.jar --env=pro後丟擲: [localhost-startStop-1] ERROR o.s.boot.web.embedded.tomcat.TomcatStart

整合spring-amqp後出現執行池為正常關閉。導致tomcat無法正常關閉顯示記憶體洩露的問題

起因:因為這幾天閒來無事,所以想著改造下舊專案的訂單自動取消功能,原本是通過定時任務輪詢掃描未支付訂單的,及時性不足並且浪費資料庫io的資源,所以就想用rabbitmq的死信佇列來完成延遲自動取消的功能。於是隨手copy了一段spring-amqp的Java Configur

.NET執行池最大執行數的限制-IIS併發瓶頸

.NET ThreadPool 最大執行緒數的限制 IIS併發瓶頸,有幾個地方,IIS執行緒池的最大佇列數,工作程序數,最大併發數。這些這裡就不展開。主要是最近因為過度使用Task 導致的執行緒數佔用過多,所以實驗了一下 .net執行緒池 的限制,分享一下。 注意IIS執行緒池與.NET執行緒池不是同一個東西

java socket學習(簡單實用多執行,實現多對多群聊)

學習過程是艱苦,學習結束是快樂的 目錄 用 [TOC]來生成目錄: 本來想寫一些文字描述描述,可是想不出來說啥。。。所以直接記錄程式碼了。。。 程式碼塊 因為喜歡把常量都提取出來 所以上來就是常量類: public class Const

生產問題--CompletableFuture預設執行

在jdk7中,我們使用執行緒池可能會使用ExecutorService,預設有四種方式Executors.newSingleeThreadPool()Executors.newFixedThreadPool()Executors.newCacheThreadPool()Exe

linux程序和執行排查 · JVM CPU高負載的排查辦法

前言通過本文,你將學會:1、linux上程序及程序中執行緒排查的基本方法,如檢視程序中的執行緒數此文中的執行緒一般指輕量級程序。檢視所有程序資訊 top -H 加上-H這個選項啟動top,top一行顯示一個執行緒(指的是(輕量級)程序? )。否則,它一行顯示一個程序。先輸入

處理rt-thread優先順序低執行無法執行

最近升級了rt-thread的核心程式碼,從3.0正式發行不久後,rt-thread採用了KConfig的配置方式,因為以前搞過linux核心配置,所以對KConfig不算太陌生,rt-thread的配置介面用起來還是相當不錯的,詳細用法可以參考官方相關文件。

執行堵塞

程式的主流程是 執行緒池Afetch資料,然後執行緒池 B delete資料 public void init() { final String fetchPoolName = "fetch-pool"; fetchVsearchDataExecutor = ne

愚蠢的操作--執行安全問題

前言 只有光頭才能變強。 文字已收錄至我的GitHub倉庫,歡迎Star:https://github.com/ZhongFuCheng3y/3y 記一次在工作中愚蠢的操作,本文關鍵字:執行緒安全 (我怎麼天天在寫Bug啊) 一、交代背景 我這邊有一個系統,提供一個RPC介面去傳送各種資訊(比如簡訊、

Task拋異常,呼叫執行處理而引發的一些隨想

記一次Task拋異常,呼叫執行緒處理而引發的一些隨想 多執行緒呼叫,任務執行緒丟擲異常如何在另一個執行緒(呼叫執行緒)中捕獲並進行處理的問題。 1.任務執行緒在任務執行緒執行語句上丟擲異常。 例如: 1 private void button2_Click(object sender, EventAr

postgresql數據庫函數執行問題

absolute btree 服務器 -m ans ica ret cpu integer 一、函數說明:首先編寫了三個函數:func_init.sqlfunc_process.sqlfunc_uuid.sql1、func_init.sql 入參為一個int類型number

[Windows10]修復註冊表相關血案:該文件沒有與之關聯的應用來執行該操作。請安裝應用,若已經安裝應用,請在“默認應用設置”頁面中創建關聯。

src 相關 overflow 還在 一次 註冊表 forum sin 嘗試 今天閑得蛋疼清理了一下右鍵菜單,於是在之後某時刻使用Everything的“雙擊路徑列打開目錄”功能時發現異常: [Window Title] Everything