idou老師教你學Istio 27:解讀Mixer Report流程

1、概述

Mixer是Istio的核心組件,提供了遙測數據收集的功能,能夠實時采集服務的請求狀態等信息,以達到監控服務狀態目的。

1.1 核心功能

?前置檢查(Check):某服務接收并響應外部請求前,先通過Envoy向Mixer(Policy組件)發送Check請求,做一些access檢查,同時確認adaptor所需cache字段,供之后Report接口使用;

?配額管理(Quota):通過配額管理機制,處理多請求時發生的資源競爭;

?遙測數據上報(Report):該服務請求處理結束后,將請求相關的日志,監控等數據,通過Envoy上報給Mixer(telemetry)

1.2 示例圖

idou老師教你學Istio 27:解讀Mixer Report流程

2、代碼分析

2.1 Report代碼分析

本節主要介紹Report的詳細流程(基于Istio release1.0.0版本,commit id為3a136c90)。Report是mixer server的一個接口,供Envoy通過grpc調用。首先,我們從mixer server的啟動入口main函數看起:

func main() {rootCmd := cmd.GetRootCmd(os.Args[1:], supportedTemplates(), supportedAdapters(), shared.Printf, shared.Fatalf)if err := rootCmd.Execute(); err != nil {os.Exit(-1)}
}

在rootCmd中,mixs通過server命令啟動了mixer server,從而觸發了runserver函數,在runserver中初始化(New)了一個server,我們一起看下newServer的函數,在這個函數中,與我們本節相關的內容就是Mixer初始化了一個grpc服務器NewGRPCServer。

rootCmd.AddCommand(serverCmd(info, adapters, printf, fatalf))
func serverCmd(info map[string]template.Info, adapters []adapter.InfoFn, printf, fatalf shared.FormatFn) *cobra.Command {sa := server.DefaultArgs()sa.Templates = infosa.Adapters = adaptersserverCmd := &cobra.Command{Use:   "server",Short: "Starts Mixer as a server",Run: func(cmd *cobra.Command, args []string) {runServer(sa, printf, fatalf)},}… …
}
func newServer(a *Args, p *patchTable) (*Server, error) {grpc.EnableTracing = a.EnableGRPCTracings.server = grpc.NewServer(grpcOptions...)mixerpb.RegisterMixerServer(s.server, api.NewGRPCServer(s.dispatcher, s.gp, s.checkCache))
}

在這個grpc的服務端中,定義了一個Report接口,這就是我們這節課主要關注的內容(可以看到Check接口也在此定義,我們下節再講)

func (s *grpcServer) Report(ctx context.Context, req *mixerpb.ReportRequest) (*mixerpb.ReportResponse, error) {lg.Debugf("Report (Count: %d)", len(req.Attributes))// 校驗attribute是否為空,空則直接returnif len(req.Attributes) == 0 {return reportResp, nil}// 若屬性word為空,賦為默認值for i := 0; i < len(req.Attributes); i++ {iflen(req.Attributes[i].Words) == 0 {req.Attributes[i].Words = req.DefaultWords}}// 根據第一條attribute,生成proto包,proto包能跟蹤一組attributesprotoBag := attribute.NewProtoBag(&req.Attributes[0], s.globalDict, s.globalWordList)// 初始化,開始跟蹤attributes各個條目中屬性accumBag := attribute.GetMutableBag(protoBag)// 保存accumBag的增量狀態reportBag := attribute.GetMutableBag(accumBag)reportSpan, reportCtx := opentracing.StartSpanFromContext(ctx, "Report")reporter := s.dispatcher.GetReporter(reportCtx)var errors *multierror.Errorfor i := 0; i < len(req.Attributes); i++ {span, newctx := opentracing.StartSpanFromContext(reportCtx, fmt.Sprintf("attribute bag %d", i))// 第一個屬性已經在創建proto包時創建,在此追蹤所有attributesif i > 0 {if err := accumBag.UpdateBagFromProto(&req.Attributes[i], s.globalWordList); err != nil {err = fmt.Errorf("request could not be processed due to invalid attributes: %v", err)span.LogFields(otlog.String("error", err.Error()))span.Finish()errors = multierror.Append(errors, err)break}}lg.Debug("Dispatching Preprocess")// 真正開始分發,預處理階段if err := s.dispatcher.Preprocess(newctx, accumBag, reportBag); err != nil {err = fmt.Errorf("preprocessing attributes failed: %v", err)span.LogFields(otlog.String("error", err.Error()))span.Finish()errors = multierror.Append(errors, err)continue}lg.Debug("Dispatching to main adapters after running preprocessors")lg.Debuga("Attribute Bag: \n", reportBag)lg.Debugf("Dispatching Report %d out of %d", i+1, len(req.Attributes))// 真正開始分發,將數據逐步加入到緩存中if err := reporter.Report(reportBag); err != nil {span.LogFields(otlog.String("error", err.Error()))span.Finish()errors = multierror.Append(errors, err)continue}span.Finish()// purge the effect of the Preprocess call so that the next time through everything is cleanreportBag.Reset()}reportBag.Done()accumBag.Done()protoBag.Done()// 真正的發送函數,從緩存中取出并發送到adaptorif err := reporter.Flush(); err != nil {errors = multierror.Append(errors, err)}reporter.Done()if errors != nil {reportSpan.LogFields(otlog.String("error", errors.Error()))}reportSpan.Finish()if errors != nil {lg.Errora("Report failed:", errors.Error())return nil, grpc.Errorf(codes.Unknown, errors.Error())}// 過程結束return reportResp, nil
}

通過上述代碼解讀,我們了解了Report接口的工作流程,但此時我們還并不知道一個請求的狀態是如何報給adaptor的,下面我們通過簡要的函數串接,把這部分流程串起來:

上述的預處理階段Preprocess與上報階段Report,最終都會調用到dispatch函數,僅通過不同的type來區分要做的事情;

func (d *Impl) Preprocess(ctx context.Context, bag attribute.Bag, responseBag *attribute.MutableBag) error {s := d.getSession(ctx, tpb.TEMPLATE_VARIETY_ATTRIBUTE_GENERATOR, bag)s.responseBag = responseBagerr := s.dispatch()if err == nil {err = s.err}… …
}
func (r *reporter) Report(bag attribute.Bag) error {s := r.impl.getSession(r.ctx, tpb.TEMPLATE_VARIETY_REPORT, bag)s.reportStates = r.stateserr := s.dispatch()if err == nil {err = s.err}… …
}

而dispatch函數中做了真正的分發動作,包括:

1.遍歷所有adaptor,調用adaptor中的函數,針對不同的adaptor生成不同的instance,并將instance緩存放入reportstates

var instance interface{}
if instance, err = input.Builder(s.bag); err != nil {log.Errorf("error creating instance: destination='%v', error='%v'", destination.FriendlyName, err)s.err = multierror.Append(s.err, err)continue
}
type NamedBuilder struct {InstanceShortName stringBuilder           template.InstanceBuilderFn
}
InstanceBuilderFn func(attrs attribute.Bag) (interface{}, error)
CreateInstanceBuilder: func(instanceName string, param proto.Message, expb *compiled.ExpressionBuilder) (template.InstanceBuilderFn, error)
builder.build(attr)
// For report templates, accumulate instances as much as possible before commencing dispatch.
if s.variety == tpb.TEMPLATE_VARIETY_REPORT {state.instances = append(state.instances, instance)continue
}

2.將instance分發到所有adaptor,最終調用并分發到adaptor的HandleMetric函數中

func (r *reporter) Flush() error {s := r.impl.getSession(r.ctx, tpb.TEMPLATE_VARIETY_REPORT, nil)s.reportStates = r.statess.dispatchBufferedReports()err := s.err… …
}
func (s *session) dispatchBufferedReports() {// Ensure that we can run dispatches to all destinations in parallel.s.ensureParallelism(len(s.reportStates))// dispatch the buffered dispatchStates we've gotfor k, v := range s.reportStates {s.dispatchToHandler(v)delete(s.reportStates, k)}s.waitForDispatched()
}
func (s *session) dispatchToHandler(ds *dispatchState) {s.activeDispatches++ds.session = ss.impl.gp.ScheduleWork(ds.invokeHandler, nil)
}
case tpb.TEMPLATE_VARIETY_REPORT:ds.err = ds.destination.Template.DispatchReport(ctx, ds.destination.Handler, ds.instances)
type TemplateInfo struct {Name             stringVariety          tpb.TemplateVarietyDispatchReport   template.DispatchReportFnDispatchCheck    template.DispatchCheckFnDispatchQuota    template.DispatchQuotaFnDispatchGenAttrs template.DispatchGenerateAttributesFn
}
DispatchReport: func(ctx context.Context, handler adapter.Handler, inst []interface{}) error {// Convert the instances from the generic []interface{}, to their specialized type.instances := make([]*metric.Instance, len(inst))for i, instance := range inst {instances[i] = instance.(*metric.Instance)}// Invoke the handler.if err := handler.(metric.Handler).HandleMetric(ctx, instances); err != nil {return fmt.Errorf("failed to report all values: %v", err)}return nil
}

2.2 相關結構體定義

Report接口請求體定義

// Used to report telemetry after performing one or more actions.
type ReportRequest struct {// 代表一個請求中的屬性// 每個attribute代表一個請求動作,多個動作可匯總在一條message中以提高效率//雖然每個“屬性”消息在語義上被視為與消息中的其他屬性無關的獨立獨立實體,但此消息格式利用屬性消息之間的增量編碼,以便大幅減少請求大小并改進端到端 效率。 每組單獨的屬性用于修改前一組。 這消除了在單個請求中多次冗余地發送相同屬性的需要。// 如果客戶端上報時不想使用增量編碼,可全量的發送所有屬性.Attributes []CompressedAttributes `protobuf:"bytes,1,rep,name=attributes" json:"attributes"`// 所有屬性的默認消息級字典.// 這使得可以為該請求中的所有屬性共享相同的字典,這可以大大減少整體請求大小DefaultWords []string `protobuf:"bytes,2,rep,name=default_words,json=defaultWords" json:"default_words,omitempty"`// 全局字典的詞條數,可檢測客戶端與服務端之間的全局字典是否同步GlobalWordCount uint32 `protobuf:"varint,3,opt,name=global_word_count,json=globalWordCount,proto3" json:"global_word_count,omitempty"`
}

3、總結

Mixer中涉及很多緩存命中等用于優化性能的設計,本文僅介紹了Mixer中Report接口發送到adaptor的過程,一些性能優化設計,如protobag,dispatch緩存等內容,將會在后續文章中解析。

相關服務請訪問https://support.huaweicloud.com/cce/index.html?cce_helpcenter_2019

轉載于:https://blog.51cto.com/14051317/2353294

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

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

相關文章

mysql刪除密碼代碼_mysql 用戶新建、受權、刪除、密碼修改

mysql 用戶新建、授權、刪除、密碼修改首先要聲明一下&#xff1a;一般情況下&#xff0c;修改MySQL密碼&#xff0c;授權&#xff0c;是需要有mysql里的root權限的。注&#xff1a;本操作是在WIN命令提示符下&#xff0c;phpMyAdmin同樣適用。用戶&#xff1a;phplamp 用戶數…

KindEditor 上傳漏洞致近百個黨政機關網站遭植入

開發四年只會寫業務代碼&#xff0c;分布式高并發都不會還做程序員&#xff1f; >>> 2月21日消息&#xff0c;近日&#xff0c;安恒明鑒網站安全監測平臺和應急響應中心監測發現近百起黨政機關網站被植入色情廣告頁面&#xff0c;分析發現被植入色情廣告頁面的網站都…

php mysql登陸頁面完整代碼_求助:PHP實現登陸注冊的代碼是什么啊(主要是數據庫那塊)?...

思路&#xff1a;注冊&#xff1a;獲取前臺表單數據->數據庫連接->判斷數據是否存在&#xff0c;存在輸出提示&#xff0c;不存在則向數據庫插入表單傳來的值->如果sql執行失敗輸出錯誤&#xff0c;成功功輸出注冊成功登陸&#xff1a;獲取前臺表單數據->數據庫連接…

Insql 1.8.2 發布,輕量級 .NET ORM 類庫

開發四年只會寫業務代碼&#xff0c;分布式高并發都不會還做程序員&#xff1f; >>> Insql 是一個輕量級的.NET ORM 類庫。對象映射基于 Dapper, Sql 配置靈感來自于 Mybatis。 TA 的追求&#xff1a;簡潔、優雅、性能與質量 TA 的宗旨&#xff1a;讓你用起來感覺到…

python 函數中所有print保存csv_python for循環print怎樣才能輸出csv呢

import csv,redef search(req,line):text re.search(req,line)if text:data text.group(1)else:data noreturn datacsvfile file(serp_html.csv,rb)reader csv.reader(csvfile)輸出百度搜索結果數據&#xff1a;當前關鍵詞&#xff0c;排名&#xff0c;排名網站&#xff0…

java中具有繼承關系的類及其對象初始化順序

先說結論對于具有繼承關系的類&#xff0c;它們的類和對象構造順序為&#xff1a;父類的類構造器() -> 子類的類構造器() -> 父類成員變量的賦值和實例代碼塊 -> 父類的構造函數 -> 子類成員變量的賦值和實例代碼塊 -> 子類的構造函數。 實驗代碼如下&#xff1…

mysql varchar 2000能存_mysql 數據庫 varchar 到底可以存多少數據呢,長文慎入

一、關于UTF-8 UTF-8 Unicode Transformation Format-8bit。是用以解決國際上字符的一種多字節編碼。 它對英文使用8位(即一個字節)&#xff0c;中文使用24位(三個字節)來編碼。 UTF-8包含全世界所有國家需要用到的字符&#xff0c;是國際編碼&#xff0c;通用性強。 UTF-8編碼…

教程 | 如何利用C++搭建個人專屬的TensorFlow

在開始之前&#xff0c;首先看一下最終成型的代碼&#xff1a; 分支與特征后端&#xff08;https://github.com/OneRaynyDay/autodiff/tree/eigen&#xff09;僅支持標量的分支&#xff08;https://github.com/OneRaynyDay/autodiff/tree/master&#xff09;這個項目是我與 Min…

docker kali安裝mysql_kali安裝docker(有效詳細的教程) ——vulhub漏洞復現 001

前記&#xff1a;博主有著多次安裝docker的豐富經驗&#xff0c;曾經為了在kali成功安裝docker花費不少時間。在kali2016.3一直到最新的kali2019.4都通吃&#xff01;所以跟著下面的步驟走&#xff0c;絕對不會出錯。(該機子此前沒裝過docker&#xff0c;并且配置好了kali更新源…

PDF文件如何轉成markdown格式

百度上根據pdf轉makrdown為關鍵字進行搜索&#xff0c;結果大多數是反過來的轉換&#xff0c;即markdown文本轉PDF格式。 但是PDF轉markdown的解決方案很少。 正好我工作上有這個需求&#xff0c;所以自己實現了一個解決方案。 下圖是一個用PDF XChange Editor打開的PDF文件&am…

kangle支不支持PHP_【轉載】PHP調用kangle的API

摘要&#xff1a;根據管理的API公布寫了一個類封裝了一個操作集合&#xff0c;這是一個kangleAPI的一個封...根據管理的API公布寫了一個類封裝了一個操作集合&#xff0c;這是一個kangleAPI的一個封裝吧&#xff0c;是在其他地方看到的&#xff0c;接口包含獲取easypanel的信息…

ES6 學習筆記(一)let,const和解構賦值

let和const let和const是es6新增的兩個變量聲明關鍵字&#xff0c;與var的不同點在于&#xff1a; &#xff08;1&#xff09;let和const都是塊級作用域&#xff0c;在{}內有效&#xff0c;這點在for循環中非常有用&#xff0c;只在循環體內有效。var為函數作用域。 &#xff0…

mysql數據庫容量和性能_新品速遞丨容量盤性能提升超 300%,數據庫支持 MySQL 8.0...

2關系型數據庫 MySQL Plus支持 MySQL 8.0 內核及 XtraBackup 物理在線遷移方式關系型數據庫服務 MySQL Plus 發布新版本 1.0.6 &#xff0c; 新增多項功能&#xff0c;提升了集群自動化運維能力。主要升級有&#xff1a;- 支持 MySQL 8.0 內核&#xff1a;根據官方測試&#xf…

10. Python面向對象

Python從設計之初就已經是一門面向對象的語言&#xff0c;正因為如此&#xff0c;在Python中創建一個類和對象是很容易的。如果接觸過java語言同學應該都知道&#xff0c;Java面向對象三大特征是&#xff1a;封裝、繼承、多態。Python面向對象也有一些特征&#xff0c;接下來我…

mysql聚簇索引 和主鍵的區別_[MySQL] innoDB引擎的主鍵與聚簇索引

MysqL的innodb引擎本身存儲的形式就必須是聚簇索引的形式,在磁盤上樹狀存儲的,但是不一定是根據主鍵聚簇的,有三種情形:1. 有主鍵的情況下,主鍵就是聚簇索引2. 沒有主鍵的情況下,第一個非空null的唯一索引就是聚簇索引3. 如果上面都沒有,那么就是有一個隱藏的row-id作為聚簇索引…

前端頁面:一直報Cannot set property 'height' of undefined

1、出現錯誤的例子&#xff0c;只拷貝了項目中關鍵出現問題的部分 例子中明明寫了styleheight:16px這個屬性&#xff0c;但是為什么還說height未定義呢 通過打印發現&#xff1a;cks.each(function () { autoTextAreaHeight($(this)); });中的$(this)取出來…

mysql表在線轉成分區表_11g普通表在線轉換分區表

本帖最后由 燈和樹 于 2016-5-4 14:58 編輯由于業務系統數據量增大&#xff0c;對其用戶表在線完成分區表轉換過程&#xff0c;記錄如下&#xff0c;11g數據庫支持。創建過渡分區表根據USER_ID創建分區表CREATE TABLE SDP_SMECD.TEST_T_USER_ID(USER_ID NUMBER(13) …

tiger4444/rabbit4444后綴勒索病毒怎么刪除 能否百分百恢復

上海某客戶中了tiger4444的勒索病毒&#xff0c;找到我們后&#xff0c;一天內全部恢復完成。說了很多關于勒索病毒的事情&#xff0c;也提醒過大家&#xff0c;可總是有人疏忽&#xff0c;致使中招后&#xff0c;丟錢丟面子&#xff0c;還丟工作。 那么要怎樣預防呢與處理呢&a…

mysql遠程一會不用卡住_連接遠程MySQL數據庫項目啟動時,不報錯但是卡住不繼續啟動的,...

連接遠程MySQL數據庫項目啟動時&#xff0c;不報錯但是卡住不繼續啟動的&#xff0c;2018-03-12 17:08:52.532DEBUG[localhost-startStop-1]o.s.beans.factory.support.DefaultListableBeanFactory.doGetBean():251 -Returning cached instance of singleton bean ‘org.spring…

GPT-5、開源、更強的ChatGPT!

年終歲尾&#xff0c;正值圣誕節熱鬧氣氛的OpenAI寫下了2024年的發展清單。 OpenAI聯合創始人兼首席執行官Sam Altman在社交平臺公布&#xff0c;AGI&#xff08;稍晚一些&#xff09;、GPT-5、更好的語音模型、更高的費率限制&#xff1b; 更好的GPTs&#xff1b;更好的推理…