記錄測試環境hertzbeat壓測cpu高,oom問題排查。jvm,mat,visulavm

記錄測試環境hertzbeat壓測cpu高,oom問題排查。jvm,mat,visulavm

一,問題背景

運維平臺,采用hertzbeat開源代碼進行采集。對單個設備連接,采集9個指標。目前hertzbeat對1個設備連接,下發9次單獨采集并獲取采集結果,存放到tsdb數據庫。測試環境進行壓測,造500個設備,hertzbeat共計500個采集任務,運行一天后,hertzbeat web頁面采集任務宕機約300+,且正常狀態的采集任務,查看采集詳情,只有實時數據,沒有歷史數據。(將查詢時間擴大到1天,則發現歷史數據只在20多分鐘的時間段內才有)。

問題整理:
1.hertzbeat任務運行一天后存在宕機
2.hertzbeat任務歷史采集數據無法查看
3.hertzbeat服務cpu在200+
4.運維服務oom

本文討論1,2,3問題。第4問題不做討論。
其中問題,1,3是同一種。2單獨。

涉及的核心服務:
運維服務,hertzbeat服務,kafka,模擬設備,emqx,tsdb時序數據庫(存放采集數據的歷史記錄)

服務部署信息和版本信息
k8s部署
hertzbeat 分支: 1.6.1
emqx版本 5.7.1
mqtt協議:5.0

核心服務配置:
hertzbeat服務,最大堆15g

采集流程:
hertzbeat 通過mqtt協議下發采集任務,模擬設備收到消息后,返回采集數據(mqtt協議消息都通過emqx broker轉發),hertzbeat收到采集結果后,通過kafka發送采集結果消息,然后hertzbeat和運維服務消費這個消息。

流程圖如下:
在這里插入圖片描述

二,使用工具

k8s:部署服務的部署平臺
VisulaVm:堆,線程分析工具
MAT:內存泄漏分析工具
豆包:工具人

MAT下載地址:
https://blog.csdn.net/wutrg1502/article/details/132315468

三,排查問題2,hertzbeat采集歷史數據無法查看。

排查思路:
hertzbeat采集數據收到后由kafka發送后,hertzbeat消費,然后寫入tsdb數據庫。
已知模擬器不停在上報。
檢查點:
kafaka消息是否有積壓情況。
tsdb是否有歷史數據。

kafka看是否消息積壓:
進入k8s的kafka容器,cd bin
然后執行:

查看消費組:./kafka-consumer-groups.sh --list --bootstrap-server localhost:9092
看 hertzbeat消費./kafka-consumer-groups.sh --describe --group xxt-consumer --bootstrap-server localhost:9092 | grep xxtopic

數字分別為:已消費,總數,待消費(這個圖是修復后,修復前有大量消息積壓。也就解釋了為什么tsdb數據庫沒有歷史數據寫入。)

在這里插入圖片描述

如何找到寫入tsdb數據庫代碼:

直接停止tsdb數據庫服務,看hertzbeat報錯日志,根據調用棧找到代碼。

原因是,hertzbeat將指標拆成多個小的循環進行調用并存儲到tsdb數據庫。將單條處理為批量調用:

List<CollectRep.Field> fields = metricsData.getFieldsList();Long[] timestamp = new Long[]{metricsData.getTime()};Map<String, Double> fieldsValue = new HashMap<>(fields.size());Map<String, String> labels = new HashMap<>(fields.size());StringBuilder batchPayload = new StringBuilder();int qty = 0;for (CollectRep.ValueRow valueRow : metricsData.getValuesList()) {fieldsValue.clear();labels.clear();for (int index = 0; index < fields.size(); index++) {CollectRep.Field field = fields.get(index);String value = valueRow.getColumns(index);if (field.getType() == CommonConstants.TYPE_NUMBER && !field.getLabel()) {// number metrics dataif (!CommonConstants.NULL_VALUE.equals(value)) {fieldsValue.put(field.getName(), CommonUtil.parseStrDouble(value));}}// labelif (field.getLabel() && !CommonConstants.NULL_VALUE.equals(value)) {labels.put(field.getName(), value);}}for (Map.Entry<String, Double> entry : fieldsValue.entrySet()) {if (entry.getKey() != null && entry.getValue() != null) {try {labels.putAll(defaultLabels);String labelName = isPrometheusAuto ? metricsData.getMetrics() : metricsData.getMetrics() + SPILT + entry.getKey();labels.put(LABEL_KEY_NAME, labelName);labels.put(MONITOR_METRIC_KEY, entry.getKey());VictoriaMetricsContent content = VictoriaMetricsContent.builder().metric(labels).values(new Double[]{entry.getValue()}).timestamps(timestamp).build();batchPayload.append(JsonUtil.toJson(content)).append("\n");qty = qty + 1;} catch (Exception e) {log.error("flush metrics data to victoria-metrics error: {}.", e.getMessage(), e);}}}}if (qty > 0){sendBatchData(batchPayload);}}

三,排查問題1,3,hertzbeat采集任務宕機和cpu高問題

生成堆,線程dump文件

進入hertzbeat容器,生成堆,線程的dump文件

命令:

1 和22 是容器中java的進程id
如何查看:
jps -v

生成線程堆棧
jstack 1 > /home/app/logs/thread_dump_$(date +%Y%m%d%H%M%S).txtjstack 1 > /home/app/logs/thread_dump_$(date +%Y%m%d%H%M%S).tdump生成堆棧  
jmap -dump:format=b,file=/home/app/logs/heap_dump_$(date +%Y%m%d%H%M%S).hprof 1jstack 22 > /home/app/logs/hert_thread_dump_$(date +%Y%m%d%H%M%S).tdump
jmap -dump:format=b,file=/home/app/logs/hert_heap_dump_$(date +%Y%m%d%H%M%S).hprof 21

注意,要重啟pod前先將轉儲的文件拷貝到本地電腦。

快速試錯

重啟hertzbeat服務。重啟后發現原本宕機的采集任務,恢復上線。
推測是hertzbeat服務性能問題導致采集任務宕機。

信息可視化

連接visulaVm

因為是測試環境,可以使用visulaVm對hertzbeat服務做一個堆,線程監控。本地windows安裝visulaVm后連接遠程服務。
具體連接操作為:(待完善,k8s管理的服務,開通jconsle連接端口)

連接好后如圖:
本次處理中關注的關鍵信息:
Uptime: jvm運行時長
Heap/metaspace:堆信息/元空間
Threads:線程創建和銷毀信息

在這里插入圖片描述
圖中反饋的問題:
1.堆占用巨大,快10G并且在頻繁gc (首先應該限制這么大的堆)
2.線程創建總數 5w+,存活 300+,守護線程300+。反映出有非常多的線程創建后就銷毀。(頻繁創建線程會消耗cpu)

問題處理:
注意,如果有k8s可視化頁面,在頁面操作就行。比如rancher,以下以rancher為例(直接用命令修改k8s配置文件也是相同的)
1.針對大堆,檢查容器啟動命令,發現k8s沒有配置pod資源限制,和java -jar啟動沒有設置堆信息。
查看k8s資源限制:

修改k8s配置文件

kubectl edit deployment hertzbeat-serv(服務名稱) -n devops(命名空間)

沒有resources limit字樣。

設置資源限制路徑:
deployment -> edit config -> resources -> memoryLimit (設置的是pod的資源,java啟動比這個小)
配置為3Gi

設置java啟動參數。找到hertzbeat啟動命令添加 -Xmx2048m -Xms2048m

2.針對線程創建問題。

在這里插入圖片描述
選擇live thread和 finished thread進行查看。
觀察到有大量live thread是與mqtt有關,這個是自定義拓展的代碼線程。
如果在上面就能判斷創建后銷毀的線程大部分都是mqtt相關的話,可以直接搜索代碼。關鍵字 mqtt之類。

我之前使用豆包生成的java代碼解析jstack生成的 線程dump.txt文件(并發截圖時的線程dump),結論為:
===== MQTT線程統計結果 =====
當前存活的MQTT線程總數:219
估算的MQTT線程總創建數:36963
估算的MQTT線程銷毀數:36744

找到代碼:
CommonDispatcher 類中處理任務下發的線程池,發現創建的線程池為:

        int coreSize = Math.max(2, Runtime.getRuntime().availableProcessors());int maxSize = Runtime.getRuntime().availableProcessors() * 16;workerExecutor = new ThreadPoolExecutor(coreSize,maxSize,10,TimeUnit.SECONDS,new SynchronousQueue<>(),threadFactory,new ThreadPoolExecutor.AbortPolicy());

SynchronousQueue隊列的意思時,核心線程用完后,任務到達隊列,則直接按照最大線程數進行創建。
參考visulavm線程存活信息,重新設置新的線程池進行替換,原hertzbeat線程池不動。

新線程設置為:

        int coreSize = 500;int maxSize = 1500;collectExecutor = new ThreadPoolExecutor(coreSize,maxSize,10,TimeUnit.MINUTES,new SynchronousQueue<>(),threadFactory,new ThreadPoolExecutor.AbortPolicy());
修改jvm堆為2g,和線程池500后運行觀察結果

結果圖:
在這里插入圖片描述
問題:
1.hertzbeat堆最大2g,運行近40分鐘后pod被重啟,看著是oom kill,查看rancher,發現這個pod的確被oom kill,且存在restart次數。

解決問題:
1.線程創建多,且沒有線程復用的問題。

繼續排查:
通過上面的圖可以看出,heap圖,不停在gc,但每gc一次,堆的使用則比之前大一點,直到達到最大堆觸發 oom被k8s kill重拉。
懷疑是gc后對象沒有被及時清理,或者堆內存泄漏。

visulaVm分析堆內存占用

將堆dump文件導入visulaVm。
在summary頁面。

在這里插入圖片描述
發現mqtt相關的占到了77.8%

右鍵這行,點擊open in new tab

看到類 MqttSubscribedPublishFlowTree 這個是mqtt發布訂閱的代碼。
于是想到業務上是用mqtt的同步響應模式進行數據采集。找到這個代碼
大概為:
每次hertzbeat執行采集,都會觸發到這個代碼。
代碼先訂閱,在發布采集消息。

在高頻的采集任務下,會出現高頻訂閱,而訂閱本質是長期關聯的,因此優化為單個設備采集topic就訂閱一次。

優化這個后,運行2小時,查看堆dump文件:

在這里插入圖片描述

使用mat分析堆內存泄漏

獲取java堆的dump文件,存放到本地,用mat打開。
注意mat如果打不開卡死了,則需要配置他內存大小,路徑:
mat安裝文件夾,MemoryAnalyzer.ini文件,設置-Xmx和-Xms,默認1g。我給的3g

使用mat加載dump文件。
點file -> open xx
導入后總覽為:
在這里插入圖片描述
推薦查看:
Leak Suspects

在這里插入圖片描述
這里會列出嫌疑比較大的。

上面已經有類名了,直接搜這個類名:
MemoryDataStorage
發現是hertzbeat存儲實時數據的核心類。有2中實現。內存,redis。

查看hertzbeat nacos配置:

  real-time:memory:enabled: trueinit-size: 16redis:enabled: false# redis mode: single, sentinel, cluster. Default is singlemode: single# separate each address with comma when using cluster mode, eg: 127.0.0.1:6379,127.0.0.1:6380address: 127.0.0.1:6379# enter master name when using sentinel modemasterName: mymasterpassword: 123456# redis db index, default: DB0db: 0

的確,這里也使用的是內存。
切換到redis 后重啟服務。

排查內存泄漏后繼續觀察

visulaVm截圖:
已運行2小時多。
在這里插入圖片描述
此時繼續查看mat信息:

在這里插入圖片描述
這個problem 1在上面mat圖的第二個problerm。
暫不處理這個,繼續觀察hertzbeat再看看。

更新運行結果:

在這里插入圖片描述
結果上看優化有效果。7小時,沒有崩潰。
看服務器上top信息,hertzbeat cpu在30~80%之間,多數在60%以下。
看hertzbeat 采集任務,沒有宕機。
看web采集結果正常。
到此優化完成。

到此,優化的點為:

修改前:visulaVm監控8h內總計創建7w線程,活躍線程400+,守護線程100+,且堆占用到了15G,且hertzbeat頁面,存在約一半采集任務宕機情況。

1.修改了執行采集任務的線程池,配置核心500 最大1500
修改點:CommonDispatcher中分發采集任務的線程池改造
修改后:觀察2H,線程創建總數1100左右,存活640,守護線程100+
2.分析堆dump文件,查看主要占用內存數據,找到,MqttSubscribedPublishFlowTree,發現采集的mqtt同步響應模式下存在重復訂閱問題。
優化訂閱次數,完成1個模擬器,1個topic訂閱1次。
3.給pod增加容量限制3G,堆增加限制最大,最小2G
修改點:配置堆最大,最小為2G,給pod增加資源限制3G
修改后:觀察40Min,存在重啟pod現象,因為oom,觀察到頻繁gc且,gc后,內值在不斷變大。懷疑內存泄漏
用mat分析發現,MemoryDataStorage占用內存高。(這個是存放采集的實時數據核心類)
4.將檢測采集的實時數據,修改到redis
修改點:將hertzbeat實時數據采集nacos配置,從內存,改動到redis
修改后:觀察20min后,堆占用在220m到890m之間波動,

排查建議

建議將堆信息,比如作為提問內容,且帶上懷疑代碼,直接問ai這有什么可以優化的,或者是否有問題。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/921159.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/921159.shtml
英文地址,請注明出處:http://en.pswp.cn/news/921159.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于 CC-Link IE FB 轉 DeviceNet 技術的三菱 PLC 與發那科機器人在汽車涂裝線的精準噴涂聯動

案例背景在汽車制造行業&#xff0c;生產線的高效協同是提高生產效率和產品質量的關鍵。某汽車制造企業的車身焊接車間采用了基于 CC-Link IE FB 主站的三菱 Q 系列 PLC&#xff0c;憑借其強大的功能和穩定的性能&#xff0c;對焊接機器人等設備進行精準控制。而在涂裝車間&…

極空間打造 “超級中樞”,從書簽筆記到聊天分享,一鍵全搞定!

「NAS、鍵盤、路由器年輕就要多折騰&#xff0c;我是愛折騰的熊貓&#xff0c;今天又給大家分享最近折騰的內容了&#xff0c;關注是對我最大的支持&#xff0c;阿里嘎多」引言書簽項目熊貓介紹過不少啦&#xff0c;但今天要介紹的這個項目&#xff0c;大不一樣。平常的書簽&am…

Swift 解法詳解:LeetCode 368《最大整除子集》

文章目錄摘要描述題解答案題解代碼分析代碼拆解示例測試及結果時間復雜度空間復雜度總結摘要 有時候我們會遇到這樣的問題&#xff1a;給定一堆數&#xff0c;如何從中挑出一個子集&#xff0c;讓這個子集里的每一對數都能互相整除&#xff1f;題目要求我們找出最大的這樣一個…

python數據分析 與spark、hive數據分析對比

Python 數據分析與 Spark、Hive 數據分析在應用場景、數據處理能力、編程模型等方面存在差異&#xff0c;以下是詳細對比&#xff1a;?數據處理規模?Python 數據分析&#xff1a;?特點&#xff1a;Python 數據分析常用庫如Pandas&#xff0c;在單機環境下對中小規模數據集&a…

專題:2025全球新能源汽車供應鏈核心領域研究報告|附300+份報告PDF、數據儀表盤匯總下載

原文鏈接&#xff1a;https://tecdat.cn/?p43781 原文出處&#xff1a;拓端抖音號拓端tecdat 2024年&#xff0c;全球汽車產業站在了“舊秩序打破、新格局建立”的十字路口——一邊是傳統供應鏈受宏觀經濟波動、地緣博弈沖擊&#xff0c;全球零部件企業營收首次出現負增長&…

從數據孤島到智能中樞:RAG與智能體協同架構如何重塑企業知識庫

1. 前言企業知識管理正面臨前所未有的挑戰。分散在各個系統中的文檔、報告、郵件和數據庫形成了數據孤島&#xff0c;而大語言模型在缺乏準確知識支撐時容易產生幻覺回答。這種矛盾催生了檢索增強生成&#xff08;RAG&#xff09;技術的快速發展。RAG不僅僅是技術組合&#xff…

UBUNTU之Onvif開源服務器onvif_srvd:2、測試

運行 # eth0: 網卡 # 192.168.0.229: IPsudo ./onvif_srvd \--ifs eth0 \--scope onvif://www.onvif.org/name/TestDev \--scope onvif://www.onvif.org/Profile/S \--name RTSP \--width 800 --height 600 \--url rtsp://192.168.0.229:554/unicast \--type JPEG 測試 使用…

項目中常用的git命令

Git介紹Git是一個分布式版本控制系統&#xff0c;主要作用就是記錄代碼的歷史變化&#xff0c;讓開發者可以查看任意時間點的代碼&#xff0c;回滾到某個歷史版本&#xff0c;對比不同版本之間的差異。在企業開發中&#xff0c;通過是通過多人協作開發&#xff0c;具體分支可以…

C 語言標準輸入輸出庫:`stdio.h` 的使用詳解

1. 概述 在 C 語言中&#xff0c;stdio.h&#xff08;Standard Input Output Header&#xff09;是一個標準庫頭文件&#xff0c;主要用于提供輸入與輸出功能。幾乎所有的 C 程序都會用到它&#xff0c;因為它定義了用于讀取、寫入、格式化、文件操作等常用函數。 要在程序中使…

flume擴展實戰:自定義攔截器、Source 與 Sink 全指南

flume擴展實戰&#xff1a;自定義攔截器、Source 與 Sink 全指南 Flume 內置的組件雖然能滿足大部分場景&#xff0c;但在復雜業務需求下&#xff08;如特殊格式數據采集、定制化數據清洗&#xff09;&#xff0c;需要通過自定義組件擴展其功能。本文將詳細講解如何自定義 Flu…

【數學建模】數學建模應掌握的十類算法

【數學建模】數學建模應掌握的十類算法前言數學建模競賽官網1. 全國大學生數學建模競賽官網2. 美國大學生數學建模競賽官網3. Matlab 網站4. 研究生數學建模競賽官網數學建模應掌握的十類算法1. 蒙特卡羅方法(Monte-Carlo方法, MC)2. 數據擬合、參數估計、插值等數據處理算法3.…

物聯網開發學習總結(1)—— IOT 設備 OTA 升級方案

在物聯網設備數量呈指數級增長的今天&#xff0c;如何高效、可靠地實現設備固件升級&#xff08;OTA&#xff09;成為了每個物聯網開發者必須面對的重要課題。傳統的HTTP升級方案雖然簡單易用&#xff0c;但隨著設備規模的擴大&#xff0c;其局限性日益明顯。 一、HTTP OTA升級…

正運動控制卡學習-網絡連接

一.硬件介紹使用正運動控制卡ECI1408進行學習&#xff0c;使用正運動函數庫進行設置&#xff0c;并參考網絡視頻等進行學習記錄&#xff0c;侵權刪除.二.使用C#創建連接界面三.創建運動卡類3.1.創建IP連接字段private string IP; //連接IP public Inptr IPHandle&#xff1b;//…

存算一體:重構AI計算的革命性技術(1)

存算一體&#xff1a;重構AI計算的革命性技術 一、從存儲墻到存算一體&#xff1a;計算架構的百年變革 1.1 馮諾依曼架構的困境與突破 在計算機發展的歷史長河中&#xff0c;存儲與計算的分離一直是制約性能提升的關鍵瓶頸。1945年&#xff0c;計算機科學家馮諾依曼提出了現代計…

Linux之centos 系統常用命令詳解(附實戰案例)

CentOS 系統常用命令詳解&#xff08;附實戰案例&#xff09; 前言 本文針對 CentOS 7/8 系統&#xff0c;整理了運維工作中高頻使用的命令&#xff0c;涵蓋系統信息、文件操作、用戶權限、軟件管理、服務控制、網絡配置等核心場景&#xff0c;并結合實戰案例說明具體用法&…

生成知識圖譜與技能樹的工具指南:PlantUML、Mermaid 和 D3.js

摘要本文詳細介紹了生成知識圖譜、技能樹和桑基圖的工具&#xff0c;包括 PlantUML、Mermaid 和 D3.js&#xff0c;以及它們的概念、原理和使用方法。文檔為前端開發提供了示例知識圖譜、技能樹和桑基圖&#xff0c;并為新手提供了在線編輯器和 VS Code 的操作步驟&#xff0c;…

如何正確使用ChatGPT做數學建模比賽——數學建模AI使用技巧

文章轉自川川菜鳥&#xff1a;如何正確使用ChatGPT做數學建模比賽 引言 數學建模競賽是將數學理論應用于解決現實世界問題的一項重要賽事。在這類比賽中&#xff0c;學生團隊通常需要在有限時間內完成從問題分析、模型構建、算法實現到結果分析和論文撰寫的一整套流程。這對參…

存算一體:重構AI計算的革命性技術(3)

四、存算一體技術的未來發展趨勢與前景 4.1 技術發展&#xff1a;從“單點突破”到“多維度融合” 4.1.1 新型存儲介質&#xff1a;憶阻器成核心方向 未來5-10年&#xff0c;憶阻器&#xff08;RRAM&#xff09;將成為存算一體芯片的主流存儲介質&#xff0c;關鍵突破集中在三方…

LangChain開源LLM集成:從本地部署到自定義生成的低成本落地方案

LangChain開源LLM集成&#xff1a;從本地部署到自定義生成的低成本落地方案 目錄 核心定義與價值底層實現邏輯代碼實踐設計考量替代方案與優化空間 1. 核心定義與價值 1.1 本質定位&#xff1a;開源LLM適配機制的橋梁作用 LangChain的開源LLM適配機制本質上是一個標準化接口…

記錄一下node后端寫下載https的文件報錯,而瀏覽器卻可以下載。

用node 寫的下載&#xff0c;直接報錯error downloading or exxtraction file: unable to verify the first certificate 根據此信息也是排查了老半天了。瀏覽器卻可下載。問了ai之后才發現&#xff0c;證書如果不完整&#xff0c;瀏覽器會自動補全證書。 先用此網站SSL Serv…