「Java分享客栈」随时用随时翻:微服务链路追踪之zipkin搭建

前言

微服务治理方案中,链路追踪是必修课,SpringCloud的组件其实使用很简单,生产环境中真正令人头疼的往往是软件维护,接口在微服务间的调用究竟哪个环节出现了问题,哪个环节耗时较长,这都是项目上线后一定会遇到的问题,为了解决这些问题链路追踪便应运而生了。


主流方案

1)、SkyWalking:这应该是目前最主流的方案了,我所在公司今年的新项目就开始使用这个,效果确实很显著,功能强大,最重要还是国产的,后面不用看了我们支持国产吧!开个玩笑哈哈,其实这个框架也有缺点,就是稍微有点重,比较适合稍大一点的项目,但可预见后面几年都是最受欢迎的方案;

2)、Zipkin:这个是老牌链路追踪方案,已经被非常多项目验证过实用性,相比较于SkyWalking,我个人更喜欢这个框架,因为更轻量级,安装也非常简单,是中小规模的微服务项目首选方案。


用法

1、zipkin环境搭建

官方提供了docker版本,十分简单。也可以下载编译好的zipkin.jar来运行,是springboot项目。

官网:https://zipkin.io/pages/quickstart.html

1)、启动

默认端口号启动zipkin服务,默认端口9411.

java -jar zipkin.jar

2)、指定端口号

java -jar zipkin.jar --server.port=8080

3)、指定访问RabbitMQ

java -jar zipkin.jar --zipkin.collector.rabbitmq.addresses=127.0.0.1

4)、启动效果
111.png


2、SpringCloud整合zipkin

springcloud其它基础依赖包引入这里省略,直接模拟场景。

会员服务:zipkin_member

订单服务:zipkin_order

消息服务:zipkin_msg

过程:会员服务调用订单服务,订单服务调用消息服务。

1)、引入依赖
<!-- zipkin -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
2)、application.yml配置

注意事项:

a)、加上服务名,RestTemplate调用时会用到;

b)、加上zipkin服务端地址;

c)、加上probability采集率设置,默认0.1,测试环境改为1.0保证每次都采集,生产环境适当抽样即可。(因为10000个请求抽样1000个也能发现问题了,没必要全部都采集)

222.png
3)、引入RestTemplate

这里restTemplate主要用来进行接口调用查看链路追踪是否生效

@Component
public class RestTemplateConfig {
    
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
4)、controller调用

会员调用订单

333.png

订单调用消息

444.png

消息处理具体业务

555.png
5)、查看效果

启动Zipkin服务端,访问:http://127.0.0.1:9411

666.png

执行controller接口

777.png

查看链路追踪,可以看到,接口调用的链路已经在zipkin显现了。

888.png
999.png


3、zipkin整合RabbitMQ异步采集

springboot2.0之后,官方不再推荐使用自建的zipkin server,而是直接使用编译好的zipkin.jar来给我们使用。

zipkin.jar中的yml配置可以参考:https://github.com/openzipkin/zipkin/blob/master/zipkin-server/src/main/resources/zipkin-server-shared.yml

1)、指定RabbitMQ为服务器

启动zipkin服务时指定rabbitmq为服务器即可,得先启动rabbitmq服务器。

java -jar zipkin.jar --zipkin.collector.rabbitmq.addresses=192.168.239.132

启动之后,可以发现rabbitmq中会自动新增一个zipkin队列,表示绑定成功。

1010.png
2)、引入中间依赖

给每个微服务引入stream和rabbitmq的中间件依赖

<!-- 引入和rabbitmq的中间依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-stream-binder-rabbit</artifactId>
</dependency>
3)、yml配置

修改每个微服务的application.yml,加上rabbitmq的配置。

rabbitmq: 
    host: 192.168.239.132
    port: 5672
    username: guest
    password: guest
4)、启动和调用

启动微服务,执行调用。

1111.png
5)、MQ是否收到消息

看rabbitmq是否有收消息,队列有反应说明rabbitmq收到消息了。

1212png.png
6)、Zipkin是否采集信息

看zipkin是否采集了链路信息

1313.png
7)、验证积压消息

关掉zipkin服务,看消息是否会积压在rabbitmq,再启动zipkin服务,看消息是否会被消费并且获取到链路信息。

1414.png

获取消息查看,发现获取到的就是traceId相关的json数据,证明整个过程都是正常的。

1515.png

重新再启动zipkin服务,发现rabbitmq积压的消息就被消费了。

1616.png

并且也能获取到链路信息

1717.png


4、zipkin使用MySQL存储

zipkin.jar中的yml配置可以参考,里面有关于mysql的配置或者其他如elasticsearch的配置:

https://github.com/openzipkin/zipkin/blob/master/zipkin-server/src/main/resources/zipkin-server-shared.yml

这节我们在上一节MQ的基础上增加MySQL的启动配置项

1)、指定MySQL

命令看着很长,其实仔细看发现很简单,都是见名知义,不必死记硬背。

java -jar zipkin.jar


--zipkin.collector.rabbitmq.addresses=192.168.239.132


--zipkin.storage.type=mysql


--zipkin.storage.mysql.host=127.0.0.1


--zipkin.storage.mysql.port=3306


--zipkin.storage.mysql.username=root


--zipkin.storage.mysql.password=123456


--zipkin.storage.mysql.db=zipkin

2)、创建zipkin数据库

根据1中命令配置的信息,创建zipkin数据库,并执行语句创建zipkin采集记录的三张表。

参考官网:https://github.com/apache/incubator-zipkin/blob/master/zipkin-storage/mysql-v1/src/main/resources/mysql.sql

这里我也贴出来 zipkin-mysql.sql

1818.png
CREATE TABLE IF NOT EXISTS zipkin_spans (
  `trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',
  `trace_id` BIGINT NOT NULL,
  `id` BIGINT NOT NULL,
  `name` VARCHAR(255) NOT NULL,
  `remote_service_name` VARCHAR(255),
  `parent_id` BIGINT,
  `debug` BIT(1),
  `start_ts` BIGINT COMMENT 'Span.timestamp(): epoch micros used for endTs query and to implement TTL',
  `duration` BIGINT COMMENT 'Span.duration(): micros used for minDuration and maxDuration query',
  PRIMARY KEY (`trace_id_high`, `trace_id`, `id`)
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;

ALTER TABLE zipkin_spans ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTracesByIds';
ALTER TABLE zipkin_spans ADD INDEX(`name`) COMMENT 'for getTraces and getSpanNames';
ALTER TABLE zipkin_spans ADD INDEX(`remote_service_name`) COMMENT 'for getTraces and getRemoteServiceNames';
ALTER TABLE zipkin_spans ADD INDEX(`start_ts`) COMMENT 'for getTraces ordering and range';

CREATE TABLE IF NOT EXISTS zipkin_annotations (
  `trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit',
  `trace_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.trace_id',
  `span_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.id',
  `a_key` VARCHAR(255) NOT NULL COMMENT 'BinaryAnnotation.key or Annotation.value if type == -1',
  `a_value` BLOB COMMENT 'BinaryAnnotation.value(), which must be smaller than 64KB',
  `a_type` INT NOT NULL COMMENT 'BinaryAnnotation.type() or -1 if Annotation',
  `a_timestamp` BIGINT COMMENT 'Used to implement TTL; Annotation.timestamp or zipkin_spans.timestamp',
  `endpoint_ipv4` INT COMMENT 'Null when Binary/Annotation.endpoint is null',
  `endpoint_ipv6` BINARY(16) COMMENT 'Null when Binary/Annotation.endpoint is null, or no IPv6 address',
  `endpoint_port` SMALLINT COMMENT 'Null when Binary/Annotation.endpoint is null',
  `endpoint_service_name` VARCHAR(255) COMMENT 'Null when Binary/Annotation.endpoint is null'
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;

ALTER TABLE zipkin_annotations ADD UNIQUE KEY(`trace_id_high`, `trace_id`, `span_id`, `a_key`, `a_timestamp`) COMMENT 'Ignore insert on duplicate';
ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`, `span_id`) COMMENT 'for joining with zipkin_spans';
ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTraces/ByIds';
ALTER TABLE zipkin_annotations ADD INDEX(`endpoint_service_name`) COMMENT 'for getTraces and getServiceNames';
ALTER TABLE zipkin_annotations ADD INDEX(`a_type`) COMMENT 'for getTraces and autocomplete values';
ALTER TABLE zipkin_annotations ADD INDEX(`a_key`) COMMENT 'for getTraces and autocomplete values';
ALTER TABLE zipkin_annotations ADD INDEX(`trace_id`, `span_id`, `a_key`) COMMENT 'for dependencies job';

CREATE TABLE IF NOT EXISTS zipkin_dependencies (
  `day` DATE NOT NULL,
  `parent` VARCHAR(255) NOT NULL,
  `child` VARCHAR(255) NOT NULL,
  `call_count` BIGINT,
  `error_count` BIGINT,
  PRIMARY KEY (`day`, `parent`, `child`)
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci;
3)、效果

启动微服务,执行controller请求,看是否成功。

RabbitMQ

1919.png

zipkin

2020.png

MySQL

2121.png


至此,springcloud sleuth + zipkin + rabbitmq + mysql 就全部整合成功了!


总结

微服务的治理方案有很多,学习方向根据个人喜好决定,我的经验就是不必盲目跟从这种用于辅助的方案,比如现在有SkyWalking,以后可能还有SkyFlying、SkySwimming。


走向高级软件工程师都要有一个意识,就是在层出不穷的开源框架如雨后春笋般出现的时候,你得有信心用到哪个花点时间就能自己搭建起来,这才是提升自己的最有效方法。


一个项目使用什么治理方案最重要的绝不是跟风,而是哪款最适合就用哪款,就像你找女朋友一样,不单单是找漂亮的,而是找最能一起过日子的,否则就是貌合神离。


分享

本篇实际上是我8年多工作及学习过程中在云笔记中记录的内容之一,其实还有很多我闲暇之余都做了下整理,有感兴趣的朋友可以下载看看,什么时候用到了翻开说不定就能节省很多时间。

链接: https://pan.baidu.com/doc/share/flr0QYwZYPYxmWSRPbnJRw-1028798558141759

提取码: bxaa

资料图.png



本人原创文章纯手打,专注于分享主流技术及实际工作经验,觉得有一滴滴帮助的话就请点个赞和收藏吧!


更多最新技术文章可关注GZH:【Java分享客栈】

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容