最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

深度解析微服務(wù)高并發(fā)資源指標(biāo)數(shù)據(jù)統(tǒng)計(jì):資源指標(biāo)數(shù)據(jù)統(tǒng)計(jì)全解析

2023-03-21 14:55 作者:兩年半的java練習(xí)生  | 我要投稿

資源指標(biāo)數(shù)據(jù)統(tǒng)計(jì)全解析

本節(jié)將結(jié)合前面所學(xué)的內(nèi)容,以及基于滑動(dòng)窗口實(shí)現(xiàn)資源指標(biāo)數(shù)據(jù)統(tǒng)計(jì),分析Sentinel是如何實(shí)現(xiàn)資源指標(biāo)數(shù)據(jù)統(tǒng)計(jì)的。

節(jié)點(diǎn)選擇器插槽

節(jié)點(diǎn)選擇器插槽(NodeSelectorSlot)負(fù)責(zé)為資源的首次訪問創(chuàng)建DefaultNode實(shí)例,以及修改Context實(shí)例的curNode字段指向當(dāng)前資源的DefaultNode實(shí)例,將DefaultNode實(shí)例綁定到調(diào)用樹上。因?yàn)楹罄m(xù)的ProcessorSlot在邏輯上都需要依賴這個(gè)ProcessorSlot,所以它被放在ProcessorSlot鏈表的第一個(gè)位置。NodeSelectorSlot的源碼如下。


如源碼所示,map字段是一個(gè)非靜態(tài)字段,意味著每個(gè)NodeSelectorSlot實(shí)例都有一個(gè)Map實(shí)例。而Sentinel只會(huì)為一個(gè)資源創(chuàng)建一個(gè)ProcessorSlotChain,一個(gè)ProcessorSlotChain又只會(huì)創(chuàng)建一個(gè)NodeSelectorSlot,并且map字段緩存DefaultNode使用的key并非資源ID,而是調(diào)用鏈入口名稱。所以,map字段的作用是緩存同一資源、不同調(diào)用鏈入口創(chuàng)建的DefaultNode實(shí)例。

Sentinel會(huì)為同一資源創(chuàng)建多少個(gè)DefaultNode實(shí)例取決于有多少個(gè)入口節(jié)點(diǎn)不同的調(diào)用鏈包含這個(gè)資源,這就是為什么說一個(gè)資源可能有多個(gè)DefaultNode實(shí)例的原因。

為什么這么設(shè)計(jì)呢?舉個(gè)例子,對(duì)于同一支付接口,我們既可以使用Spring MVC暴露給前端訪問,也可以使用Dubbo暴露給其他內(nèi)部服務(wù)調(diào)用。由于入口節(jié)點(diǎn)不同,支付接口會(huì)被兩條調(diào)用鏈包含。針對(duì)這種情況,我們可以通過設(shè)置來限制從Spring MVC進(jìn)來的流量,也就是對(duì)前端請(qǐng)求限流。

NodeSelectorSlot類的entry方法最難理解的就是,將當(dāng)前資源的DefaultNode實(shí)例綁定到調(diào)用樹的如下代碼:


這行代碼可以分為兩種情況來分析,接下來以Sentinel提供的demo為例進(jìn)行分析。

1. 一般情況

Sentinel的sentinel-demo模塊提供了多種使用場(chǎng)景的demo,我們以sentinel-demo-springwebmvc這個(gè)demo為例進(jìn)行講解。該demo下有一個(gè)hello接口,其代碼如下。


提示:這里不需要添加任何規(guī)則,只是為了調(diào)試Sentinel的源碼。

在啟動(dòng)demo后,使用瀏覽器訪問hello接口,在NodeSelectorSlot類的entry方法的綁定調(diào)用樹這一行代碼下斷點(diǎn),觀察此時(shí)Context實(shí)例的字段信息。在正常情況下,我們可以看到如圖4.4所示的結(jié)果。

圖4.4 綁定調(diào)用樹1

從圖4.4中可以看出,此時(shí)調(diào)用鏈入口節(jié)點(diǎn)(entranceNode)的子節(jié)點(diǎn)(childList)為空,并且當(dāng)前CtEntry實(shí)例(curEntry)的父(parent)、子(child)節(jié)點(diǎn)都是Null。當(dāng)綁定調(diào)用樹這一行代碼執(zhí)行完成后,Context實(shí)例的字段信息如圖4.5所示。

圖4.5 綁定調(diào)用樹2

從圖4.5中可以看出,NodeSelectorSlot為當(dāng)前資源創(chuàng)建的DefaultNode實(shí)例被添加到了調(diào)用鏈入口節(jié)點(diǎn)(entranceNode)的子節(jié)點(diǎn)(childList)中。

此時(shí),ROOT節(jié)點(diǎn)、調(diào)用鏈入口節(jié)點(diǎn)及當(dāng)前資源的DefaultNode節(jié)點(diǎn)構(gòu)造成的調(diào)用樹如下。

如果現(xiàn)在訪問demo的其他接口,如訪問err接口,則將會(huì)生成如下所示的調(diào)用樹。


提示:名稱為

sentinel_spring_web_context的調(diào)用鏈入口節(jié)點(diǎn)將會(huì)存儲(chǔ)Web項(xiàng)目中所有資源的DefaultNode節(jié)點(diǎn)。

2. 存在多次調(diào)用SphU#entry方法的情況

如果在一個(gè)服務(wù)中既添加了Sentinel的WebMvc適配模塊的依賴,也添加了Sentinel的OpenFeign適配模塊的依賴,并且使用了OpenFeign調(diào)用內(nèi)部其他服務(wù)的接口,就會(huì)存在一次調(diào)用鏈路上出現(xiàn)多次調(diào)用SphU#entry方法的情況。

WebMvc適配器在接收客戶端請(qǐng)求時(shí)會(huì)調(diào)用一次SphU#entry方法,在處理客戶端請(qǐng)求時(shí)可能需要使用OpenFeign調(diào)用內(nèi)部其他服務(wù)的接口,那么在發(fā)起接口調(diào)用時(shí),Sentinel的OpenFeign適配器也會(huì)調(diào)用一次SphU#entry方法。

現(xiàn)在將demo的hello接口修改一下,將hello接口調(diào)用的doBusiness方法也作為資源,并使用Sentinel保護(hù)起來,改造后的hello接口代碼如下。


我們可以將doBusiness方法看作遠(yuǎn)程調(diào)用。例如,使用POST方式調(diào)用第三方的接口,接口名稱為hello2,那么我們可以使用POST:/hello2作為資源名稱,并將流量類型設(shè)置為OUT類型,將上下文名稱設(shè)置為my_context。

在啟動(dòng)demo后,使用瀏覽器訪問hello接口。當(dāng)代碼執(zhí)行到apiHello方法時(shí),在NodeSelectorSlot#entry方法的綁定調(diào)用樹這一行代碼下斷點(diǎn),當(dāng)綁定調(diào)用樹這一行代碼執(zhí)行完成后,Context實(shí)例的字段信息如圖4.6所示。

從圖4.6中可以看出,Sentinel并沒有創(chuàng)建名稱為my_context的Context實(shí)例,因?yàn)楫?dāng)前調(diào)用鏈上已經(jīng)存在Context實(shí)例,Sentinel只是在調(diào)用鏈入口處創(chuàng)建了Context實(shí)例。

圖4.6 綁定調(diào)用樹3

在執(zhí)行NodeSelectorSlot#entry方法之前,由于還沒有為名稱為POST:/hello2的資源創(chuàng)建ProcessorSlotChain,因此SphU#entry方法會(huì)為該資源創(chuàng)建一個(gè)ProcessorSlotChain,并為該P(yáng)rocessorSlotChain創(chuàng)建一個(gè)NodeSelectorSlot。當(dāng)執(zhí)行到NodeSelectorSlot#entry方法時(shí),該方法就會(huì)為該資源創(chuàng)建一個(gè)DefaultNode實(shí)例,而將該資源的DefaultNode實(shí)例綁定到節(jié)點(diǎn)樹后,該資源的DefaultNode實(shí)例就會(huì)成為GET:/hello資源的DefaultNode實(shí)例的子節(jié)點(diǎn),此時(shí)調(diào)用樹如下。


此時(shí),當(dāng)前調(diào)用鏈路上已經(jīng)存在兩個(gè)CtEntry實(shí)例,這兩個(gè)CtEntry實(shí)例構(gòu)造了一個(gè)雙向鏈表,如圖4.7所示。

圖4.7 CtEntry構(gòu)造的雙向鏈表

雖然存在兩個(gè)CtEntry實(shí)例,但此時(shí)Context實(shí)例的curEntry字段指向的是第二個(gè)CtEntry實(shí)例,第二個(gè)CtEntry實(shí)例是在apiHello方法調(diào)用SphU#entry方法時(shí)創(chuàng)建的。在執(zhí)行完doBusiness方法后,需要調(diào)用當(dāng)前CtEntry#exit方法,由該CtEntry將Context實(shí)例的curEntry字段還原為指向該CtEntry的父CtEntry。

接下來分析NodeSelectorSlot#entry方法中的另一行代碼,代碼如下。


這行代碼的作用是將當(dāng)前創(chuàng)建的DefaultNode實(shí)例賦值給當(dāng)前CtEntry實(shí)例的curNode字段。結(jié)合圖4.7來理解,就是將資源GET:/hello的DefaultNode實(shí)例賦值給第一個(gè)CtEntry實(shí)例的curNode字段,將資源POST:/hello2的DefaultNode實(shí)例賦值給第二個(gè)CtEntry實(shí)例的curNode字段。

ClusterNode構(gòu)造器插槽

在一個(gè)資源的ProcessorSlotChain中,NodeSelectorSlot負(fù)責(zé)為資源創(chuàng)建DefaultNode實(shí)例,而這個(gè)DefaultNode實(shí)例僅限同一入口的調(diào)用鏈?zhǔn)褂?。所以,一個(gè)資源可能會(huì)存在多個(gè)DefaultNode實(shí)例,那么想要獲取一個(gè)資源的總QPS,就必須遍歷這些DefaultNode實(shí)例。出于性能考慮,Sentinel會(huì)為每個(gè)資源創(chuàng)建一個(gè)全局唯一的ClusterNode實(shí)例,用于統(tǒng)計(jì)資源的全局指標(biāo)數(shù)據(jù)。

與NodeSelectorSlot的職責(zé)相似,ClusterBuilderSlot的職責(zé)是為資源創(chuàng)建全局唯一的ClusterNode實(shí)例,且僅在資源第一次被訪問時(shí)創(chuàng)建。

ClusterBuilderSlot在創(chuàng)建ClusterNode實(shí)例時(shí),需要將ClusterNode實(shí)例賦值給DefaultNode實(shí)例的clusterNode字段,由DefaultNode實(shí)例持有ClusterNode實(shí)例,并由DefaultNode負(fù)責(zé)代理ClusterNode完成資源指標(biāo)數(shù)據(jù)統(tǒng)計(jì)。

必須先有DefaultNode實(shí)例,才能將ClusterNode實(shí)例委托給DefaultNode實(shí)例,這就是ClusterBuilderSlot在ProcessorSlotChain中必須被放在NodeSelectorSlot之后的原因。

ClusterBuilderSlot聲明的字段如下。


因?yàn)橐粋€(gè)資源只會(huì)有一個(gè)ProcessorSlotChain,這就意味著ClusterBuilderSlot只會(huì)被創(chuàng)建一個(gè),那么讓ClusterBuilderSlot持有資源的ClusterNode實(shí)例,就可以省去每次都從clusterNodeMap靜態(tài)字段中獲取資源的ClusterNode實(shí)例的步驟,這當(dāng)然也是出于性能方面的考慮。

ClusterBuilderSlot類的entry方法的源碼如下。


① 如果clusterNode字段為空,說明當(dāng)前資源首次被訪問,那么需要為資源創(chuàng)建一個(gè)全局唯一的ClusterNode實(shí)例。

② 將ClusterNode實(shí)例委托給資源的DefaultNode實(shí)例來統(tǒng)計(jì)資源指標(biāo)數(shù)據(jù),node參數(shù)為NodeSelectorSlot傳遞過來的DefaultNode實(shí)例。

③ 如果調(diào)用來源不為空,那么為當(dāng)前調(diào)用來源創(chuàng)建一個(gè)StatisticNode實(shí)例。

ClusterBuilderSlot將ClusterNode實(shí)例賦值給DefaultNode實(shí)例的clusterNode字段,后續(xù)的ProcessorSlot就能從entry方法的node參數(shù)中獲取ClusterNode實(shí)例。DefaultNode與ClusterNode的關(guān)系如圖4.8所示。

圖4.8 DefaultNode與ClusterNode的關(guān)系

每個(gè)ClusterNode實(shí)例都有一個(gè)Map類型的字段,用來緩存調(diào)用來源(origin)與StatisticNode實(shí)例的映射,代碼如下。


?originCountMap:如果上游服務(wù)調(diào)用當(dāng)前服務(wù)的接口將origin字段傳遞過來,那么ClusterBuilderSlot就會(huì)為ClusterNode實(shí)例創(chuàng)建一個(gè)StatisticNode實(shí)例,用來統(tǒng)計(jì)當(dāng)前資源被該遠(yuǎn)程服務(wù)調(diào)用的指標(biāo)數(shù)據(jù)。

提示:例如,上游服務(wù)在發(fā)送HTTP請(qǐng)求時(shí),在請(qǐng)求頭添加S-user參數(shù),或者上游服務(wù)在發(fā)送Dubbo RPC調(diào)用時(shí),在請(qǐng)求參數(shù)列表添加application參數(shù),就能獲取來源應(yīng)用名稱。

當(dāng)我們想要查看哪個(gè)來源應(yīng)用訪問這個(gè)接口最頻繁時(shí),可以從ClusterNode實(shí)例的originCountMap字段,根據(jù)來源應(yīng)用名稱獲取StatisticNode實(shí)例,從而獲取QPS,并據(jù)此實(shí)現(xiàn)按調(diào)用來源限流。

ClusterNode#getOrCreateOriginNode方法的源碼如下。


為了便于使用,ClusterBuilderSlot會(huì)將調(diào)用來源的StatisticNode實(shí)例賦值給CtEntry實(shí)例的originNode字段,后續(xù)的ProcessorSlot可先調(diào)用Context實(shí)例的getCurEntry方法獲取CtEntry實(shí)例,再調(diào)用CtEntry實(shí)例的getOriginNode方法即可獲取該StatisticNode實(shí)例。

這里我們可以得出一個(gè)結(jié)論,如果自定義的ProcessorSlot需要用到調(diào)用來源的StatisticNode,那么在構(gòu)建ProcessorSlotChain時(shí),必須將這個(gè)自定義的ProcessorSlot放在ClusterBuilderSlot之后。

資源指標(biāo)數(shù)據(jù)統(tǒng)計(jì)插槽

StatisticSlot是實(shí)現(xiàn)資源各項(xiàng)指標(biāo)數(shù)據(jù)統(tǒng)計(jì)的處理器插槽,它與NodeSelectorSlot、ClusterBuilderSlot共同組成了資源指標(biāo)數(shù)據(jù)統(tǒng)計(jì)流水線。

NodeSelectorSlot負(fù)責(zé)為資源創(chuàng)建DefaultNode實(shí)例,并將DefaultNode實(shí)例向下傳遞給ClusterBuilderSlot;ClusterBuilderSlot則負(fù)責(zé)加工資源的DefaultNode實(shí)例,添加ClusterNode實(shí)例,然后將DefaultNode實(shí)例向下傳遞給StatisticSlot,如圖4.9所示。

圖4.9 資源指標(biāo)數(shù)據(jù)統(tǒng)計(jì)流水線

StatisticSlot在統(tǒng)計(jì)指標(biāo)數(shù)據(jù)之前會(huì)先調(diào)用后續(xù)的ProcessorSlot,再根據(jù)后續(xù)ProcessorSlot判斷是否需要拒絕當(dāng)前請(qǐng)求的結(jié)果并決定記錄哪些指標(biāo)數(shù)據(jù)。StatisticSlot的源碼框架如下。


?entry:先通過fireEntry方法調(diào)用后續(xù)的ProcessorSlot#entry方法,再根據(jù)后續(xù)的ProcessorSlot是否拋出BlockException來決定統(tǒng)計(jì)哪些指標(biāo)數(shù)據(jù),并將資源并行占用的線程數(shù)加1。

? exit:若無任何異常,則統(tǒng)計(jì)請(qǐng)求成功、請(qǐng)求執(zhí)行耗時(shí)指標(biāo),并將資源并行占用的線程數(shù)減1。

從StatisticSlot#entry方法的源碼中可以看出,為什么Sentinel設(shè)計(jì)的責(zé)任鏈需要由前一個(gè)ProcessorSlot在entry方法或exit方法中調(diào)用fireEntry方法或fireExit方法以調(diào)用下一個(gè)ProcessorSlot的entry方法或exit方法,而不是使用for循環(huán)遍歷調(diào)用ProcessorSlot。因?yàn)槊總€(gè)ProcessorSlot都有權(quán)決定先等后續(xù)的ProcessorSlot執(zhí)行完成再做自己的事情,還是先完成自己的事情再讓后續(xù)的ProcessorSlot執(zhí)行,這與流水線有所區(qū)別。

1. entry方法

第一種情況:當(dāng)后續(xù)的ProcessorSlot未拋出任何異常時(shí),表示不需要拒絕當(dāng)前請(qǐng)求,當(dāng)前請(qǐng)求會(huì)被放行。

如果當(dāng)前請(qǐng)求被放行,則需要將當(dāng)前資源并行占用的線程數(shù)加1,將當(dāng)前時(shí)間窗口被放行的請(qǐng)求總數(shù)加1,代碼如下。


如果調(diào)用來源不為空,也將調(diào)用來源對(duì)應(yīng)的StatisticNode的當(dāng)前并行占用線程數(shù)加1,將當(dāng)前時(shí)間窗口被放行的請(qǐng)求數(shù)加1,代碼如下。


如果流量類型為IN,則讓統(tǒng)計(jì)整個(gè)應(yīng)用所有流入類型流量的ENTRY_NODE自增并行占用的線程數(shù)、當(dāng)前時(shí)間窗口被放行的請(qǐng)求數(shù)加1,代碼如下。

回調(diào)所有的ProcessorSlotEntryCallback的onPass方法,代碼如下。


調(diào)用

StatisticSlotCallbackRegistry#addEntryCallback靜態(tài)方法注冊(cè)



ProcessorSlotEntryCallback。ProcessorSlotEntryCallback接口的定義如下。


? onPass:該方法在請(qǐng)求被放行時(shí)被回調(diào)執(zhí)行。

? onBlocked:該方法在請(qǐng)求被拒絕時(shí)被回調(diào)執(zhí)行。

第二種情況:捕獲到PriorityWaitException。

這是特殊情況,在需要對(duì)請(qǐng)求限流時(shí),只有使用默認(rèn)流量效果控制器才可能會(huì)拋出PriorityWaitException,這部分內(nèi)容將在講解FlowSlot的實(shí)現(xiàn)源碼時(shí)再做分析。

當(dāng)捕獲到PriorityWaitException時(shí),說明當(dāng)前請(qǐng)求已經(jīng)被休眠了一段時(shí)間了,但還是允許請(qǐng)求通過的,只是不需要讓DefaultNode實(shí)例統(tǒng)計(jì)這個(gè)請(qǐng)求了,只自增當(dāng)前資源并行占用的線程數(shù),同時(shí),DefaultNode實(shí)例也會(huì)讓ClusterNode實(shí)例自增并行占用的線程數(shù),最后會(huì)回調(diào)所有

ProcessorSlotEntryCallback#onPass方法。這部分的源碼如下。


第三種情況:捕獲到BlockException。

BlockException只在需要拒絕請(qǐng)求時(shí)被拋出。捕獲到BlockException時(shí)執(zhí)行的代碼如下。


①當(dāng)捕獲到BlockException時(shí),將異常保存到調(diào)用鏈上下文的當(dāng)前CtEntry實(shí)例中,StatisticSlot的exit方法會(huì)識(shí)別是統(tǒng)計(jì)請(qǐng)求異常指標(biāo)還是統(tǒng)計(jì)請(qǐng)求被拒絕指標(biāo)。

②調(diào)用DefaultNode#increaseBlockQps方法自增請(qǐng)求被拒絕總數(shù),將當(dāng)前時(shí)間窗口的block qps這項(xiàng)指標(biāo)數(shù)據(jù)的值加1。

③ 如果調(diào)用來源不為空,則讓調(diào)用來源對(duì)應(yīng)的StatisticNode實(shí)例統(tǒng)計(jì)的請(qǐng)求被拒絕總數(shù)加1。

④ 如果流量類型為IN,則讓ENTRY_NODE統(tǒng)計(jì)的請(qǐng)求被拒絕總數(shù)加1。

⑤ 回調(diào)所有的

ProcessorSlotEntryCallback#onBlocked方法。

StatisticSlot捕獲BlockException只是為了統(tǒng)計(jì)請(qǐng)求被拒絕的總數(shù),而BlockException還是會(huì)被向上拋出。拋出異常的目的是攔住請(qǐng)求,執(zhí)行服務(wù)降級(jí)處理。

第四種情況:捕獲到其他異常。

其他異常并非指業(yè)務(wù)異常,因?yàn)榇藭r(shí)業(yè)務(wù)代碼還未被執(zhí)行,而業(yè)務(wù)代碼拋出的異常,會(huì)通過調(diào)用Tracer#trace方法統(tǒng)計(jì)請(qǐng)求異??倲?shù)。

當(dāng)捕獲到非BlockException時(shí),除PriorityWaitException外,其他類型的異常都進(jìn)行同樣的處理:讓資源的DefaultNode實(shí)例自增當(dāng)前時(shí)間窗口的請(qǐng)求異??倲?shù);讓調(diào)用來源的StatisticNode實(shí)例、統(tǒng)計(jì)所有IN類型流量的ENTRY_NODE自增當(dāng)前時(shí)間窗口的請(qǐng)求異??倲?shù)。這部分的源碼如下。


① 將異常保存到調(diào)用鏈上下文的當(dāng)前Entry實(shí)例中。

②調(diào)用DefaultNode#increaseExceptionQps方法統(tǒng)計(jì)異常指標(biāo),將當(dāng)前時(shí)間窗口的exception qps這項(xiàng)指標(biāo)數(shù)據(jù)的值加1。

③ 如果調(diào)用來源不為空,則讓調(diào)用來源的StatisticNode實(shí)例統(tǒng)計(jì)異常指標(biāo)。

④ 如果流量類型為IN,則讓ENTRY_NODE統(tǒng)計(jì)異常指標(biāo)。⑤ 拋出異常。

2. exit方法

當(dāng)exit方法被調(diào)用時(shí),要么請(qǐng)求被拒絕,要么請(qǐng)求被放行且已經(jīng)被執(zhí)行完成,所以exit方法需要知道當(dāng)前請(qǐng)求是否被正常執(zhí)行完成,這正是StatisticSlot在捕獲異常時(shí)將異常保存到當(dāng)前CtEntry實(shí)例的原因。

exit方法通過Context實(shí)例可以獲取當(dāng)前CtEntry實(shí)例,從當(dāng)前CtEntry實(shí)例中可以獲取entry方法中保存的異常。exit方法的源碼如下(有刪減)。

① exit方法通過Context實(shí)例可以獲取當(dāng)前資源的DefaultNode實(shí)例,如果entry方法中未出現(xiàn)異常,則說明請(qǐng)求是正常完成的。

② 當(dāng)計(jì)算耗時(shí)時(shí),可以將當(dāng)前時(shí)間減去調(diào)用鏈上當(dāng)前CtEntry實(shí)例的創(chuàng)建時(shí)間的值作為請(qǐng)求的執(zhí)行耗時(shí)。

③ 在請(qǐng)求被正常完成的情況下,需要統(tǒng)計(jì)總耗時(shí)指標(biāo),增加當(dāng)前請(qǐng)求的執(zhí)行耗時(shí),統(tǒng)計(jì)成功請(qǐng)求總數(shù),將成功請(qǐng)求總數(shù)加1。

④ 如果調(diào)用來源不為空,則讓調(diào)用來源的StatisticNode實(shí)例統(tǒng)計(jì)總耗時(shí)指標(biāo),增加當(dāng)前請(qǐng)求的執(zhí)行耗時(shí),統(tǒng)計(jì)成功請(qǐng)求總數(shù),將成功請(qǐng)求總數(shù)加1。

⑤ 恢復(fù)當(dāng)前資源占用的線程數(shù)。

⑥ 如果調(diào)用來源不為空,則恢復(fù)當(dāng)前調(diào)用來源占用的線程數(shù)。

⑦如果流量類型為IN,則讓ENTRY_NODE統(tǒng)計(jì)總耗時(shí)指標(biāo),增加當(dāng)前請(qǐng)求的執(zhí)行耗時(shí),統(tǒng)計(jì)成功請(qǐng)求總數(shù),將成功請(qǐng)求總數(shù)加1,恢復(fù)占用的線程數(shù)。

⑧ 回調(diào)所有ProcessorSlotExitCallback#onExit方法。

資源指標(biāo)數(shù)據(jù)的收集過程

ClusterNode是一個(gè)資源全局的指標(biāo)數(shù)據(jù)統(tǒng)計(jì)節(jié)點(diǎn),但我們并未在StatisticSlot的entry方法與exit方法中看到其被使用。這里實(shí)際上使用了委托模式,ClusterNode被ClusterBuilderSlot委托給DefaultNode統(tǒng)計(jì)指標(biāo)數(shù)據(jù),如下述代碼所示。

當(dāng)請(qǐng)求被成功處理后,StatisticSlot會(huì)調(diào)用DefaultNode實(shí)例的addRtAndSuccess方法增加請(qǐng)求處理成功總數(shù)和總耗時(shí);DefaultNode會(huì)先調(diào)用父類的addRtAndSuccess方法,再調(diào)用ClusterNode實(shí)例的addRtAndSuccess方法。ClusterNode類與DefaultNode類都是StatisticNode類的子類。StatisticNode類的addRtAndSuccess方法的源碼如下。

rollingCounterInSecond是一個(gè)秒級(jí)滑動(dòng)窗口,rollingCounterInMinute是一個(gè)分鐘級(jí)滑動(dòng)窗口,類型都為ArrayMetric。分鐘級(jí)滑動(dòng)窗口共有60個(gè)MetricBucket,每個(gè)MetricBucket都會(huì)被WindowWrap數(shù)組包裝,用于統(tǒng)計(jì)1秒內(nèi)的各項(xiàng)指標(biāo)數(shù)據(jù),如圖4.10所示。

圖4.10 WindowWrap數(shù)組

當(dāng)調(diào)用rollingCounterInMinute的addSuccess方法時(shí),先由滑動(dòng)窗口根據(jù)當(dāng)前時(shí)間戳獲取當(dāng)前時(shí)間窗口的MetricBucket實(shí)例,再調(diào)用MetricBucket實(shí)例的addSuccess方法,將success這項(xiàng)指標(biāo)的值加上方法參數(shù)successCount的值(一般是1)。

Sentinel在MetricEvent枚舉類中定義了Sentinel會(huì)收集的指標(biāo)數(shù)據(jù)。MetricEvent枚舉類的源碼如下。

? PASS指標(biāo):請(qǐng)求被放行的總數(shù)。

? BLOCK指標(biāo):請(qǐng)求被拒絕的總數(shù)。

? EXCEPTION指標(biāo):異常的請(qǐng)求總數(shù)。

? SUCCESS指標(biāo):被成功處理的請(qǐng)求總數(shù)。

? RT指標(biāo):被成功處理的請(qǐng)求的總耗時(shí)。

?OCCUPIED_PASS指標(biāo):預(yù)通過總數(shù)(前一個(gè)時(shí)間窗口使用了當(dāng)前時(shí)間窗口的passQps)。

其他一些指標(biāo)數(shù)據(jù)都可以通過以上指標(biāo)數(shù)據(jù)計(jì)算得出,例如,被成功處理的請(qǐng)求的平均耗時(shí)可以根據(jù)被成功處理的請(qǐng)求的總耗時(shí)除以被成功處理的請(qǐng)求總數(shù)計(jì)算得出。

小結(jié)

本篇主要介紹了Sentinel如何實(shí)現(xiàn)基于滑動(dòng)窗口統(tǒng)計(jì)資源的實(shí)時(shí)指標(biāo)數(shù)據(jù)、Sentinel資源指標(biāo)數(shù)據(jù)統(tǒng)計(jì)流程分析,以及調(diào)用樹的結(jié)構(gòu),同時(shí)分析了NodeSelectorSlot、ClusterBuilderSlot和StatisticSlot這幾個(gè)處理器插槽的用途及它們之間的聯(lián)系。


深度解析微服務(wù)高并發(fā)資源指標(biāo)數(shù)據(jù)統(tǒng)計(jì):資源指標(biāo)數(shù)據(jù)統(tǒng)計(jì)全解析的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國家法律
马尔康县| 泸州市| 台东县| 南城县| 峨眉山市| 赤壁市| 通城县| 句容市| 东乌| 哈密市| 巴东县| 贺州市| 广河县| 会同县| 东城区| 蚌埠市| 习水县| 新津县| 鄂尔多斯市| 治多县| 定结县| 麦盖提县| 江城| 东乌珠穆沁旗| 乌拉特前旗| 当雄县| 尼木县| 小金县| 黄大仙区| 杭州市| 厦门市| 阳高县| 合江县| 无棣县| 陈巴尔虎旗| 平阴县| 宜良县| 乌什县| 芜湖市| 瓦房店市| 基隆市|