自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

線程剖析 - 助力定位代碼層面高耗時(shí)問(wèn)題

開(kāi)發(fā) 前端
線程剖析的自身監(jiān)控指標(biāo),這些指標(biāo)有助于更好地了解剖析功能的性能和繁忙程度,以便進(jìn)行決策和調(diào)優(yōu)。線程剖析不僅提供了性能數(shù)據(jù),還可以與 OpenTelemetry 相結(jié)合,實(shí)現(xiàn)鏈路特征的關(guān)聯(lián),從而更全面地理解性能問(wèn)題。

在當(dāng)今的軟件開(kāi)發(fā)領(lǐng)域,性能問(wèn)題是一個(gè)永不過(guò)時(shí)的挑戰(zhàn)。為了解決這一挑戰(zhàn),開(kāi)發(fā)人員需要深入了解他們的應(yīng)用程序運(yùn)行時(shí)的性能,并快速定位高耗時(shí)問(wèn)題。線程剖析是一種強(qiáng)大的工具,通過(guò)采集和計(jì)算運(yùn)行時(shí)線程棧,可以幫助開(kāi)發(fā)人員更好地理解和解決性能問(wèn)題。本文將深入探討線程剖析的基本思想和實(shí)現(xiàn)思路,以及客戶端和服務(wù)端的設(shè)計(jì)。

一、基本思想

線程剖析的核心思想是在業(yè)務(wù)線程執(zhí)行請(qǐng)求時(shí)創(chuàng)建一個(gè)特定閾值觸發(fā)的檢測(cè)任務(wù),用于監(jiān)測(cè)高耗時(shí)問(wèn)題。如果任務(wù)未被取消,在達(dá)到高耗時(shí)閾值時(shí),將有專門的線程去執(zhí)行剖析任務(wù),采集業(yè)務(wù)線程的堆棧,并異步發(fā)送給剖析服務(wù)端進(jìn)行計(jì)算,以估算出棧上的各個(gè)方法耗時(shí)。這個(gè)工具不僅提供了詳細(xì)的性能數(shù)據(jù),還能與開(kāi)放遙測(cè)(OpenTelemetry)結(jié)合,從而實(shí)現(xiàn)鏈路特征的關(guān)聯(lián),主要流程如下:

圖片圖片

二、實(shí)現(xiàn)思路

客戶端設(shè)計(jì)

客戶端的架構(gòu)主要體現(xiàn)在任務(wù)的創(chuàng)建、調(diào)度、執(zhí)行和導(dǎo)出四個(gè)環(huán)節(jié)。

創(chuàng)建&調(diào)度任務(wù)

業(yè)務(wù)線程執(zhí)行時(shí),若滿足指定要監(jiān)控的接口或線程名稱,將構(gòu)造一個(gè)包含該線程對(duì)象的檢測(cè)任務(wù)放入隊(duì)列,時(shí)間輪的工作線程會(huì)周期性(默認(rèn)100ms)在輪盤上移動(dòng)一格,類似我們平時(shí)看到的鐘表上的指針那樣,每個(gè)周期會(huì)從任務(wù)隊(duì)列取出所有任務(wù),將各個(gè)任務(wù)分配添加到時(shí)間輪中每個(gè)格子中。如下圖所示:

圖片圖片

執(zhí)行任務(wù)

分配完成后,由任務(wù)執(zhí)行線程池的線程去執(zhí)行當(dāng)前周期所屬格子的所有任務(wù)。在執(zhí)行前,業(yè)務(wù)線程可能優(yōu)先結(jié)束而取消該任務(wù)的執(zhí)行,例如在達(dá)到耗時(shí)閾值后,剖析任務(wù)已經(jīng)或準(zhǔn)備開(kāi)始執(zhí)行,但主線程取消了剖析任務(wù)這樣一個(gè)臨界點(diǎn),此時(shí)可通過(guò)各語(yǔ)言的同步機(jī)制來(lái)及時(shí)取消剖析任務(wù)。

任務(wù)執(zhí)行時(shí),剖析線程將周期性采集線程的堆棧,而為了方便后續(xù)的分析工作,也會(huì)同時(shí)記錄當(dāng)前堆棧產(chǎn)生的時(shí)間戳,直到業(yè)務(wù)線程發(fā)出中斷通知,或采集樣本數(shù)達(dá)到上限,或任務(wù)狀態(tài)發(fā)生改變,然后中斷剖析線程的執(zhí)行。

執(zhí)行完成后,將采集到的線程棧集 push 到診斷數(shù)據(jù)隊(duì)列,等待數(shù)據(jù)導(dǎo)出線程消費(fèi)此隊(duì)列,并發(fā)送到服務(wù)端。這里需要注意,線程棧數(shù)據(jù)文本量一般不會(huì)太小,比如我們一個(gè)專門用于測(cè)試的應(yīng)用,500ms 觸發(fā)的閾值下的 HTTP 接口,每次請(qǐng)求讓線程隨機(jī) Sleep 5s 以內(nèi),當(dāng)接口耗時(shí)超過(guò) 3s,單次剖析產(chǎn)生的棧文本大小在 200KB 以上,因此這里需要有個(gè)參數(shù),來(lái)控制隊(duì)列默認(rèn)長(zhǎng)度,避免過(guò)多的堆棧快照擠兌內(nèi)存。

整個(gè)任務(wù)執(zhí)行流程如下圖所示:

圖片圖片

數(shù)據(jù)預(yù)聚合&導(dǎo)出

預(yù)聚合工作將由獨(dú)立的工作線程消費(fèi)診斷數(shù)據(jù)隊(duì)列后來(lái)做,即將多個(gè)線程快照合并為一個(gè),降低網(wǎng)絡(luò) IO 開(kāi)銷。具體就是對(duì)于快照集中每個(gè)快照的棧幀,按照它的開(kāi)始時(shí)間取快照集中相同棧幀的最小值,結(jié)束時(shí)間取快照集中相同棧幀的最大值這個(gè)規(guī)則進(jìn)行聚合,流程如下圖所示:

圖片圖片

而數(shù)據(jù)發(fā)送層就比較簡(jiǎn)單了,采用高性能無(wú)鎖隊(duì)列 Mpsc, 使用 gRPC 協(xié)議發(fā)送到診斷服務(wù)端:

圖片圖片

當(dāng)然,為了降低業(yè)務(wù)系統(tǒng)的壓力,也可以將原始數(shù)據(jù)直接落盤,由外部獨(dú)立的采集器逐行采集然后發(fā)送到消息隊(duì)列。

服務(wù)端設(shè)計(jì)

圖片圖片

服務(wù)端的架構(gòu)主要考慮三個(gè)點(diǎn):

數(shù)據(jù)接收

同 Otel 對(duì) Trace 數(shù)據(jù)的處理思路類似,診斷數(shù)據(jù)發(fā)送請(qǐng)求需要快速地被響應(yīng),來(lái)減少客戶端因請(qǐng)求延遲導(dǎo)致發(fā)送隊(duì)列數(shù)據(jù)被丟棄的可能。因此,診斷服務(wù)端采用吞吐性能較好的 go 語(yǔ)言編寫,而請(qǐng)求涉及到跨語(yǔ)言調(diào)用,協(xié)議層上,綜合高效快速可靠因素,選用較成熟的 gRPC 協(xié)議進(jìn)行通信。

數(shù)據(jù)接收并成功解析后,需異步將數(shù)據(jù)放入隊(duì)列,這里我們選用采用了多副本機(jī)制的 Kafka 消息中間件,來(lái)滿足診斷服務(wù)各模塊之間的解耦,同時(shí)也保證診斷數(shù)據(jù)不丟失 。

數(shù)據(jù)解析&加工

診斷剖析數(shù)據(jù)消費(fèi)組會(huì)去消費(fèi)隊(duì)列中的數(shù)據(jù),將數(shù)據(jù)進(jìn)行進(jìn)一步解析,并且持久化處理,其中包括:

  • a) 父子棧幀推導(dǎo)

客戶端的預(yù)聚合會(huì)將多個(gè)快照合并為一個(gè),因此快照內(nèi)的每個(gè)棧幀將擁有不同的起始和結(jié)束時(shí)間。由于 Java 的原始線程堆棧是無(wú)層級(jí)的結(jié)構(gòu),為了提高數(shù)據(jù)的可讀性,進(jìn)一步降低高耗時(shí)問(wèn)題定位發(fā)現(xiàn)的成本,因此需將已合并的堆棧進(jìn)一步推導(dǎo)為包含父子棧幀的結(jié)構(gòu)化信息,即從棧頂?shù)牡诙€(gè)棧幀開(kāi)始遍歷調(diào)用棧,若當(dāng)前棧幀的快照開(kāi)始和結(jié)束的時(shí)間范圍位于上個(gè)棧幀的左開(kāi)右閉或左閉右開(kāi)區(qū)間,則將當(dāng)前棧幀設(shè)置為上個(gè)棧幀的子棧:

圖片圖片

注意:

1. 一個(gè) Java 線程的大部分調(diào)用棧形式本身就是個(gè)從 "Thread.run" 開(kāi)始的嵌套,而每次快照時(shí)也無(wú)從得知層級(jí)信息,因此不考慮推導(dǎo)快照開(kāi)始和結(jié)束時(shí)間完全一致的棧幀,將這些棧幀置為同級(jí)即可。

2. 使用線程的快照時(shí)間來(lái)推導(dǎo)還原父子棧和耗時(shí)仍然是個(gè)相對(duì)比較粗略的統(tǒng)計(jì)行為,其精度受到當(dāng)前線程調(diào)用棧快照導(dǎo)出的耗時(shí),以及每次快照的間隔耗時(shí)的影響,因此父子層級(jí)結(jié)果僅供參考,并不絕對(duì)等于實(shí)際調(diào)用的關(guān)系結(jié)果。

  • b) 自身耗時(shí)計(jì)算

當(dāng)已推導(dǎo)出父子棧幀關(guān)系后,可對(duì)結(jié)果集進(jìn)行遍歷,計(jì)算自身耗時(shí),計(jì)算規(guī)則如下:

  • 從第二個(gè)棧幀開(kāi)始,如果與上一個(gè)棧幀的快照開(kāi)始和結(jié)束時(shí)間一致,則上個(gè)棧幀的自身耗時(shí)設(shè)為 0,否則會(huì)將當(dāng)前棧幀的父棧幀(若存在)的自身耗時(shí)減掉上個(gè)棧幀的自身耗時(shí)。
  • 如果當(dāng)前棧幀是最后一個(gè),則將當(dāng)前棧幀自身耗時(shí)設(shè)為快照開(kāi)始與結(jié)束的時(shí)間差,并且將當(dāng)前棧幀的父棧幀(若存在)的自身耗時(shí)減掉當(dāng)前棧幀的自身耗時(shí)。
  • 如果當(dāng)前棧幀有子棧幀,處理方式同上。

以上圖調(diào)用時(shí)序?yàn)槔?,根?jù)以上規(guī)則得出的自身耗時(shí)計(jì)算示意圖如下:

圖片圖片

  • c) 數(shù)據(jù)持久化

當(dāng)完成父子棧幀推導(dǎo)和自身耗時(shí)計(jì)算后,數(shù)據(jù)將持久化存儲(chǔ),例如將數(shù)據(jù)存儲(chǔ)到 ClickHouse,供數(shù)據(jù)查詢端使用。

數(shù)據(jù)查詢

診斷剖析數(shù)據(jù)將以 HTTP API 形式對(duì)外提供查詢服務(wù),例如可觀測(cè)性門戶系統(tǒng),可根據(jù)線程名,鏈路 Trace ID, Span ID 等特征進(jìn)行剖析數(shù)據(jù)的查詢。

[
    {
        "data": "YXQgc3VuLm5pby5jaC5Vd...",//線程剖析棧
        "thread_name": "XNIO-1 I/O-1",//線程名稱
        "thread_state": "RUNNABLE",//線程狀態(tài)
        "trigger_millisecond": 500,//觸發(fā)閾值
        "self_millisecond": 38,//自身耗時(shí)
        "source_snapshot_count": 153//快照數(shù)
    },
    {
        "data": "YXQgaW8udW5kZXJ0b3cuc2Vy...",
        "thread_name": "XNIO-1 task-1",
        "thread_state": "RUNNABLE",
        "trigger_millisecond": 500,
        "self_millisecond": 0,
        "source_snapshot_count": 140
    }
]

調(diào)用鏈關(guān)聯(lián)

線程剖析能結(jié)合 OpenTelemetry ,借助 OpenTelemetry Java Instrumentation 上下文的生命周期,從而關(guān)聯(lián) Trace ID 、接口名等鏈路特征。

圖片圖片

自身監(jiān)控指標(biāo)

線程剖析功能需要擁有較完善的自身監(jiān)控,以便觀測(cè)復(fù)雜剖析流程下對(duì)業(yè)務(wù)系統(tǒng)潛在的性能影響。這些監(jiān)控包括:

  • 任務(wù)檢測(cè)隊(duì)列大小

檢測(cè)隊(duì)列用于給時(shí)間輪提供任務(wù),該指標(biāo)的大小給線程剖析的采樣,接口名,線程名稱等條件提供了一定參考。

圖片圖片

  • 任務(wù)釋放平均耗時(shí)

剖析任務(wù)的釋放將會(huì)中斷正在執(zhí)行的剖析任務(wù),其中涉及到剖析、數(shù)據(jù)狀態(tài)機(jī)的改變,線程的中斷。多線程情況下,需保證操作的原子性,如果任務(wù)釋放的平均耗時(shí)變長(zhǎng),則能反映當(dāng)前業(yè)務(wù)系統(tǒng) CPU 線程上下文切換效率下降。

圖片圖片

  • 正在執(zhí)行剖析任務(wù)的個(gè)數(shù)

線程剖析是以線程為單位來(lái)執(zhí)行的,通過(guò)觀測(cè)正在進(jìn)行線程剖析的任務(wù)數(shù),可反映出剖析功能繁忙的程度,以及幫助我們決策是否需要對(duì)同時(shí)剖析的任務(wù)數(shù)進(jìn)行限制。

圖片圖片

  • 線程堆棧導(dǎo)出平均耗時(shí)

線程棧導(dǎo)出方法的平均耗時(shí),如果該操作耗時(shí)顯著升高,且調(diào)用棧未有明顯變化,則代表性能惡化。

圖片圖片

  • 數(shù)據(jù)隊(duì)列大小

指待發(fā)送到服務(wù)端的數(shù)據(jù)隊(duì)列大小。

  • 數(shù)據(jù)入隊(duì)速率

指待發(fā)送到服務(wù)端的數(shù)據(jù)入隊(duì)的速率。

  • 數(shù)據(jù)合并平均耗時(shí)

數(shù)據(jù)發(fā)送前進(jìn)行預(yù)聚合,將多個(gè)線程快照合并為一個(gè),這個(gè)過(guò)程的平均耗時(shí),該值可供剖析條件提供一定參考。

圖片圖片

  • 線程??煺諏?dǎo)出發(fā)送平均字節(jié)

線程快照發(fā)送的請(qǐng)求包平均大小。

圖片圖片

  • 數(shù)據(jù)導(dǎo)出速率

線程快照發(fā)送的速率。

圖片圖片

對(duì)以上指標(biāo)進(jìn)行監(jiān)控,也方便對(duì)相關(guān)參數(shù)進(jìn)行調(diào)優(yōu),從而更好地在診斷剖析功能的完整性與服務(wù)性能之間做相關(guān)取舍。

三、結(jié)語(yǔ)

線程剖析為解決性能問(wèn)題提供了有力支持。通過(guò)采集和分析線程棧信息,它能夠幫助開(kāi)發(fā)人員定位應(yīng)用程序中的高耗時(shí)問(wèn)題,為性能優(yōu)化提供關(guān)鍵信息。本文詳細(xì)介紹了線程剖析的基本思想和實(shí)現(xiàn)思路,以及客戶端和服務(wù)端的設(shè)計(jì)架構(gòu)。其核心思想是通過(guò)創(chuàng)建特定閾值觸發(fā)的檢測(cè)任務(wù),監(jiān)測(cè)高耗時(shí)問(wèn)題,并將采集到的數(shù)據(jù)異步發(fā)送到剖析服務(wù)端進(jìn)行進(jìn)一步計(jì)算和分析。

此外,線程剖析的自身監(jiān)控指標(biāo),這些指標(biāo)有助于更好地了解剖析功能的性能和繁忙程度,以便進(jìn)行決策和調(diào)優(yōu)。線程剖析不僅提供了性能數(shù)據(jù),還可以與 OpenTelemetry 相結(jié)合,實(shí)現(xiàn)鏈路特征的關(guān)聯(lián),從而更全面地理解性能問(wèn)題。

總的來(lái)說(shuō),線程剖析可以幫助開(kāi)發(fā)人員提高應(yīng)用程序的質(zhì)量和性能,快速定位性能問(wèn)題,以確保應(yīng)用程序的順暢運(yùn)行,同時(shí),也可以更有效地應(yīng)對(duì)性能挑戰(zhàn),提高應(yīng)用程序的可維護(hù)性和性能。

責(zé)任編輯:武曉燕 來(lái)源: 得物技術(shù)
相關(guān)推薦

2010-02-05 18:00:18

Android源代碼

2010-02-04 10:19:39

C++多線程

2021-04-15 09:07:52

hotspotJavaC++

2025-03-06 00:00:05

DPIHD開(kāi)發(fā)

2010-08-25 14:56:15

CSS相對(duì)定位

2011-07-21 11:12:58

iPhone 線程 多線程

2022-03-25 07:39:09

OSMySQL層面

2020-08-13 08:45:09

多線程死鎖

2023-01-11 07:54:09

GC搜索代碼

2010-11-04 10:05:48

2017-09-21 17:15:18

互聯(lián)網(wǎng)

2010-02-01 13:34:59

Python 腳本

2010-05-27 12:58:07

SVN升級(jí)

2024-12-12 09:24:28

RocksDB服務(wù)器

2015-07-08 10:37:12

MySQL高可用架構(gòu)業(yè)務(wù)架構(gòu)

2010-03-12 14:28:45

Python if語(yǔ)句

2010-01-26 17:53:30

Android代碼結(jié)構(gòu)

2019-04-15 15:22:47

CPU代碼Top

2022-07-24 14:30:16

數(shù)據(jù)治理5G網(wǎng)絡(luò)VoNR
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)