业余草springcloud教程|第九篇:服务链路追踪(springcloudsleuth)(finchley版本)

业余草      2022-04-07     584

关键词:

这篇文章主要讲述服务追踪组件zipkin,Spring Cloud Sleuth集成了zipkin组件。

一、简介

Add sleuth to the classpath of a Spring Boot application (see below for Maven and Gradle examples), and you will see the correlation data being collected in logs, as long as you are logging requests.

—— 摘自官网

Spring Cloud Sleuth 主要功能就是在分布式系统中提供追踪解决方案,并且兼容支持了 zipkin,你只需要在pom文件中引入相应的依赖即可。

二、服务追踪分析

微服务架构上通过业务来划分服务的,通过REST调用,对外暴露的一个接口,可能需要很多个服务协同才能完成这个接口功能,如果链路上任何一个服务出现问题或者网络超时,都会形成导致接口调用失败。随着业务的不断扩张,服务之间互相调用会越来越复杂。

技术分享图片

随着服务的越来越多,对调用链的分析会越来越复杂。它们之间的调用关系也许如下:

技术分享图片

三、术语

  • Span:基本工作单元,例如,在一个新建的span中发送一个RPC等同于发送一个回应请求给RPC,span通过一个64位ID唯一标识,trace以另一个64位ID表示,span还有其他数据信息,比如摘要、时间戳事件、关键值注释(tags)、span的ID、以及进度ID(通常是IP地址) 
    span在不断的启动和停止,同时记录了时间信息,当你创建了一个span,你必须在未来的某个时刻停止它。
  • Trace:一系列spans组成的一个树状结构,例如,如果你正在跑一个分布式大数据工程,你可能需要创建一个trace。
  • Annotation:用来及时记录一个事件的存在,一些核心annotations用来定义一个请求的开始和结束 
    • cs - Client Sent -客户端发起一个请求,这个annotion描述了这个span的开始
    • sr - Server Received -服务端获得请求并准备开始处理它,如果将其sr减去cs时间戳便可得到网络延迟
    • ss - Server Sent -注解表明请求处理的完成(当请求返回客户端),如果ss减去sr时间戳便可得到服务端需要的处理请求时间
    • cr - Client Received -表明span的结束,客户端成功接收到服务端的回复,如果cr减去cs时间戳便可得到客户端从服务端获取回复的所有所需时间 
      将Span和Trace在一个系统中使用Zipkin注解的过程图形化:

将Span和Trace在一个系统中使用Zipkin注解的过程图形化:

技术分享图片

四、构建工程

基本知识讲解完毕,下面我们来实战,本文的案例主要有三个工程组成:一个server-zipkin,它的主要作用使用ZipkinServer 的功能,收集调用数据,并展示;一个service-hi,对外暴露hi接口;一个service-miya,对外暴露miya接口;这两个service可以相互调用;并且只有调用了,server-zipkin才会收集数据的,这就是为什么叫服务追踪了。

4.1 构建server-zipkin

在spring Cloud为F版本的时候,已经不需要自己构建Zipkin Server了,只需要下载jar即可,下载地址:

https://dl.bintray.com/openzipkin/maven/io/zipkin/java/zipkin-server/

也可以在这里下载:

链接: https://pan.baidu.com/s/1w614Z8gJXHtqLUB6dKWOpQ 密码: 26pf

下载完成jar 包之后,需要运行jar,如下:

java -jar zipkin-server-2.10.1-exec.jar

访问浏览器localhost:9494

4.2 创建service-hi

在其pom引入起步依赖spring-cloud-starter-zipkin,代码如下:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 4     <modelVersion>4.0.0</modelVersion>
 5  
 6     <groupId>com.forezp</groupId>
 7     <artifactId>service-zipkin</artifactId>
 8     <version>0.0.1-SNAPSHOT</version>
 9     <packaging>jar</packaging>
10  
11     <name>service-hi</name>
12     <description>Demo project for Spring Boot</description>
13  
14     <parent>
15         <groupId>com.forezp</groupId>
16         <artifactId>sc-f-chapter9</artifactId>
17         <version>0.0.1-SNAPSHOT</version>
18     </parent>
19  
20  
21  
22     <dependencies>
23  
24         <dependency>
25             <groupId>org.springframework.boot</groupId>
26             <artifactId>spring-boot-starter-web</artifactId>
27         </dependency>
28  
29         <dependency>
30             <groupId>org.springframework.cloud</groupId>
31             <artifactId>spring-cloud-starter-zipkin</artifactId>
32         </dependency>
33  
34  
35  
36     </dependencies>
37  
38     <build>
39         <plugins>
40             <plugin>
41                 <groupId>org.springframework.boot</groupId>
42                 <artifactId>spring-boot-maven-plugin</artifactId>
43             </plugin>
44         </plugins>
45     </build>
46  
47 </project>

在其配置文件application.yml指定zipkin server的地址,头通过配置“spring.zipkin.base-url”指定:

1 server.port=8988
2 spring.zipkin.base-url=http://localhost:9411
3 spring.application.name=service-hi

通过引入spring-cloud-starter-zipkin依赖和设置spring.zipkin.base-url就可以了。

对外暴露接口:

 1 package com.forezp;
 2  
 3 import brave.sampler.Sampler;
 4 import org.springframework.beans.factory.annotation.Autowired;
 5 import org.springframework.boot.SpringApplication;
 6 import org.springframework.boot.autoconfigure.SpringBootApplication;
 7 import org.springframework.context.annotation.Bean;
 8 import org.springframework.web.bind.annotation.RequestMapping;
 9 import org.springframework.web.bind.annotation.RestController;
10 import org.springframework.web.client.RestTemplate;
11 import java.util.logging.Level;
12 import java.util.logging.Logger;
13  
14 @SpringBootApplication
15 @RestController
16 public class ServiceHiApplication {
17  
18     public static void main(String[] args) {
19         SpringApplication.run(ServiceHiApplication.class, args);
20     }
21  
22     private static final Logger LOG = Logger.getLogger(ServiceHiApplication.class.getName());
23  
24  
25     @Autowired
26     private RestTemplate restTemplate;
27  
28     @Bean
29     public RestTemplate getRestTemplate(){
30         return new RestTemplate();
31     }
32  
33     @RequestMapping("/hi")
34     public String callHome(){
35         LOG.log(Level.INFO, "calling trace service-hi  ");
36         return restTemplate.getForObject("http://localhost:8989/miya", String.class);
37     }
38     @RequestMapping("/info")
39     public String info(){
40         LOG.log(Level.INFO, "calling trace service-hi ");
41  
42         return "i‘m service-hi";
43  
44     }
45  
46     @Bean
47     public Sampler defaultSampler() {
48         return Sampler.ALWAYS_SAMPLE;
49     }
50  
51  
52 }

4.3 创建service-miya

创建过程痛service-hi,引入相同的依赖,配置下spring.zipkin.base-url。

对外暴露接口:

 1  
 2 package com.forezp;
 3  
 4 import brave.sampler.Sampler;
 5 import org.springframework.beans.factory.annotation.Autowired;
 6 import org.springframework.boot.SpringApplication;
 7 import org.springframework.boot.autoconfigure.SpringBootApplication;
 8 import org.springframework.context.annotation.Bean;
 9 import org.springframework.web.bind.annotation.RequestMapping;
10 import org.springframework.web.bind.annotation.RestController;
11 import org.springframework.web.client.RestTemplate;
12  
13 import java.util.logging.Level;
14 import java.util.logging.Logger;
15  
16 @SpringBootApplication
17 @RestController
18 public class ServiceMiyaApplication {
19  
20     public static void main(String[] args) {
21         SpringApplication.run(ServiceMiyaApplication.class, args);
22     }
23  
24     private static final Logger LOG = Logger.getLogger(ServiceMiyaApplication.class.getName());
25  
26  
27     @RequestMapping("/hi")
28     public String home(){
29         LOG.log(Level.INFO, "hi is being called");
30         return "hi i‘m miya!";
31     }
32  
33     @RequestMapping("/miya")
34     public String info(){
35         LOG.log(Level.INFO, "info is being called");
36         return restTemplate.getForObject("http://localhost:8988/info",String.class);
37     }
38  
39     @Autowired
40     private RestTemplate restTemplate;
41  
42     @Bean
43     public RestTemplate getRestTemplate(){
44         return new RestTemplate();
45     }
46  
47  
48     @Bean
49     public Sampler defaultSampler() {
50         return Sampler.ALWAYS_SAMPLE;
51     }
52 }

4.4 启动工程,演示追踪

依次启动上面的工程,打开浏览器访问:http://localhost:9411/,会出现以下界面:

技术分享图片

访问:http://localhost:8989/miya,浏览器出现:

i’m service-hi

再打开http://localhost:9411/的界面,点击Dependencies,可以发现服务的依赖关系:

技术分享图片

点击find traces,可以看到具体服务相互调用的数据:

技术分享图片

本文源码下载:

https://github.com/forezp/SpringCloudLearning/tree/master/sc-f-chapter9

五、参考资料

spring-cloud-sleuth

http://cloud.spring.io/spring-cloud-static/Finchley.RELEASE/single/spring-cloud.html

技术分享图片

感谢您的关注!可加QQ1群:135430763,QQ2群:454796847,QQ3群:187424846。QQ群进群密码:xttblog,想加微信群的朋友,可以微信搜索:xmtxtt,备注:“xttblog”,添加助理微信拉你进群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至[email protected]邮箱。商务合作可添加助理微信进行沟通!

业余草springcloud教程|第一篇:服务的注册与发现eureka(finchley版本)

一、springcloud简介鉴于《史上最简单的SpringCloud教程》很受读者欢迎,再次我特意升级了一下版本,目前支持的版本为SpringBoot版本2.0.3.RELEASE,SpringCloud版本为Finchley.RELEASE。Finchley版本的官方文档如下: http://cloud.spring.io/spring-clo... 查看详情

业余草springcloud教程|第四篇:断路器(hystrix)(finchley版本)

...一个个的服务,服务与服务之间可以相互调用(RPC),在SpringCloud可以用RestTemplate+Ribbon和Feign来调用。为了保证其高可用,单个服务通常会集群部署。由于网络原因或者自身的原因,服务并不能保证100%可用,如果单个服务出现问... 查看详情

业余草springcloud教程|第五篇:路由网关(zuul)(finchley版本)

...候忘记了。并且配置服务也是注册到服务注册中心的。在SpringCloud微服务系统中,一种常见的负载均衡方式是,客户端的请求首先经过负载均衡( 查看详情

业余草springcloud教程|第二篇:服务消费者(rest+ribbon)(finchley版本)

...一个独立的服务,服务与服务的通讯是基于httprestful的。Springcloud有两种服务调用方式,一种是ribbon+restTemplate,另一种是feign。在这一篇文章首先讲解下基于ribbon+rest。一、ribbon简介Ribbonisaclientsideloadbalancerwhichgivesyoua 查看详情

业余草springcloud教程|第六篇:分布式配置中心(springcloudconfig)(finchley版本)

...到过,使用配置服务来保存各个服务的配置文件。它就是SpringCloudConfig。一、简介在分布式系统中,由于服务数量巨多,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件。在SpringCloud中,有分布式配置... 查看详情

业余草springcloud教程|第三篇:服务消费者(feign)(finchley版本)

上一篇文章,讲述了如何通过RestTemplate+Ribbon去消费服务,这篇文章主要讲述如何通过Feign去消费服务。一、Feign简介Feign是一个声明式的伪Http客户端,它使得写Http客户端变得更简单。使用Feign,只需要创建一个接口并注解。它具... 查看详情

业余草springcloud教程|第八篇:消息总线(springcloudbus)(finchley版本)

SpringCloudBus将分布式的节点用轻量的消息代理连接起来。它可以用于广播配置文件的更改或者服务之间的通讯,也可以用于监控。本文要讲述的是用SpringCloudBus实现通知微服务架构的配置文件的更改。一、准备工作本文还是基于... 查看详情

业余草springcloud教程|第十二篇:断路器聚合监控(hystrixturbine)(finchley版本)

...要聚合所以服务的HystrixDashboard的数据了。这就需要用到SpringCloud的另一个组件了,即HystrixTurbine。一、HystrixTurbine简介看单个的HystrixDashboard的数据并没有什么多大的价值,要想看这个系统的Hyst 查看详情

springcloud-第九篇feign

...么Feign旨在使编写JavaHttp客户端变得更容易。前面在使用SpringCloudRibbon+RestTemplate时,利用RestTemplate对h 查看详情

业余草springcloud教程|第七篇:高可用的分布式配置中心(springcloudconfig)(finchley版本)

上一篇文章讲述了一个服务如何从配置中心读取文件,配置中心如何从远程git读取配置文件,当服务实例很多时,都从配置中心读取文件,这时可以考虑将配置中心做成一个微服务,将其集群化,从而达到高可用,架构图如下:... 查看详情

(第九篇)iptables详解

常见的网络攻击形式1.拒绝服务攻击:DOS2.分布式拒绝服务攻击DDOS3.漏洞入侵4.口令猜测以上内容简单了解,具体可自行百度,此处不必知晓。Linux防火墙基础Linux防火墙体系主要工作在网络层,针对TCP/IP数据包实施过滤和限制,... 查看详情

用仿actionscript的语法来编写html5——第九篇,仿urlloader读取文件

第九篇,仿URLLoader读取文件先看看最后的代码functionreadFile(){urlloader=newLURLLoader();urlloader.addEventListener(LEvent.COMPLETE,readFileOk);urlloader.load("../file/test.txt","text");}functionreadFileOk(){mytxt.text 查看详情

第九篇:docker镜像仓库(代码片段)

环境说明:操作系统:centos7内核版本:[[email protected]~]#uname-r3.10.0-693.21.1.el7.x86_64摘要:仓库(Repository)是集中存放镜像的地方,与之关联的是注册服务器。那注册服务器和仓库有什么关系呢?比如仓库地址为:https://dl.docker... 查看详情

第九篇googlenet——论文翻译

文章目录摘要 查看详情

业余草thrift内存溢出的分析解决过程分享

业余草 今天为大家分享一下我在使用 thrift过程中遇到的内存泄漏解放方法。 背景:有一个项目做一个系统,分客户端和服务端,客户端用c++写的,用来收集信息然后传给服务端(客户端的数量还是比较多的,正常的... 查看详情

springcloud教程——sleuth(f版本)

...。随着服务的越来越多,对调用链的分析会越来越复杂。SpringCloudSleuth服务链路跟踪功能就可以帮助我们快速的发现错误根源以及监控分析每条请求链路上的性 查看详情

第九篇:网络编程补充与进程

本篇内容udp协议套接字开启进程的方式多进程实现并发的套接字通信join方法守护进程同步锁进程队列生产者消费者模型进程池paramiko模块 一、 udp协议套接字1.TCP和UDP在传输层区别:UDP是无连接不可靠的数据报协议。TCP提... 查看详情

第九篇道

第九篇 道  “道”这个字出现在人们的视野中,已经有很悠久的历史。但是人们对于“道”这个字的理解非常模糊,都是盲目地去猜测,不知道这个字真正的意义是什么。其实,“道”就是轨道,也可以称之为“宇宙... 查看详情