新手问题 OpenTracing——概念与目标

cdh0805010118 · 2018年06月28日 · 405 次阅读

OpenTracing 概念和目标

随着数据爆炸式增长,单体应用已完全不能满足业务需要,分布式服务,特别是微服务越来越成为趋势。达到服务高可用的 N 个 9,以及服务出现问题后定位问题,也变得越来越困难。APM(Application Performance Management) 中有三大块:trace、logging 和 metrics,这三个支撑后续运维提供业务支撑的稳定性、运营人员问题跟踪、以及反馈给运营产品的建议。这三大块有交集。 分布式跟踪系统主要是讲 Trace 部分。

在 OpenTracing 没有出现之前,主要依据 Google 的 Dapper 论文和一些厂商自己的想法,设计的 trace 系统。没有太多规范,这样导致的一个大问题是,业务方采用一个厂商的 trace 系统,则如果因为一些原因,想换另一个 trace 系统投入生产,则如果 trace 在设计方面的侵入性、或者 rpc 组件、存储访问组件植入,则改造成本无法想象。如果有一个标准可以规范各大厂商在 rpc 组件,存储组件等封装中,注入 trace 系统是标准化的,则只需要改造与业务无关的系统部分,例如 trace 的 collect、storage 和 dashboard 部分,就可以实现。因此,大名鼎鼎的 CNCF 机构设计了分布式跟踪系统标准——OpenTracing

OpenTracing 通过提供与平台无关、厂商无关的 API,使得开发人员能够方便的添加(或者更换)分布式追踪系统的实现, 同时 OpenTracing 提供了用于运营支撑系统的和针对特定平台的辅助程序库,可在OpenTracing找到。

Trace 系统本质理解

  1. 一个 web 请求打到端口,自带 traceid 或者 gateway 生成 traceid, 然后在响应到外部的整个链路都带有这个 traceid,那么根据这个 traceid,我们就能搜索到整个链路。
  2. 进一步地,想知道 traceid 经过的服务列表、存储、以及所花费的时长等,调用链路的服务拓扑图。这就需要 spanid 和 rpc 请求上下文携带信息等
  3. 最终 Trace 系统要反馈给开发业务人员、产品运营人员并作出有价值的决策,这就需要借助 dashboard 丰富的报表统计数据。

一个 traceid 所经过的链路,一定是有向无环图

下面的两幅图:

  1. 一个 web 请求所经过的所有 rpc 服务,表示该链路的拓扑图,侧重微服务之间的拓扑关系。 调用链路
  2. 已发现问题和时间序列的角度,看各个微服务上下文执行时间的花费。 时间维度的链路

OpenTracing 设计理念

OpenTracing 最重要的作用是,当你的系统按照标准规范设计后,增加一个分布式跟踪系统变得非常简单。通常不同分布式跟踪系统产品如果遵循了 OpenTracing 标准规范,则更换 trace 产品时,只需要初始化服务时,指定 Collector 服务、存储服务、Dashboard 服务和初始化全局 Trace 实例,就 ok 了。其他的使用 OpenTracing 标准 interface 中的方法就行了,因为 Trace 产品已经实现了这些 interface。

例如:初期时,使用 AppDash 作为分布式跟踪系统的 DEMO

func main(){
    store := appdash.NewMemoryStore()
    // 初始化collector客户端,以及对接collector的后端存储服务
    // notice:这里直接在服务本身内部初始化collector,是不合理的。因为最好存储服务和collector服务是独立的两个分布式服务。因为appdash就是小业务量的服务,所以都是在本地搜集和存储
    cs:=appdash.NewServer(l, appdash.NewLocalCollector(store))
    // dashboard UI, ui 也应该是一个独立的查询服务
    tapp, err:=  traceapp.New(nil, appdashURL)
    // 初始化全局tracer, 同时指定collector服务的rpc端口服务。
    // 也即指定全局tracer和agent, 只是appdash比较简单
    tracer:= appdashot.NewTracer(appdash.NewRomoteCollector(collectorPort))
    opentraceing.InitGlobalTracer(tracer)
    // 初始化服务本身
    // ...
}

当业务量爆发时, 觉得 Appdash 无法适应业务需要,需要替换其他的 Trace 产品方案,如:Zipkin。在原来 Appdash 的基础上,替换掉 func main 中的 collector 服务、存储服务以及初始化全局 Tracer,其他不变, DEMO 如下:

func main(){
    // 初始化collector服务的client端
    collector, err:= zipkin.NewKafkaCollector("ZIPKIN_ADDR")
    // 初始化全局tracer
    tracer, err := zipkin.NewTracer(
        zipkin.NewRecorder(collector, false, ":8000", "example"),
    )
    opentracing.InitGlobalTracer(tracer)
}

从这两个例子,我们可以看到若要在分布式业务各个微服务本身,替换掉 Trace 系统,则只需要告诉业务方的全局初始化 Tracer 方法,以及对应的 Collector 服务连接方式,其他的都不关心,因为其他的,比如:Span 的创建,微服务之间的 Trace 关联(通过上下文)等都是通过 OpenTracing 的标准库做到的,类似于多态。

参考资料

opentracing 文档中文版 ( 翻译 ) 吴晟

更多原创文章干货分享,请关注公众号
  • 加微信实战群请加微信(注明:实战群):gocnio
暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册