您好!欢迎来到爱源码

爱源码

热门搜索: 抖音快手短视频下载   

微服务-如何处理链接跟踪问题 <源代码交易>

  • 时间:2022-08-18 00:31 编辑: 来源: 阅读:313
  • 扫一扫,手机访问
摘要:微服务-如何处理链接跟踪问题 <源代码交易>
一、链路跟踪微服务架构将单个应用划分为各种小的、相互连接的服务,每个服务完成单个业务功能,彼此独立、解耦,每个服务可以独立演进。 与传统的单一服务相比,微服务具有隔离性、技术异构性、可扩展性和部署简化等优势。 同样,微服务架构在带来诸多好处的同时,也给系统增加了不少复杂性。 作为一种分布式服务,通常部署在由不同数据中心和不同服务器组成的集群中。 而且,同一个微服务系统,可能是不同团队,不同语言开发的。 通常一个应用由多个微服务组成,微服务之间的数据交互需要通过远程过程调用来完成。因此,在一个由许多微服务组成的系统中,请求需要在服务之间流动,调用链路复杂。一旦出现问题,就很难定位问题和跟踪异常。 链路跟踪系统就是为了解决上述问题而产生的。用于跟踪每个请求的完整调用链路,记录从请求开始到请求结束所调用任务的名称、耗时、标签数据和日志信息,并通过可视化界面进行分析和展示,帮助技术人员准确定位异常服务,发现性能瓶颈,梳理调用链路,估算系统容量。 链接跟踪系统几乎所有的理论模型都借鉴了谷歌的一篇论文“Dapper,一个大规模分布式系统跟踪基础设施”,典型的产品有优步·耶格、推特zipkin、淘宝鹰眼等 尽管这些产品以不同的方式实现,但通常有三个核心步骤:数据收集、数据存储和查询呈现。 链路跟踪系统的首要和最基本的工作是数据采集。 在这个过程中,链接跟踪系统需要入侵客户端代码进行嵌入,用来收集跟踪数据。 但由于不同链接跟踪系统的API互不兼容,埋点代码编写不一样,导致客户在切换不同链接跟踪产品时改动很大。 为了解决这类问题,OpenTracing规范应运而生,旨在统一链接跟踪系统的API。 第二,OpenTracing规范。OpenTracing是一套分布式追踪协议,独立于平台和语言,具有统一的接口规范,方便接入不同的分布式追踪系统。 2.1数据模型开放追踪语义规范中定义的数据模型包括Trace、Sapn和Reference。 2.1.1 Trace Trace表示一个完整的跟踪环节,比如一个事务或者一个流程的执行过程。 轨迹是由一个或多个区间组成的有向无环图(DAG)。 下图显示了由8个跨度组成的轨迹:[span a]↓↓(根跨度)|+-| |[Span b][Span C]↓↓( Span C是` Span A的'子跨度)| |[Span D]+-+| |[Span E][Span F]& gt;& gt& gt[Span G]>& gt& gt[Span H]↑↑↑( Span G ` follows from ` Span F)按时间轴更直观地显示轨迹:-time[Span A][Span B][Span D][Span C][Span E][Span F][Span G][Span H]2 . 1 . 2 Span Span代表一个独立的工作单元,它是跟踪链路的基本组成部分。 例如,RPC调用、函数调用或Http请求。 每个Span封装了以下状态:操作名用于表示Span的任务名 例如,RPC方法名、函数名或大型任务中的子任务名。 开始时间戳任务开始时间 结束时间戳 任务结束时间 通过Span的结束时间戳和开始时间戳,可以计算出Span的总时间消耗。 一组跨度标签。每个Span标签都是一个键值对。 键必须是字符串,值可以是字符串、布尔值或数字类型。 一组跨度日志每个跨度日志由一个键值对和一个相应的时间戳组成。 键必须是字符串,值可以是任何类型。 2.1.3参照一个跨度可以与一个或多个跨度有因果关系,称为参照。 OpenTracing目前定义了两种关系:ChildOf(父子)和FollowsFrom(后续)。 子关系的父跨度的执行依赖于子跨度的执行结果,子跨度和父跨度的引用关系是ChildOf。 例如,对于RPC调用,服务器的Span(子Span)和客户端调用的Span(父Span)是ChildOf关系。 FollowFrom关系的父跨度的执行不依赖于子跨度的执行结果,子跨度和父跨度之间的引用关系是follow from。 FollowFrom通常用于指示异步调用,例如消息队列中消费者范围和生产者范围之间的关系。 2.2应用程序接口(API)2.2.1 Tracer Tracer接口用于跨进程创建跨度、注入数据和提取数据。 它通常有以下功能:开始一个新的跨度创建和开始一个新的跨度。 将SpanContext注入到载体中 从载体中提取SpanContext 2.2.2 spanRetrieve一个SpanContext返回Span对应的Span上下文。 覆盖操作名升级操作名 设置跨度标签设置跨度标签数据 日志结构化数据记录结构化数据。 设置行李项行李项是一个字符串型的键值对,对应一个Span,用Trace传播。 因为每个键值都将被复制到每个本地和远程子Span,这可能会导致巨大的网络和CPU开销。 Getbaggage item获取baggage item的值。 完成完成一个跨度 2.2.3 Span上下文用于承载跨越服务边界的数据,包括跟踪ID、Span ID和需要传播到下游Span的行李数据。 在OpenTracing中,强制要求SpanContext的实例是不可变的,以避免在Span完成并被引用时出现复杂的生命周期问题。 2.2.4 NoopTracer所有OpenTracing API的实现都必须提供某种形式的NoopTracer,用来标记和控制OpenTracing或者注入一些对测试无害的东西。 3.Jaeger Jaeger是优步的开源分布式追踪系统,其应用程序界面完全遵循OpenTracing规范。 Jaeger本身是用go语言编写的,是跨平台、跨语言的,提供各种语言的用户界面,如c++、java、go、python、ruby、php、nodejs等。 3.1 Jaeger组件微服务——如何处理链接追踪问题jaeger-clientjaeger的客户端代码库,它实现了OpenTracing协议。 当我们的应用程序组装它时,它负责收集数据并将其发送给jaeger-agent。 这是我们唯一需要写代码的地方。 Jaeger-agent负责从jaeger-client接收Trace/Span信息,并将其批量上传到jaeger-collector。 Jaeger-collector负责接收来自jaeger-agent的Trace/Span信息,经过验证、索引等解决方案后,写入后台存储。 数据存储负责数据存储。 Jaeger的数据存储是一个可插拔的组件,目前支持Cassandra、ElasticSearch和Kafka。 耶格-查询和。负责ui数据查询,并通过前台界面显示查询结果。 微服务-如何处理链接追踪问题3.2快速入门Jaeger官方提供了一张一体化图片,方便快速测试:# Pull image $ Docker Pull Jaeger追踪/一体化:最新# Run image $ Docker Run-d-name Jaeger \-e COLLECTOR _ ZIPKIN _ HTTP _ PORT = 9411 \-p 5775:5775/UDP \-p 6831:6831/UDP \-p 6832:6832 以下是端口使用说明:微服务——如何处理链接跟踪问题。启动后,我们可以访问http://localhost:16686,在浏览器中查看和查询采集的数据。 因为一体机镜像采集的数据存储在docker中,不能长期保存,所以只能在开发或测试环境中使用,不能在生产环境中使用。 在生产环境中,每个组件都需要根据实际情况进行部署。 4.Jaeger在业务代码的应用系统中使用Jaeger非常简单,只要在原程序中插入一些代码即可。 下面的代码模拟了一个查询客户账户余额并执行扣款的业务场景:4.1初始化jaeger函数主要是根据实际需要配置相关参数,如服务名称、采样方式、采样比例等。 Funinit jaeger () (tracer开放追踪。追踪器,关闭。closer,err error){//构造配置信息cfg := & Config。配置{ //设置服务名ServiceName: "ServiceAmount ",//设置采样参数Sampler:& amp config . Sampler config { type:" const ",//全采样模式Param: 1,// on state},}//生成新的tracer tracer,closer,Err = CFG . new tracer()if Err = = nil {//设置tracer为全局singleton对象open tracking . Set global tracer(tracer)} return } 4.2检测客户平衡的函数用于检测客户平衡,模拟一个子任务Span。 Funcheck balance (request string,CTX context . context){//Create span span,_:= open tracking . startspanfromcontext(CTX,“check balance”)//仿真系统执行一系列操作,耗时1/3秒。睡眠(时间。Second/3) //示例:将要跟踪的信息放入tag span。SetTag("request ",Request) span.set tag ("reply "," check balance reply ")//结束当前span . finish()log . println(" check balance done ")} 4.3从客户账户扣款功能模拟一个子任务span C reduction (requeststring,CTX context . context){//创建一个子span span,_:= open tracking . startspanfromcontext(CTX,“Reduction”)//仿真系统执行一系列操作,耗时1/2秒。睡眠(时间。Second/2) //示例:将要跟踪的信息放入tag span。SetTag("request ",请求)span.settag ("reply "," reduction reply ")//结束当前span . finish()log . println(" reduction done ")} 4.4主函数初始化jaeger环境,生成tracer,创建父span,调用两个子任务span,分别是余额查询和推演。 package main import(" context " " fmt " " github . com/open tracing/open tracing-go " " github . com/Uber/jaeger-client-go/Config " " io " " log " " time ")funcmain(){//初始化jaeger并创建新的tracer Tracer,closer,err: = initjaeger () if err!= nil { Panic(fmt . sprintf(" error:cannotinit jaeger:% v \ n ",err))} defer coller . close()//创建一个新的span作为父span,启动计费流程span:= tracer . startspan(" calculate fee ")//生成父span的上下文CTX:= open tracking . context withsspan(context . background()),span) //示例:设置一个span标记信息span.settag ("db.instance "," customers ")//示例:输出一个Span日志信息Span。LogKV("event "," timed out") //调用check balance(" check balance request ",CTX)函数,将父span的上下文作为参数。//以父span的上下文为参数,调用演绎函数reduction ("reduction request ",CTX)//结束父span。Finish ()}五、Jaeger在gRPC微服中的应用。我们仍然模拟一个查询客户账户余额并执行扣款的业务场景。并将查询客户账户余额、执行扣款等功能转化为gRPC微服务:5.1 gRPC服务器代码main.go:代码使用第三方依赖库github . com/gRPC-ecosystem/go-gRPC-middleware/tracing/OpenTracing,将open tracing封装为通用gRPC中间件,通过gRPC拦截器无缝嵌入到gRPC服务中。 包main import(" fmt " " github . com/grpc-ecosystem/go-grpc-middleware/tracing/open tracing " " github . com/open tracing/open tracing-go " " github . com/Uber/jaeger-client-go/config " " Google . golang . org/grpc " " Google . golang . org/grpc/Reflection " " grpc-jaeger-server/account " " io " " log " " net ")//初始化jaeger func init jaeger()(tracer open tracking。追踪者,靠近木卫一。closer,err error){//构造配置信息cfg := & Config。配置{ //设置服务名ServiceName: "ServiceAmount ",//设置采样参数Sampler:& amp config . Sampler config { type:" const ",//全采样模式Param: 1,//开启全采样模式},}//生成新的tracer tracer,closer,Err = CFG . new tracer()if Err = = nil {//设置Tracer为全局单例对象open tracing . Set global Tracer(Tracer)} return } funcmain(){//初始化jaeger并创建新的tracer Tracer,closer,err: = init Jaeger () if err!= nil { panic(fmt。Sprintf("ERROR:无法初始化Jaeger: %v\n ",err)) }延迟关闭。关闭()日志。println(" succeed to init jaeger ")//注册grpc帐户服务服务器:= gRPC . new server(gRPC . unary interceptor(gRPC _ open tracking . unary server interceptor(gRPC _ open tracking . with tracer(tracer)))account . Register Accountserver(server,& Accountserver { })reflection . Register(server)log . println(" succeeded to Register account service ")//监听gRPC帐户服务端口监听器,err: = net.listen ("TCP ",":8080 ")如果err!= nil { log . println(err)return } log . println("启动注册帐户服务")//如果err := server,则启动gRpc帐户服务。服务(倾听者);呃!= nil {log。println(err)return } } account sever . go:Package Main Import(" github . com/Open tracking/Open tracking-go " " golang . org/x/net/context " " grpc-jaeger-server/account " " time ")//计费服务类型AccountServer struct{}//检测客户余额的微服务,模拟子span task func (s * account server)检查余额(ctxcontext.context,request * account.check balance请求)(response * account.check balance响应,error error){ response = & account . check balance睡眠(时间。Second/3) //将要跟踪的信息放入tag span。SetTag("request ",请求)span.settag ("reply ",响应)//结束当前span.finish()返回响应,err }//从客户账户中扣除微服务,模拟子span task func(s * accountserver)Reduction(CTX context . Request * account . Reduction Request)(response * account . Reduction response,err err){ response = & account . Reduction response { reply:" Reduction reply " ,//求解结果}//创建子spanspan,_:= open tracking . startspanfrommontext(CTX," Reduction))//模拟系统执行睡眠(时间。Second/3) //将要跟踪的信息放入tagspan.settag ("request ",请求)span.settag ("reply ",响应)//结束当前span span.finish()返回响应,Err}5.2 gRPC客户端代码main . go:package main import(" context " " fmt " " github . com/gRPC-ecosystem/go-gRPC-middleware/tracking/open tracing " " github . com/open tracing/open tracing-go " " github . com/Uber/jaeger-Client-go/config " " Google . golang . org/gRPC追踪器,关闭。closer,err error){//构造配置信息cfg := & Config。配置{ //设置服务名ServiceName: "ServiceAmount ",//设置采样参数Sampler:& amp config . Sampler config { type:" const ",//全采样模式Param: 1,//开启全采样模式},}//生成新的tracer tracer,closer,Err = CFG . new tracer()if Err = = nil {//设置Tracer为全局单例对象open tracing . Set global Tracer(Tracer)} return } funcmain(){//初始化jaeger并创建新的tracer Tracer,closer,err: = init Jaeger () if err!= nil { panic(fmt。Sprintf("ERROR:无法初始化Jaeger: %v\n ",Err))} defer coller . Close()log . println(" succeeded to init Jaeger ")//创建新的span,关闭span defer span。Finish() //作为父span返回时:= tracer.startspan("计算费用")函数。span:= open tracing . context withspan(context . background(),span)//生成的上下文CTX连接到grpc服务器conn,err: = grpc.dial ("localhost: 8080 ",grpc。WithInsecure(),grpc。with unary interceptor(grpc _ open tracing。unarcyclientinterceptor(grpc _ open tracing。WithTracer(tracer),)))if err!= nil {log。Println(err) return} //创建gRPC计费服务客户端:= account . new account client(conn)//以父span的上下文为参数,调用gRPC微服务checkbalanceresponse,err: = client.checkbalance (CTX,& account。CheckBalanceRequest { Account:" user Account " ,})if err!= nil { log . println(err)return } log . println(checkbalanceresponse)//以父span的上下文为参数调用gRPC微服务还原响应进行推演,err: = client.reduction (CTX,& account。reduction request { Account:" user Account ",Amount: 1,}) if err!= nil { log . println(err)return } log . println(reduction response)}注:本文使用的开发工具是:goland,如果你觉得本文对你有帮助,可以喜欢并关注。


  • 全部评论(0)
资讯详情页最新发布上方横幅
最新发布的资讯信息
【域名/主机/服务器|】qq邮箱提醒在哪里打开(2024-06-04 18:58)
【技术支持|常见问题】1556原创ng8文章搜索页面不齐(2024-05-01 14:43)
【技术支持|常见问题】1502企业站群-多域名跳转-多模板切换(2024-04-09 12:19)
【技术支持|常见问题】1126完美滑屏版视频只能显示10个(2024-03-29 13:37)
【技术支持|常见问题】响应式自适应代码(2024-03-24 14:23)
【技术支持|常见问题】1126完美滑屏版百度未授权使用地图api怎么办(2024-03-15 07:21)
【技术支持|常见问题】如何集成阿里通信短信接口(2024-02-19 21:48)
【技术支持|常见问题】算命网微信支付宝产品名称年份在哪修改?风水姻缘合婚配对_公司起名占卜八字算命算财运查吉凶源码(2024-01-07 12:27)
【域名/主机/服务器|】帝国CMS安装(2023-08-20 11:31)
【技术支持|常见问题】通过HTTPs测试Mozilla DNS {免费源码}(2022-11-04 10:37)

联系我们
Q Q:375457086
Q Q:526665408
电话:0755-84666665
微信:15999668636
联系客服
企业客服1 企业客服2 联系客服
86-755-84666665
手机版
手机版
扫一扫进手机版
返回顶部