zipkin trace数据结构说明(四)

前言

使用zipkin做二次开发,第一步是要对zipkin整体有一个了解,能够简单的搭建DEMO跑一跑,前面两篇文章,就是做这个用的,接下来最重要的一点,就是了解他存储在elasticsearch的数据结构。

span结构

zipkin存储span的话,存在elasticsearch里面,每一天的数据自动创建一个index, 格式如下

zipkin:span-2018-08-06 
zipkin:span-2018-08-07  # 2018-08-07这一天的span都存储在这个index下面

一个span的数据结构如下

{
  "_index": "zipkin:span-2018-08-07",
  "_type": "span",
  "_id": "AWUSkiT_lG0UQ3Osck2S",
  "_version": 1,
  "_score": 1,
  "_source": {
    "traceId": "6c3c748ff257f23b",
    "duration": 2928879,
    "localEndpoint": {
      "ipv4": "10.208.204.119",
      "port": 7900,
      "serviceName": "sleuthconsumer"
    },
    "timestamp_millis": 1533614872966,
    "kind": "SERVER",
    "name": "http:/consumer",
    "id": "6c3c748ff257f23b",
    "timestamp": 1533614872966000,
    "parentId": "6c3c748ff257f23b",
    "tags": {
      "mvc.controller.class": "HomeController",
      "mvc.controller.method": "service1",
      "lc": "hystrix",
      "spring.instance_id": "DESKTOP-CBSVPL2:sleuthConsumer:7900",
      "thread": "hystrix-sleuthConsumer2-1"
    }
  }
}

这个是从elasticsearch里面拷贝出来的数据结构,其实主要看下面这一块就好了

{
    "traceId": "6c3c748ff257f23b",
    "duration": 2928879,
    "localEndpoint": {
      "ipv4": "10.208.204.119",
      "port": 7900,
      "serviceName": "sleuthconsumer"
    },
    "timestamp_millis": 1533614872966,
    "kind": "SERVER",
    "name": "http:/consumer",
    "id": "6c3c748ff257f23b",
    "timestamp": 1533614872966000,
    "parentId": "6c3c748ff257f23b",
    "tags": {
      "mvc.controller.class": "HomeController",
      "mvc.controller.method": "service1",
      "lc": "hystrix",
      "spring.instance_id": "DESKTOP-CBSVPL2:sleuthConsumer:7900",
      "thread": "hystrix-sleuthConsumer2-1"
    }
  }

traceId : 同一次http请求的traceId都是一样的,他表示了一个调用链的产生,同一个调用链里面的span的traceId都是一样的

duration : 耗时,一个span的产生表示一次调用请求。duration 就是这次请求从接收到所耗费的时间 ,单位: 微秒

localEndpoint : 本地服务器的网络信息

ipv4 : 本地服务器IP

port : 本地服务端口

serviceName: 本地服务名

timestamp_millis : 本次请求的开始时间,单位: 毫秒

kind : span的类型,有server和client的区分。

name : 调用的本服务的接口地址

id : spanID

parentId : 父节点ID,用来关联调用关系

tags : 针对这个span所打的标签,里面的内容具有不确定性。

dependency结构

zipkin存储调用链的话,存在elasticsearch里面,每一天的调用链分别用一个index存储, 格式如下

zipkin:span-2018-08-06 
zipkin:span-2018-08-07  # 2018-08-07这一天的调用链都存储在这个index下面
{
  "_index": "zipkin:dependency-2018-08-07",
  "_type": "dependency",
  "_id": "sleuthconsumer|sleuthconsumer2",
  "_version": 3,
  "_score": 1,
  "_source": {
    "id": "sleuthconsumer|sleuthconsumer2",
    "parent": "sleuthconsumer",
    "child": "sleuthconsumer2",
    "callCount": 56,
    "errorCount": 4
  }
}

id : 由parent和child构成

parent : 调用开始的服务名

child : 被调用的服务名

callCount : 调用次数

errorCount : 调用的错误次数

以上说的是存储在数据库最原始的数据结构,下面来讲一下,zipkin在程序里面已经组装好了的数据结构。

完整trace数据结构

调用链如下:

  1. sleuthconsumer : http:/consumer
  2. 在consumer 方法中,
  3. 调用sleuthprovider: http:/provider
  4. 调用sleuthconsumer2: http:/consumer2
    1. sleuthprovider: http:/provider

方法的调用层次如上,界面的生成的数据结构如下 , 前端返回的json数据,总共生成了四个span标签,表示四个http请求。

[
  {
    "traceId": "aac7faa56867fbc3", # traceId , 表示同一次请求
    "id": "aac7faa56867fbc3",   # 请求的第一个span,ID 和traceId相同
    "name": "http:/consumer",  # 访问的接口
    "timestamp": 1533293762448000,  # 请求开始时间 ,单位微秒
    "duration": 30060, # 整个请求的耗时,根节点的耗时,其实就是整个调用链完成的耗时时间
    "annotations": [
      {
        "timestamp": 1533293762448000,  # 服务接收到请求的时间,也就是请求开始时间
        "value": "sr",   # service receiverd 
        "endpoint": {  # 服务本地的网络信息,应用名,IP,端口
          "serviceName": "sleuthconsumer",
          "ipv4": "10.208.204.119",
          "port": 7900
        }
      },
      {
        "timestamp": 1533293762478060,  #整个调用链的结束时间
        "value": "ss", # service  send 虽然这个地方显示的是service send , 但是实际上是整个调用链的结束
        "endpoint": {   # 服务本地的网络信息,应用名,IP,端口
          "serviceName": "sleuthconsumer",
          "ipv4": "10.208.204.119",
          "port": 7900
        }
      }
    ],
    "binaryAnnotations": [  # 服务的一系列标签信息
      {
        "key": "mvc.controller.class",
        "value": "HomeController",
        "endpoint": {
          "serviceName": "sleuthconsumer",
          "ipv4": "10.208.204.119",
          "port": 7900
        }
      }
      # 省略剩余的标签
    ]
  },
  {
    "traceId": "aac7faa56867fbc3", # 调用链全局公用一个traceID
    "id": "4aab338d1c5bcc52",  # spanID
    "name": "http:/provider",  # 请求的URI
    "parentId": "aac7faa56867fbc3", # 他的上级请求ID,sleuthconsumer 的ID,表示请求是从sleuthconsumer 发过来的
    "timestamp": 1533293762450000, # 请求的开始时间,从 sleuthconsumer 发出请求开始算起
    "duration": 4000,  # sleuthprovider 服务provider接口的耗时
    "annotations": [
      {
        "timestamp": 1533293762450000,  # sleuthconsumer 发出调用http:/provider的时间
        "value": "cs", # client send 
        "endpoint": { # 服务本地的网络信息,应用名,IP,端口
          "serviceName": "sleuthconsumer",
          "ipv4": "10.208.204.119",
          "port": 7900
        }
      },
      {
        "timestamp": 1533293762452000, # sleuthprovider 接收到请求的时间
        "value": "sr", # service receive
        "endpoint": { # 服务本地的网络信息,应用名,IP,端口
          "serviceName": "sleuthprovider",
          "ipv4": "10.208.204.119",
          "port": 7902
        }
      },
      {
        "timestamp": 1533293762453000, # sleuthprovider 请求完成,发出返回值的时间
        "value": "ss", # service send 
        "endpoint": {
          "serviceName": "sleuthprovider",
          "ipv4": "10.208.204.119",
          "port": 7902
        }
      },
      {
        "timestamp": 1533293762454000, # sleuthconsumer接收到 sleuthprovider 的返回值的时间, 至此,这个调用完成,总共耗时4毫秒
        "value": "cr",  # client receive 
        "endpoint": { 
          "serviceName": "sleuthconsumer",
          "ipv4": "10.208.204.119",
          "port": 7900
        }
      }
    ],
    "binaryAnnotations": [  # 标签信息,列出了跟本次请求相关的标签
      {
        "key": "http.host",
        "value": "localhost",
        "endpoint": {
          "serviceName": "sleuthconsumer",
          "ipv4": "10.208.204.119",
          "port": 7900
        }
      }
      # 省略剩余的标签
    ]
  },
  {
    "traceId": "aac7faa56867fbc3", # 调用链全局公用一个traceID
    "id": "66193640803fca1b", # sleuthconsumer 请求 sleuthconsumer2 这次请求的spanId
    "name": "http:/consumer2", # 接口URI
    "parentId": "aac7faa56867fbc3", # 表示从哪个请求发过来的,aac7faa56867fbc3 是sleuthconsumer的ID
    "timestamp": 1533293762455000, # 请求的开始时间,从sleuthconsumer发出请求的时候开始算起 ,单位: 微秒
    "duration": 22000,  # 本次请求从开始到完成的耗费时间 ,单位微秒
    "annotations": [
      {
        "timestamp": 1533293762455000, # sleuthconsumer发出请求的时间
        "value": "cs", # client send 
        "endpoint": { #sleuthconsumer的应用信息
          "serviceName": "sleuthconsumer",
          "ipv4": "10.208.204.119",
          "port": 7900
        }
      },
      {
        "timestamp": 1533293762457000, # sleuthconsumer2接收到请求的时间 
        "value": "sr", # service receive 
        "endpoint": { #sleuthconsumer2的本地应用信息
          "serviceName": "sleuthconsumer2",
          "ipv4": "10.208.204.119",
          "port": 7901
        }
      },
      {
        "timestamp": 1533293762477000, #sleuthconsumer2请求处理完成,发出响应结果的时间
        "value": "ss",  # service send 
        "endpoint": {
          "serviceName": "sleuthconsumer2",
          "ipv4": "10.208.204.119",
          "port": 7901
        }
      },
      {
        "timestamp": 1533293762477000, # sleuthconsumer 收到返回值的时间,此时表示一个请求的完成
        "value": "cr",
        "endpoint": {
          "serviceName": "sleuthconsumer",
          "ipv4": "10.208.204.119",
          "port": 7900
        }
      }
    ],
    "binaryAnnotations": [ # 标签信息,列出了跟本次请求相关的标签
      {
        "key": "http.host",
        "value": "localhost",
        "endpoint": {
          "serviceName": "sleuthconsumer",
          "ipv4": "10.208.204.119",
          "port": 7900
        }
      }
      # 省略剩余的标签
    ]
  },
  {
    "traceId": "aac7faa56867fbc3", # 调用链全局公用一个traceID
    "id": "dd53905167c2ec13",  # sleuthconsumer2 调用 sleuthprovider 产生的spanId
    "name": "http:/provider",  # 本次请求的接口URI
    "parentId": "66193640803fca1b", # 他的上级节点ID,也就是哪个span调用的它, 此处表示sleuthconsumer2 的span
    "timestamp": 1533293762458000, # sleuthconsumer2 发出http:/provider请求的开始时间
    "duration": 17000, # 请求开始到结束的耗时时间
    "annotations": [ 
      {
        "timestamp": 1533293762458000, # sleuthconsumer2 发出http:/provider请求的开始时间
        "value": "cs", # client send 
        "endpoint": { # sleuthconsumer2的应用信息
          "serviceName": "sleuthconsumer2",
          "ipv4": "10.208.204.119",
          "port": 7901
        }
      },
      {
        "timestamp": 1533293762471000, # sleuthprovider收到请求的时间
        "value": "sr", # service receive 
        "endpoint": { # sleuthprovider本地的应用信息
          "serviceName": "sleuthprovider",
          "ipv4": "10.208.204.119",
          "port": 7902
        }
      },
      {
        "timestamp": 1533293762475000, # sleuthprovider请求处理完成,返回响应结果的时间
        "value": "ss",  # service send 
        "endpoint": {
          "serviceName": "sleuthprovider",
          "ipv4": "10.208.204.119",
          "port": 7902
        }
      },
      {
        "timestamp": 1533293762475000, # sleuthconsumer2 收到请求的相应结果的时间 ,请求至此结束
        "value": "cr", # client receive 
        "endpoint": {
          "serviceName": "sleuthconsumer2",
          "ipv4": "10.208.204.119",
          "port": 7901
        }
      }
    ],
    "binaryAnnotations": [
      {
        "key": "http.host",
        "value": "localhost",
        "endpoint": {
          "serviceName": "sleuthconsumer2",
          "ipv4": "10.208.204.119",
          "port": 7901
        }
      }
      #省略剩余的标签
    ]
  }
]

以上所有和时间相关的,单位都是微秒

一个请求的完成,有四个比较重要的概念:

cs - Client Send : 客户端已经提出了请求。这就设置了跨度的开始。

sr - Server Receive: 服务器已收到请求并将开始处理它。这与CS之间的差异将是网络延迟和时钟抖动的组合。

ss - Server Send: 服务器已完成处理,并将请求发送回客户端。这与SR之间的差异将是服务器处理请求所花费的时间

cr - Client Receive : 客户端已经收到来自服务器的响应。这就设置了跨度的终点。当记录注释时,RPC被认为是完整的。

sharedCode源码交流群,欢迎喜欢阅读源码的朋友加群,添加下面的微信, 备注”加群“ 。

这里写图片描述

展开阅读全文

没有更多推荐了,返回首页