内容简介:现代互联网服务通常是使用复杂的、大规模的分布式系统来实现的。这些应用程序往往是由大量的软件模块构建的,而且这些软件模块可能由不同的团队开发,可能使用不同的编程语言,并且可以跨多个物理设施跨越数千台机器。在这种环境中,帮助理解系统行为和性能问题推理的工具是非常宝贵的。微服务架构是一个分布式架构,实际开发中,我们按照业务要求划分服务单元,一套系统往往会由多个业务单元构成。在这个场景中,一个请求可能需要经历多个业务单元的处理才能完成响应,如果出现了错误或异常,很难定位。为了解决这个问题,谷歌开源了分布式链路追踪组
现代互联网服务通常是使用复杂的、大规模的分布式系统来实现的。这些应用程序往往是由大量的软件模块构建的,而且这些软件模块可能由不同的团队开发,可能使用不同的编程语言,并且可以跨多个物理设施跨越数千台机器。在这种环境中,帮助理解系统行为和性能问题推理的 工具 是非常宝贵的。
微服务架构是一个分布式架构,实际开发中,我们按照业务要求划分服务单元,一套系统往往会由多个业务单元构成。在这个场景中,一个请求可能需要经历多个业务单元的处理才能完成响应,如果出现了错误或异常,很难定位。
为了解决这个问题,谷歌开源了分布式链路追踪组件Drapper,并发表论文 《Dapper, a Large-Scale Distributed Systems Tracing Infrastructure》 介绍了Drapper的设计思想。在该论文的影响下,Twitter设计、研发并开源了分布式链路追踪系统Zipkin。
Zipkin
Zipkin是一个分布式跟踪系统,它可以帮助收集时间数据,以此解决在微服务架构下的延迟问题。它同时提供了分布式系统时间数据的收集和查询功能。Zipkin的架构如下图所示:
通过架构图可知,Zipkin由Collector、Storage、API、UI共4个组件构成,Reporter由应用系统提供并收集数据,其工作原理大概如下:
- 在应用程序中嵌入追踪器(Tracer),它使用Span记录应用程序动作的时间和元数据信息;
- Reporter把Span发送至Zipkin的数据收集器Collector;
- Collector通过Storage组件把数据存储至数据库;
- UI组件通过API接口查询追踪数据并显示;
Zipkin通过Trace结构表示对一次请求的跟踪,一次请求由若干服务处理,每个服务生成一个Span,同一请求的Span之间存在关联关系,在UI组件中以树形式展示。Span的主要数据模型如下所示:
字段 | 类型 | 说明 |
---|---|---|
traceId | string | 随机生成,用于唯一标识一个追踪信息,所有的span都包含此信息。 |
name | string | span的名称,可使用method命名,在UI组件中显示 |
parentId | string | 父级span的编号,若为空,则表示为根span |
id | string | span的编号 |
timestamp | integer | span创建的时间 |
duration | integer | span持续时间 |
annotations | Annotation | 关联一个事件,用时间戳解释延迟信息 |
tags | Tags | span的标签,用于搜索、显示和分析 |
Zipkin官方已经推出各种常见语言的支持,如C#、 go 、 Java 、JavaScript、 Ruby 、Scala、PHP,另外社区也贡献了 Python 、C/C++、 Lua 等语言的支持。
实战演练
Step-0:准备工作
本文将延续“go-kit微服务系列”,使用go-kit集成Zipkin实现算术运算服务的链路追踪,这里将包含两个部分:
gateway
go-kit在 tracing
包中默认添加了 zipkin
的支持,所以集成工作将会比较轻松。在开始之前,需要下载以下依赖:
# zipkin官方库 go get github.com/openzipkin/zipkin-go # 下面三个包都是依赖,按需下载 git clone https://github.com/googleapis/googleapis.git [your GOPATH]/src/google.golang.org/genproto git clone https://github.com/grpc/grpc-go.git [your GOPATH]/src/google.golang.org/grpc git clone https://github.com/golang/text.git [your GOPATH]/src/golang.org/text 复制代码
本次演练使用 arithmetic_consul_demo
中的 gateway
和 register
两个服务,复制该目录并重命名为 arithmetic_trace_demo
,删除 discover
。
Step-1:Docker启动Zipkin
- 打开文件
docker/docker-compose.yml
,在consul的基础上增加zipkin配置信息(使用官方推荐的openzipkin/zipkin
),最终内容如下所示:
version: '2' services: consul: image: progrium/consul:latest ports: - 8400:8400 - 8500:8500 - 8600:53/udp hostname: consulserver command: -server -bootstrap -ui-dir /ui zipkin: image: openzipkin/zipkin ports: - 9411:9411 复制代码
- 打开终端切换至
docker
目录,执行以下命令,启动consul和zipkin。
sudo docker-compose up 复制代码
- 启动成功后,打开浏览器输入
http://localhost:9411
检查是否启动成功。
Step-2:修改gateway
gateway
将作为链路追踪的第一站和最后一站,我们需要截获到达 gateway
的所有请求,记录追踪信息。 gateway
作为外部请求的服务端,同时作为算术运算服务的客户端(反向代理内部实现)。
创建追踪器
结合Zipkin的架构图,需要在应用程序中集成Reporter组件,我们使用官方提供的go包。代码如下(默认设置了zipkin的url):
// 创建环境变量 var ( // consul环境变量省略 zipkinURL = flag.String("zipkin.url", "http://192.168.192.146:9411/api/v2/spans", "Zipkin server url") ) flag.Parse() var zipkinTracer *zipkin.Tracer { var ( err error hostPort = "localhost:9090" serviceName = "gateway-service" useNoopTracer = (*zipkinURL == "") reporter = zipkinhttp.NewReporter(*zipkinURL) ) defer reporter.Close() zEP, _ := zipkin.NewEndpoint(serviceName, hostPort) zipkinTracer, err = zipkin.NewTracer( reporter, zipkin.WithLocalEndpoint(zEP), zipkin.WithNoopTracer(useNoopTracer), ) if err != nil { logger.Log("err", err) os.Exit(1) } if !useNoopTracer { logger.Log("tracer", "Zipkin", "type", "Native", "URL", *zipkinURL) } } 复制代码
为所有请求增加链路追踪
我们使用的传输方式为http,可以使用 zipkin-go
提供的 middleware/http
包,它采用装饰者模式把我们的 http.Handler
进行封装,然后启动监听即可,代码如下所示:
//创建反向代理 proxy := NewReverseProxy(consulClient, zipkinTracer, logger) tags := map[string]string{ "component": "gateway_server", } handler := zipkinhttpsvr.NewServerMiddleware( zipkinTracer, zipkinhttpsvr.SpanName("gateway"), zipkinhttpsvr.TagResponseSize(true), zipkinhttpsvr.ServerTags(tags), )(proxy) 复制代码
反向代理设置
gateway
接收请求后,会创建一个 span
,其中的 traceId
将作为本次请求的唯一编号, gateway
必须把这个 traceId
“告诉”算术运算服务,算术运算服务才能为该请求持续记录追踪信息。
在 ReverseProxy
中能够完成这一任务的就是 Transport
,我们可以使用 zipkin-go
的 middleware/http
包提供的 NewTransport
替换系统默认的 http.DefaultTransport
。代码如下所示:
// NewReverseProxy 创建反向代理处理方法 func NewReverseProxy(client *api.Client, zikkinTracer *zipkin.Tracer, logger log.Logger) *httputil.ReverseProxy { //创建Director director := func(req *http.Request) { //省略 } // 为反向代理增加追踪逻辑,使用如下RoundTrip代替默认Transport roundTrip, _ := zipkinhttpsvr.NewTransport(zikkinTracer, zipkinhttpsvr.TransportTrace(true)) return &httputil.ReverseProxy{ Director: director, Transport: roundTrip, } } 复制代码
这一步很关键!若不设置,会导致整个链路追踪不完整。为了解决这个问题,花费了不少时间,最后还是通过 zipkin-go
的 README 解开了疑惑。
完成以上过程,就可以编译运行了。
Step-3:修改算术服务
创建追踪器
这一步与 gateway
的处理方式一样,不再描述。
追踪Endpoint
go-kit提供了对 zipkin-go
的封装,可直接调用中间件 TraceEndpoint
对算术运算服务的两个 Endpoint
进行设置。代码如下:
endpoint := MakeArithmeticEndpoint(svc) endpoint = NewTokenBucketLimitterWithBuildIn(ratebucket)(endpoint) //添加追踪,设置span的名称为calculate-endpoint endpoint = kitzipkin.TraceEndpoint(zipkinTracer, "calculate-endpoint")(endpoint) //创建健康检查的Endpoint healthEndpoint := MakeHealthCheckEndpoint(svc) healthEndpoint = NewTokenBucketLimitterWithBuildIn(ratebucket)(healthEndpoint) //添加追踪,设置span的名称为health-endpoint healthEndpoint = kitzipkin.TraceEndpoint(zipkinTracer, "health-endpoint")(healthEndpoint) 复制代码
追踪Transport
- 修改
transports.go
的MakeHttpHandler
方法。增加参数zipkinTracer
,然后在ServerOption中设置追踪参数。代码如下:
// MakeHttpHandler make http handler use mux func MakeHttpHandler(ctx context.Context, endpoints ArithmeticEndpoints, zipkinTracer *gozipkin.Tracer, logger log.Logger) http.Handler { r := mux.NewRouter() zipkinServer := zipkin.HTTPServerTrace(zipkinTracer, zipkin.Name("http-transport")) options := []kithttp.ServerOption{ kithttp.ServerErrorLogger(logger), kithttp.ServerErrorEncoder(kithttp.DefaultErrorEncoder), zipkinServer, } //省略代码 return r } 复制代码
- 在
main.go
中调用MakeHttpHandler
。
//创建http.Handler r := MakeHttpHandler(ctx, endpts, zipkinTracer, logger) 复制代码
至此,所有的代码修改工作已经完成,下一步就是启动测试了。
Step-4:运行&测试
确保 Consul
、 Zipkin
、 gateway
、 register
四个服务已经正常运行,然后使用Postman进行请求测试(与之前类似,为了方便查看数据,可多点几次)。
在浏览器中打开 http://localhost:9411
,点击“Find Traces”按钮,即可看到如下界面。详细显示了每个请求执行的时间、span的数量、途径的服务名称等信息。
打开第一个请求,进入该请求的链路追踪界面,如下图所示。
- 上半部分显示:,该请求的执行时间为10.970毫秒、途径的服务为2个、链路深度为3、span数量为3。
- 下半部分显示:以树形方式显示span,直观展示每个span的途径服务、执行时间、span名称等信息。
通过该界面,我们可以知道请求链路中比较耗时的环节为 gateway-service
。原因是:每次请求过来,程序都要到Consul中查询服务实例,动态创建服务地址。
另外,点击树形结构的每个span,可以查看span的描述信息,这里不再展开描述。
总结
本文使用go-kit的 tracing
组件和 zipkin-go
包,为网关服务和算术运算服务增加了链路追踪功能,以实例方式演示了在go-kit中集成 Zipkin
的方式。示例比较简单,希望对你有用!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 微服务全链路异步化实践
- Go 微服务全链路跟踪详解
- 微服务架构自动化测试全链路设计
- sleuth和zipkin微服务里的链路跟踪
- lar-trace为服务之间调用提供链路追踪
- Spring Cloud实战系列(七) - 服务链路追踪Spring Cloud Sleuth
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Google 广告优化与工具
宫鑫 / 电子工业出版社 / 2010-7 / 60.00元
《Google 广告优化与工具》全面地阐述了Google AdWords这个高效广告投放平台的各方面内容,包括Google广告的渠道组成、质量得分、关键词和广告语策略、后期跟踪机制以及各种辅助工具的使用等。引导读者一步步建立一个强大的Google搜索引擎营销投放策略。本书案例丰富、知识面广且层次清晰,适用于各个层次的搜索引擎营销优化人员,不论是电商企业的领导人、工作在账户优化第一线的具体操作者、营......一起来看看 《Google 广告优化与工具》 这本书的介绍吧!