成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

線程池如何監控,才能幫助開發者快速定位線上錯誤?

開發 前端
不論線程池是否由 Spring 管理,采集的方式大致相同。一種從 Spring 容器取,一種是創建好線程池后放到一個自定義容器

大部分情況下,線程池的運行情況對于使用者來說是個黑盒

運行情況不可知,會導致 生產出現事故問題排查困難,以及線程池參數難以定義

文章圍繞線程池監控展開,討論 線程池如何監控、監控的指標以及監控數據的存儲展示

01如何監控運行數據

設想一下,如果想監控線程池的運行數據,你會怎么操作?這里提供兩種常規思路

線程池運行時埋點,每一次運行任務都進行統計

定時獲取線程池的運行數據

這里我推薦第二種,因為線程池的監控 API 會通過 獲取主鎖來控制結果的相對準確性,性能相對較差,后面會詳細說明

為什么叫相對準確?因為任務和線程的狀態在計算過程中可能會動態變化,只能給到一個近似值,保證不了絕對準確

模擬下定時采集線程池運行時數據的代碼

  1. private ScheduledThreadPoolExecutor collectVesselExecutor; 
  2.  
  3. String collectVesselTaskName = "client.scheduled.collect.data"
  4. collectVesselExecutor = new ScheduledThreadPoolExecutor( 
  5.         new Integer(1), 
  6.         ThreadFactoryBuilder.builder().daemon(true).prefix(collectVesselTaskName).build() 
  7. ); 
  8.  
  9. // 延遲 initialDelay 后循環調用. scheduleWithFixedDelay 每次執行時間為上一次任務結束時, 向后推一個時間間隔 
  10. collectVesselExecutor.scheduleWithFixedDelay( 
  11.         () -> runTimeGatherTask(), 
  12.         properties.getInitialDelay(), 
  13.         properties.getCollectInterval(), 
  14.         TimeUnit.MILLISECONDS 
  15. ); 

一般線程池分為兩種方式創建,Spring Bean 和非 Spring Bean,假設創建的線程池是 Spring 管理的

我們只需要在 Spring 容器啟動成功后,延遲一段時間后開始采集運行數據就 OK 了

不論線程池是否由 Spring 管理,采集的方式大致相同。一種從 Spring 容器取,一種是創建好線程池后放到一個自定義容器

02監控的指標有哪些?

說一下目前 Hippo4J 定義的線程池監控指標,包括不限于。大家有業務中使用到的監控指標都可以討論下

  • 線程池當前負載:當前線程數 / 最大線程數
  • 線程池峰值負載:當前線程數 / 最大線程數,線程池運行期間最大的負載
  • 核心線程數:線程池的核心線程數
  • 最大線程數:線程池限制同時存在的線程數
  • 當前線程數:當前線程池的線程數
  • 活躍線程數:執行任務的線程的大致數目
  • 最大出現線程數:線程池中運行以來同時存在的最大線程數
  • 阻塞隊列:線程池暫存任務的容器
  • 隊列容量:隊列中允許元素的最大數量
  • 隊列元素:隊列中已存放的元素數量
  • 隊列剩余容量:隊列中還可以存放的元素數量
  • 線程池任務完成總量:已完成執行的任務的大致總數
  • 拒絕策略執行次數:運行時拋出的拒絕次數總數

這些指標可以幫助我們解決大多數因為線程池而導致的問題排查。但是,事情往往不能盡善盡美

當前線程數、活躍線程數、最大出現線程數、線程池任務完成總量 的線程池 API 會先獲取到 mainLock,然后才開始計算

mainLock 是線程池的主鎖,線程執行、線程銷毀和線程池停止等都會使用到這把鎖

  1. final ReentrantLock mainLock = this.mainLock; 
  2. mainLock.lock(); 
  3. try { 
  4.     xxxxx 
  5. } finally { 
  6.     mainLock.unlock(); 

如果頻繁獲取這把鎖,會導致原有線程池任務執行性能受到影響

所以,我們應該避免頻繁獲取這幾項參數,這也是不使用線程池任務執行埋點最重要的原因

03監控數據存儲

上面的線程池監控指標如果只能支持實時查看,并不能幫忙開發日常排查錯誤

大部分場景下,生產上的問題發現會有延遲。比如 12:30 出現的問題,業務13:00 進行的反饋

為了更好幫助開發排錯,我們需要將線程池的歷史運行數據進行存儲

說到線程池歷史運行數據的存儲,使用 時序數據庫(TSDB) 是最合適的

但大部分情況下,公司不會為了這一個需求搭建或者采購時序數據庫,那就可以使用折中方案,比如說 MySQL、ES 等

我們以 MySQL 為例,his_run_data 歷史運行數據表,建表語句如下:

  1. CREATE TABLE `his_run_data` ( 
  2.   `thread_pool_id` varchar(56) DEFAULT NULL COMMENT '線程池ID'
  3.   `instance_id` varchar(256) DEFAULT NULL COMMENT '實例ID'
  4.   `current_load` bigint(20) DEFAULT NULL COMMENT '當前負載'
  5.   `peak_load` bigint(20) DEFAULT NULL COMMENT '峰值負載'
  6.   `pool_size` bigint(20) DEFAULT NULL COMMENT '線程數'
  7.   `active_size` bigint(20) DEFAULT NULL COMMENT '活躍線程數'
  8.   `queue_capacity` bigint(20) DEFAULT NULL COMMENT '隊列容量'
  9.   `queue_size` bigint(20) DEFAULT NULL COMMENT '隊列元素'
  10.   `queue_remaining_capacity` bigint(20) DEFAULT NULL COMMENT '隊列剩余容量'
  11.   `completed_task_count` bigint(20) DEFAULT NULL COMMENT '已完成任務計數'
  12.   `reject_count` bigint(20) DEFAULT NULL COMMENT '拒絕次數'
  13.   `timestampbigint(20) DEFAULT NULL COMMENT '時間戳'
  14.   `gmt_create` datetime DEFAULT NULL COMMENT '創建時間'
  15.   `gmt_modified` datetime DEFAULT NULL COMMENT '修改時間'
  16.   PRIMARY KEY (`id`), 
  17.   KEY `idx_group_key` (`tp_id`,`instance_id`) USING BTREE, 
  18.   KEY `idx_timestamp` (`timestamp`) USING BTREE 
  19. ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='歷史運行數據表'

可以看到,建表語句中有三個關鍵字段:

thread_pool_id:表示當前數據的線程池標識

instance_id:應用可能集群部署,標識集群下唯一的線程池

timestamp:記錄線程池運行數據產生時的時間戳

有一個問題,線上的線程池是源源不斷產生運行數據的,遲早不得把表的數據量推到上億?

因為數據是有時效性的,過了一定時間之后,就沒有必要再占用實時的資源

針對上述問題提供兩種解決方案:

  • 假設數據存儲 1 天,如果超出這個時間,直接刪除即可
  • 同上所述,過期數據可以保留到備份表中,并刪除 his_run_data 數據

可能有的小伙伴還會擔心,數據量太大會不會導致查詢時過慢?

我們可以算一下,假設有 100 個應用,每個應用部署 10 個節點

假設數據有效期為 1 小時,那么可以產出的數據是 72 萬,一天也就是 1728 萬

對于 MySQL 而言,幾千萬數據量以下針對索引的查詢,都不會產生性能瓶頸

04如何定義公共監控?

抽象線程池存儲

上面說到,線程池的采集歷史運行數據在各個應用系統中,數據的存儲、定期刪除是否可以抽象出來,避免重復的工作

如果選擇抽象數據存儲,客戶端節點與服務端之間的交互如下:

  • 客戶端定時采集線程池歷史運行數據,將數據打包好發送服務端
  • 服務端接收客戶端上報的數據,進行數據入庫持久化存儲
  • 服務端定期刪除或存檔客戶端線程池歷史運行數據
  • 由服務端統一對外提供線程池運行圖表的數據展示

這里有個小問題,客戶端如何打包發送給服務端?定時采集數據后直接上報是不是可行呢

不推薦采集、上報兩種行為放到一個流程中,好的設計應該是要 分離開職責;而且,如果在上報過程中網絡出現阻塞等等問題,會耽誤采集線程的下一次采集結果

我們可以使用多線程生產、消費模型來做,相信大家初學多線程一定都學過這個設計

  1. // 緩沖隊列 
  2. private BlockingQueue<Message> messageCollectVessel  = new ArrayBlockingQueue(bufferSize); 
  3.  
  4. // 生產者 
  5. Message message = collector.collectMessage(); 
  6. boolean offer = messageCollectVessel.offer(message); 
  7. if (!offer) { 
  8.     log.warn("Buffer data starts stacking data..."); 
  9.  
  10. // 消費者 
  11. while (true) { 
  12.     try { 
  13.         Message message = messageCollectVessel.take(); 
  14.         messageSender.send(message); 
  15.     } catch (Throwable ex) { 
  16.         log.error("Consumption buffer container task failed. Number of buffer container tasks :: {}", messageCollectVessel.size(), ex); 
  17.     } 

創建阻塞緩沖隊列,由定時線程池采集歷史運行數據,并放到緩沖隊列中;然后起一個線程,循環消費即可

極端情況下緩沖隊列元素會出現堆積,最新采集的線程池數據也就無法插入成功,為了不影響客戶端的運行,僅做異常警告處理

使用最新抽象出來的客戶端、服務端交互流程,有以下幾個優點

  • 數據的存儲和查詢展示由服務端提供功能,減輕客戶端壓力和重復工作量
  • 歷史運行數據的刪除或備份操作由服務端統一執行
  • 不同的項目不需要為線程池歷史運行數據分別創建表結構存儲
  • 形成交互規范,避免業務發散單獨開發,中心化的設計更利于技術的迭代和管理

監控圖表展示

不同公司對于線程池的監控不盡相同,出于各種考慮,會將監控封裝成最符合自己業務場景的流程

Hippo4J 從最基本的指標出發,封裝出了最小代價的監控體系,并提供可視化頁面的圖標展示

有興趣可以查看 Hippo4J 框架官網介紹

Site:https://www.hippox.cn

還有一個功能點,考慮到很多公司搭建了一套監控體系,其中以 Prometheus + Grafana 為主

后續 Hippo4J 會接入 Prometheus,應用內部存儲線程池的運行數據,適配 Prometheus 采集存儲,最終展示到 Grafana

05總結回顧

線程池作為企業級應用廣泛的技術,對它的監控是不可或缺的穩定性保障之一

文章從線程池的監控出發,講解了如何監控、監控的指標以及監控數據的存儲,相信讀者們也各有收獲

 

責任編輯:武曉燕 來源: 龍臺的技術筆記
相關推薦

2013-09-29 10:04:09

Arrownock開發者社交

2015-07-22 16:08:46

OpenStack開源貢獻代碼

2012-05-21 22:04:02

Android

2014-04-08 09:58:26

PythonPython教程

2012-08-22 09:39:28

開發者

2024-12-12 09:00:33

2013-07-15 14:08:10

開發者技能

2014-12-24 10:00:07

Spring

2021-02-01 15:59:41

Angular開發者代碼

2011-06-22 10:35:02

FirefoxWeb

2013-12-27 09:03:47

開發項目

2020-10-09 09:44:25

JavaScript 開發 應用

2024-07-22 08:00:00

2019-12-20 09:12:37

內存工程師網絡

2021-12-25 22:31:55

Sentry 監控SDK 開發 性能監控

2022-08-15 11:29:44

騰訊云云端開發工具Web IDE

2015-03-27 11:26:58

移動開ISVSI

2019-06-27 10:15:46

架構代碼項目

2022-07-05 08:25:10

Reactyarn link

2012-09-05 14:45:45

Windows 8
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品久久7777777 | 超碰在线人 | 精品国产一区二区三区久久狼黑人 | 国产伦精品一区二区三区视频金莲 | 亚洲成人精品免费 | 欧美一级毛片免费观看 | 狠狠操狠狠干 | 97精品久久| 三级黄片毛片 | 操操日 | 日本精品网站 | 国产精品视频在线观看 | 亚洲色图网址 | 久久久久久久久久爱 | 日韩欧美中文字幕在线观看 | 精品久久不卡 | 午夜成人免费视频 | 欧美日韩国产一区二区三区不卡 | 久久成人国产精品 | 成人h动漫精品一区二区器材 | 日韩精品在线一区 | 国产成人精品亚洲日本在线观看 | 欧美精三区欧美精三区 | 99色综合 | 国产你懂的在线观看 | 在线看成人av | 最近中文字幕第一页 | 国产欧美在线一区二区 | 91精品午夜窝窝看片 | 伊人久操| 九九热精品视频在线观看 | 国产精品国产a | 国产一区二区三区四区三区四 | 高清久久久 | 中国黄色在线视频 | 天天操夜夜操 | 精品婷婷| 一级黄色片一级黄色片 | 精品久久久久久 | 国产成人99久久亚洲综合精品 | 久久国产一区二区三区 |