调用链跟踪系统-介绍

背景资料

Dapper,大规模分布式系统的跟踪系统

Zipkin

如果要查看zipkin资料,官网的英文文档是最正确的,讲解也很系统;

在阅读文章前,建议先至少看一下Dapper的翻译;

一、介绍

调用链跟踪系统进行了比较大的升级,主要改变有:

  1. 对接zipkin日志标准(仍保留了些许不同);
  2. 使用zipkin的数据库和界面;
  3. 大幅降低对正常业务流程的性能影响;
  4. 将数据压缩后再传递给收集器;
  5. rabbitmq使用单独的数据通道,不再和业务共用一个;
  6. 采用文件日志和mysql记录结合的方式,分别记录调用链的业务数据和性能数据。 业务数据100%记录,性能数据采样记录(5%);
  7. 支持业务数据的上下文透明传输

下面详细讲解系统的构成、设计考量、使用和特点。

二、结构

分布式跟踪系统整体结构

浅绿色的是数据最终落地的地方。

名词解释:临时存储

临时存储究竟是干嘛的呢?在zipkin里,一个Span被分割成两部分,一个是Client/Producer,另一个是Server/Consumer。Span的含义更接近于一次RPC,它横跨了两个服务节点,所以在两个节点分别上报信息,最后再合并成一个Span。

后端收到两部分Span的时间不一样,临时存储就用来存储先到达的Span,等另一半到达后再取出来做合并。

名词解释:收集器

从MQ接收上报的Span,做Span的合并,并存储到持久存储(mysql)

名词解释:压缩

压缩成二进制,再通过MQ传递。实际应用中,是先将Span转换为数组,将key替换成a-z的单字母,再转成json后使用zlib压缩(需要zlib扩展)。

和压缩相关的还有一个叫 msgpack 的东西,但是它需要单独安装PHP扩展,所以放弃了。

三、设计考量

考量一:降低对业务的影响

只在少数地方嵌入跟踪代码。实际操作中,在项目入口(index.php)、rpc请求、输出这三个地方做了埋点。

耗时操作在请求以外执行。我们知道PHP没有异步,但是PHP有个非常有用的函数register_shutdown_function,我们把耗时操作全放里面,这样可以尽量减少对线上业务的影响。如果是fastcgi模式,我们会优先使用fastcgi_finish_request这个函数。http://php.net/manual/zh/function.register-shutdown-function.php#108212

考量二:开关/采样率/消息生产速率控制

一共设计了两个开关(业务日志开关、Span上报开关),默认情况下这两个开关都是开启的。在此基础上,增加了采样率控制,仅当Span上报开关开启,且当前Span需要采样时,Span才会通过MQ传递给后端。业务日志开关控制biz-ztrace日志的记录。

需要注意的时,即便把开关全部关闭,traceid也会生成、传递,但不会有日志记录,也不会有Span上报。

对于消息速率控制,在实际中采用的是“过量丢弃”,阈值是10000。只要队列里的消息超过这个值,即不再接收消息,直接抛弃。

考量三:动态增加消费能力

随着系统扩大,采集的数据增多,动态增强数据的消费能力非常重要。目前的做法是通过加开消费者来实现。之所以能直接增加消费者,是因为它们使用的同一个临时存储,我们只是把消息的消费瓶颈,转移到了临时存储的IO瓶颈上。

想象一下,我们有两个消费者A、B,分别使用两个不同的临时存储,Client端的Span被A接收到,Server端的Span被B接收到,由于它们的临时存储隔开的,A、B都无法做Span的合并!

几乎所有的调用链跟踪系统实现方案,都绕不开这个问题,可能是一个Span被分发到不同处理实例,也可能是同一Trace的不同Span被分发到不同处理实例——这都会带来很多麻烦。

解决方法也很多,比如根据traceid做hash,再转发给不同的后端实例,这样同一个trace下的Span都会被,且只会被转发给同一处理实例。

但是,仅仅做hash是不够的,还必须借助“一致性Hash”算法。下面的例子解释了原因。

假设已经有一个处理实例CA,spanA、SpanB都属于同一个trace。CA已经接收到spanA了,这时我们新增了一个CB(和CA使用不同临时存储),如果hash结果表明spanB应该转发给CB(这完全可能发生),那又会出现CA、CB都无法合并这个Span的情况。

关于一致性Hash,我们后面再讲。

考量四:业务日志、性能日志分开

之所以要分开,是因为业务日志很多(随着采集端的增加,数据增长更多),我们还没处理过这么多的数据。

目前,业务日志记录了$_GET、$_POST、$_SERVER和apiReturn,收集端有seller和api。每天产生的日志共2.5G左右,每月日志总量大概在25G。日志总量和采集端数量呈正相关。

四、使用

下面的例子都有判断$trace_open;,并且使用了 try {} catch () {},这样做是为了减少可能出现的异常,必须要添加。

记录业务日志

业务日志是记录在文件里的,用的最多。

过期数据处理

我们把太久远的数据称为“过期数据”,因为它们被再次使用的概率很低。我们用的最多的是近期的数据,近期数据才是最重要的,业务日志和性能统计数据都适用这个道理。

我们处理过期数据的方式很简单——打包压缩、删除,这是目前能找到的最划算的处理方法。具体处理逻辑:

文件日志:保留一个月的压缩日志,保留一周内的原始日志。
数据库:保留两个月的数据。

global $trace_open;
if ($trace_open) {
    try {
        $tracer = \Tricolor\ZTracker\Core\GlobalTracer::tracer();
        $tracer->log('get', $_GET);
    } catch (\Exception $e) {}
}

记录跟踪日志

跟踪日志会出现在ui里(如果被采样了的话)

global $trace_open;
if ($trace_open) {
    try {
        $tracer = \Tricolor\ZTracker\Core\GlobalTracer::tracer();
        $tracer->currentSpan()->putTag('store_id', (int)$_POST['store_id']);
    } catch (\Exception $e) {}
}

透明传输业务字段(试验性质)

在调用链上游设置一个值,在调用链下游可以获取到。

之所以说是试验性质,是因为设计里有,也有实现,但实际业务里还没使用过。

global $trace_open;
if ($trace_open) {
    try {
        $tracer = \Tricolor\ZTracker\Core\GlobalTracer::tracer();
        $tracer->currentContext()->set('from', 'mamagou');
        // get
        $tracer->currentContext()->get('from');
    } catch (\Exception $e) {}
}

五、特点

  1. 和zipkin的Span比起来,我们的Span结构略有不同。zipkin里的Sampled字段,在我们这里对应Decision字段,Decision字段除了记录是否采样,还记录了log开关和report开关。

  2. 数据库、UI使用zipkin,减少了一些开发量。zipkin的Span设计能适应较多的采集场景,比如单向数据传递、黑盒模式的远端节点(调用数据库时,数据库就是一个黑盒模型)。

  3. 和淘宝类似,加了业务字段透传功能,业务日志和跟踪日志分开。

postman 实现API自动化测试

编 写:袁 亮
时 间:2017-01-16
说 明:postman 实现API自动化测试


一. 实现目的

  1. 接口开发调试工具
  2. 自动化测试
  3. 接口用例团队内共享
  4. 降低接口文档编写成本

二. 实现流程

  1. 团队使用同一份文档
    测试文档存入代码仓库
    使用前从代码仓库拉取导入
    修改完之后,重新导出,并更新代码仓库
    ps:后续为了降低代码层级,可以将API分成很多个collection,前期先合并成同一个

  2. 使用工具产生文档
    postman:界面gui模式
    newman:服务端cli模式

三. postman产生文档

  1. 通用层实现 在collection上做
    • 所有接口都先放在同一个collection,后期根据模块拆分
      方便在同一个collection上实现一些通用逻辑
    • 环境变量支持
      appid: 10101
      appsecret: 8e2160ec2b07f1faca9055be530bf09d
      host: http://api.shop.ci123.com/
      maxtime: 300
    • pre-request中实现签名
    • tests中实现统一的校验
      http状态码 200
      返回json,并且需要包含state和mess字段
      接口超时时间
      签名出错
  2. 目录层级规范
    • 根据模块不同,创建不同的文件夹
    • gui展示的原因,目录层级最多3层
    • 每一个接口,都是一个文件夹 (所以实质上除了collection只有2层目录)
    • 最底层的文件夹下,所有请求都是同一个接口的不同用例
  3. 具体实例实现
    • url地址
      {{host}}/Item/getSkuByItemId?appid={{appid}}
    • post参数增加两行
      expire {{expire}}
      mdstr {{mdstr}}
      ps:因为request只读的原因,不能追加,只能在每个地方都写一次这个
    • 填入其他请求参数,构造每一种apiReturn的情况
      一个用例只实现一个对应apiReturn,这个return可能有多种情况,放在examples里
    • 每个用例,必须增加tests,来告知是否通过
      除了最终成功的那个请求,其他请求的tests主要就是校验state状态码即可
    • 执行成功的用例校验
      写请求:一般是校验对应的id是否正确,比如订单id,商品id等
      读请求:解析对应的json数据格式,是否包含什么样的字段等等
      ps:后续谁有空可以看下,是否可以自己定义模板,现在看到的那些模板只能选择使用,不能自己创建
  4. 开发调试规范
    • 从代码仓库把文档导入到postman
    • 接口编写过程中,使用这个来进行调试,所有情况必须测到
      有多少个state返回,就最少有多少个接口用例
    • 接口全部写完之后,必须通过runner来确保所有用例全部跑通
      不要出现改到后面,前面的跑过的用例又跑不了
    • 写完之后,把postman里的数据导出到git仓库中

四、自动化测试 todo

  1. 安装newman环境
  2. 定时或者在git的钩子里设置
  3. 拉取对应的文档,执行测试
  4. 测试结果入库
  5. 展示报警
    工作台展示
    邮件、短信报警

五、postman常用操作

  1. 设置
    皮肤设置
    返回值解析设置:json auto的时候,没有自动识别是json
  2. 环境变量设置与使用
  3. 数据导入导出
    collection导入导出
    整体导入导出
  4. 复制修改
    用例复制,文件夹复制等
  5. examples使用
    可以配合做mock server
  6. runner使用
  7. console控制台调试
  8. 搜索
  9. API文档发布
    免费版有限制,可以大概看看
  10. 官方文档,可以快速看一遍
  11. 错误提示
    特别是全局变量中的
  12. runner里执行的时候,一定要注意request的是要保存里的,不然更改了是无效的
    send本身是直接起效
  13. ctrl + s保存修改
  14. Codeception

Elk 6.1 安装使用说明

ELK 不是一款软件,而是 Elasticsearch、Logstash 和 Kibana 三种软件产品的首字母缩写。这三者都是开源软件,通常配合使用,而且又先后归于 Elastic.co 公司名下,所以被简称为 ELK Stack。根据 Google Trend 的信息显示,ELK Stack 已经成为目前最流行的集中式日志解决方案。

架构

Logstash

介绍

数据收集引擎:数据存储与数据流。它支持动态的从各种数据源搜集数据,并对数据进行过滤、分析、丰富、统一格式等操作,然后存储到用户指定的位置;

安装

1、 官方教程
2、 windows下安装Logstash

效果图

注意事项

1、windows下需要使用NSSM

Elasticsearch

安装

说明:Elastic 需要 Java 8 环境,注意要保证环境变量JAVA_HOME正确设置。
1、下载最新Elasticsearch版本,解压到指定目录。
2、在Unix上运行bin/elasticsearch或者在Windows上运行bin\elasticsearch.bat
3、打开:http://localhost:9200/

效果图

注意事项:

  1. 启动内存不足
# vi ${elasticsearch_HOME}/config/jvm.options
#-Xms2g
#-Xmx2g
-Xms512m
-Xmx512m
  1. 无法以root权限启动
# groupadd es
# useradd es -g es -p es
# chown es:es ${elasticsearch_HOME}/
# sudo su es
# ./bin/elasticsearch

安装elasticsearch-head

git clone git://github.com/mobz/elasticsearch-head.git
cd elasticsearch-head
npm install
npm run start
open http://localhost:9100/

谷歌插件安装链接

说明

Kibana

介绍

Kibana是个数据分析和可视化平台。通常与 Elasticsearch 配合使用,对其中数据进行搜索、分析和以统计图表的方式展示;

安装

kibana官方文档

效果图

注意事项

1、 需要cmd执行,直接运行.bat无效
2、 Logstash 6.1.1 issue with setup.bat file "could not find jruby in"
在7.0版本修复,下载master文件,并替换bin目录文件接口。

参考资料
1. Kibana入门教程
2. Logstash 最佳实践
3. kibana官方文档
4. ELK+Filebeat 集中式日志解决方案详解