您当前的位置: 首页 >  spring

一一哥Sun

暂无认证

  • 3浏览

    0关注

    622博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Day18_02_SpringCloud教程之Sleuth链路追踪

一一哥Sun 发布时间:2019-07-22 17:17:08 ,浏览量:3

21_SpringCloud教程之Sleuth链路追踪 一. Sleuth简介

微服务架构是一个分布式架构,它按业务划分服务单元,一个分布式系统往往有很多个服务单元.由于服务单元数量众多,业务的复杂性,如果出现了错误和异常,很难去定位.主要体现在一个请求可能需要调用很多个服务,而内部服务的调用复杂性,决定了问题难以定位.所以在微服务架构中,必须实现分布式链路追踪,去跟进一个请求到底有哪些服务参与,参与的顺序又是怎样的,从而达到每个请求的步骤清晰可见,出了问题,可以很快的定位.

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调用,对外暴露的一个接口,可能需要很多个服务协同才能完成这个接口功能,如果链路上任何一个服务出现问题或者网络超时,都会形成导致接口调用失败.随着业务的不断扩张,服务之间互相调用会越来越复杂.

随着服务的越来越多,对调用链的分析会越来越复杂.

三. Zipkin介绍 1. Zipkin是什么

Zipkin的设计是基于谷歌的Google Dapper论文,它是一种分布式的跟踪系统,可以帮助我们收集时间数据,解决在微服务架构下的延迟问题,另外它可以管理这些数据的收集和查找.

每个应用程序向Zipkin报告定时数据,Zipkin UI呈现了一个依赖图表来展示多少跟踪请求经过了每个应用程序.如果想解决延迟问题,可以过滤或者排序所有的跟踪请求,并且可以查看每个跟踪请求占总跟踪时间的百分比.

2. 为什么使用Zipkin?

随着业务越来越复杂,系统也随之进行各种拆分,特别是随着微服务架构和容器技术的兴起,看似简单的一个应用,后台可能有几十个甚至几百个服务在支撑.一个前端的请求可能需要多次的服务调用最后才能完成,当请求变慢或者不可用时,我们无法得知是哪个后台服务引起的,这时就需要解决如何快速定位服务故障点,Zipkin分布式跟踪系统就能很好的解决这样的问题.

3. Zipkin原理

针对服务化应用全链路追踪的问题,Google发表了Dapper论文,介绍了他们如何进行服务追踪分析.其基本思路是在服务调用的请求和响应中加入ID,标明上下游请求的关系,利用这些信息,可以可视化地分析服务调用链路和服务间的依赖关系.

对应Dpper的开源实现是Zipkin,支持多种语言包括JavaScript,Python,Java, Scala, Ruby, C#, Go等,其中Java由多种不同的库来支持.

Spring Cloud Sleuth是对Zipkin的一个封装,对于Span、Trace等信息的生成、接入HTTP Request,以及向Zipkin Server发送采集信息等全部自动完成.

4. Zipkin架构

跟踪器(Tracer)位于你的应用程序中,并记录发生的操作的时间和元数据,提供了相应的类库,对用户的使用来说是透明的,收集的跟踪数据称为Span;将数据发送到Zipkin的仪器化应用程序中的组件称为Reporter,Reporter通过几种传输方式之一将追踪数据发送到Zipkin收集器(collector),然后将跟踪数据进行存储(storage),由API查询存储以向UI提供数据.

4.1 Trace

Zipkin使用Trace结构表示对一次请求的跟踪,一次请求可能由后台的若干服务负责处理,每个服务的处理是一个Span,Span之间有依赖关系,Trace就是树结构的Span集合.

4.2 Span

每个服务的处理跟踪是一个Span,可以理解为一个基本的工作单元,包含了一些描述信息: id,parentId,name,timestamp,duration,annotations等.

  • traceId: 标记一次请求的跟踪,相关的Spans都有相同的traceId;

  • id: span id;

  • name: span的名称,一般是接口方法的名称;

  • parentId: 可选的id,当前Span的父Span id,通过parentId来保证Span之间的依赖关系,如果没有parentId,表示当前Span为根Span;

  • timestamp: Span创建时的时间戳,使用的单位是微秒(而不是毫秒),所有时间戳都有错误,包括主机之间的时钟偏差以及时间服务重新设置时钟的可能性,出于这个原因,Span应尽可能记录其duration;

  • duration: 持续时间使用的单位是微秒(而不是毫秒);

  • annotations: 注释用于及时记录事件,有一组核心注释用于定义RPC请求的开始和结束;

  • cs: Client Send,客户端发起请求;

  • sr: Server Receive,服务器接受请求,开始处理;

  • ss: Server Send,服务器完成处理,给客户端应答;

  • cr: Client Receive,客户端接受应答从服务器;

  • binaryAnnotations: 二进制注释,旨在提供有关RPC的额外信息.

4.3 Transport

收集的Spans必须从被追踪的服务运输到Zipkin collector,有三个主要的传输方式: HTTP, Kafka和Scribe;

4.4 Components

有4个组件组成Zipkin: collector,storage,search,web UI.

  • collector: 一旦跟踪数据到达Zipkin collector守护进程,它将被验证,存储和索引,以供Zipkin收集器查找;

  • storage: Zipkin最初数据存储在Cassandra上,因为Cassandra是可扩展的,具有灵活的模式,并在Twitter中大量使用.但是这个组件可插入,除了Cassandra之外,还支持ElasticSearch和MySQL存储,zipkin默认的存储方式为in-memory,即不会进行持久化操作.如果想进行收集数据的持久化,可以存储数据在Cassandra,因为Cassandra是可扩展的,有一个灵活的模式,并且在Twitter中被大量使用,我们使这个组件可插入.除了Cassandra,我们原生支持ElasticSearch和MySQL,其他后端可能作为第三方扩展提供.

  • search: 一旦数据被存储和索引,我们需要一种方法来提取它.查询守护进程提供了一个简单的JSON API来查找和检索跟踪,主要给Web UI使用.

  • web UI: 创建了一个GUI,为查看痕迹提供了一个很好的界面,Web UI提供了一种基于服务,时间和注释查看跟踪的方法.

四. 构建工程

接下来我们创建三个工程: 一个zipkin-server,它的主要作用使用ZipkinServer的功能,收集调用数据并展示; 一个service-hello,对外暴露hi接口; 一个sleuth-service-provider,对外暴露showInfo接口. 这两个service可以相互调用,并且只有调用了,server-zipkin才会收集调用数据,这就是为什么叫服务追踪了. 

1. 构建zipkin-server

在Spring Cloud Finchley.RELEASE版本中,不需要我们自己再构建Zipkin Server项目了,只需要下载一个zipkin-server-2.10.1-exec.jar即可,下载地址:

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

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

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

访问浏览器localhost:9494

2. 创建service-hello服务 2.1 创建pom文件

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



    
        sleuth06
        com.syc.cloud
        1.0-SNAPSHOT
    

    4.0.0
    service_hello

    
        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.springframework.cloud
            spring-cloud-starter-zipkin
        
    


2.2 创建application.yml文件

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

server:
  port: 8761
spring:
  application:
    name: service-hello
  #指定zipkin server的地址,通过配置“spring.zipkin.base-url”指定.
  zipkin:
    base-url: http://localhost:9411

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

2.3 入口类及对外接口
package com.syc.cloud;

import brave.sampler.Sampler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.logging.Level;
import java.util.logging.Logger;

@SpringBootApplication
@RestController
public class SleuthHelloServiceApp {

    public static void main(String[] args) {
        SpringApplication.run(SleuthHelloServiceApp.class, args);
    }

    private static final Logger LOG = Logger.getLogger(SleuthHelloServiceApp.class.getName());

    @Autowired
    private RestTemplate restTemplate;

    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }

    //调用8762里的接口方法
    @RequestMapping("/hello")
    public String callHome() {
        LOG.log(Level.INFO, "calling trace service-hello ");
        return restTemplate.getForObject("http://localhost:8762/provider", String.class);
    }

    @RequestMapping("/info")
    public String info() {
        LOG.log(Level.INFO, "calling trace service-hello ");
        return "i'm service-hello";
    }

    //配置采样
    @Bean
    public Sampler defaultSampler() {
        return Sampler.ALWAYS_SAMPLE;
    }

}
3. 创建sleuth-service-provider

创建过程基本等同于service-hello,引入相同的依赖包,也是配置spring.zipkin.base-url.

对外暴露接口:

package com.syc.cloud;

import brave.sampler.Sampler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 */
@SpringBootApplication
@RestController
public class SleuthProviderServiceApp {

    public static void main(String[] args) {
        SpringApplication.run(SleuthProviderServiceApp.class, args);
    }

    private static final Logger LOG = Logger.getLogger(SleuthProviderServiceApp.class.getName());

    @RequestMapping("/provider")
    public String home(){
        LOG.log(Level.INFO, "hello is being called...");

        return "Hello, I'm provider!";
    }

    //调用8761里的服务
    @RequestMapping("/showInfo")
    public String info(){
        LOG.log(Level.INFO, "info is being called");
        return restTemplate.getForObject("http://localhost:8761/info",String.class);
    }

    @Autowired
    private RestTemplate restTemplate;

    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }

    //配置采样
    @Bean
    public Sampler defaultSampler() {
        return Sampler.ALWAYS_SAMPLE;
    }

}
4. 启动工程

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

访问http://localhost:8761/hello,浏览器出现:

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

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

 

关注
打赏
1665624836
查看更多评论
立即登录/注册

微信扫码登录

0.0429s