022 SpringCloud_分布式链路跟踪

分布式调用系统的现状:

       当前,随着互联网架构的扩张,分布式系统变得日趋复杂,越来越多的组件开始走向分布式化,如微服务、消息收发、分布式数据库、分布式缓存、分布式对象存储、跨域调用,这些组件共同构成了繁杂的分布式网络。

当应用A发出某个请求时,其背后可能有数十个甚至更多的服务被调用,可谓是“牵一发而动全身”

业界非常知名的分布式链路跟踪服务:

阿里:鹰眼

大众点评:CAT

美团:OCTO

京东: Hydra

Twitter—OpenZipkin

鹰眼系统简介:

阿里中分布式调用跟踪是采用鹰眼(EagleEye)系统来实现的,鹰眼是基于日志的分布式调用跟踪系统,其理念脱胎于Google Dapper论文,其关键核心在于调用链,为每个请求生成全局唯一的IDTraceld),通过它将不同系统的“孤立的”调用信息关联在一起,还原出更多有价值的数据。

可以在业务异常日志的错误信息中找到Traceld(比如TraceId=ac18287913742691251746923),之后在鹰眼系统中只需要输入Traceld,就可以看到调用链中具体的情况,在调用链上更加直观地定位到问题,层层排查后确定问题的所在。

ZipKin是一个链路跟踪工具,可以用来监控微服务集群中调用链路的通畅情况

首先,ZipKinSpring Cloud 的分布式链路跟踪解决方案:

比如存在两个子项目,并在一个项目中使用RestTemplate或者Feign等方法调用另外一个项目中的接口,这样就可以利用ZipKin进行跟踪服务!

第一步:需要一个zipkin-server服务

第二步:需要两个trace服务,然后进行调用跟踪

代码实现:

1.创建eureka-server:略(详见前文)

2.创建zipkin-server:独立于eureka,可以注册到eureka做负载和高可用;

pom:

<dependencies>
      <dependency>
          <groupId>io.zipkin.java</groupId>
          <artifactId>zipkin-server</artifactId>
      </dependency>
      <dependency>
        <groupId>io.zipkin.java</groupId>
        <artifactId>zipkin-autoconfigure-storage-mysql</artifactId>
    </dependency>
    <dependency>
        <groupId>io.zipkin.java</groupId>
        <artifactId>zipkin-autoconfigure-ui</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
      <dependency>
        <groupId>org.jooq</groupId>
        <artifactId>jooq</artifactId>
    </dependency>
  </dependencies>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Edgware.SR4</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<build>
    <finalName>spring-cloud-06-config-server</finalName>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <mainClass>com.cc.springcloud.Application</mainClass>
            </configuration>
        </plugin>
    </plugins>
</build>

--------------------------------------------------------------------------------------------

application.properties:

spring.application.name=zipkin-server
server.port=9500

spring.datasource.url=jdbc:mysql://localhost:3306/zipkin?characterEncoding=UTF-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&useUnicode=true
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.schema=classpath:/zipkin.sql
spring.datasource.initialize=true
spring.datasource.continue-on-error=true
##真实生产环境应该使用ES进行存储,myqsl无法承受高并发
zipkin.storage.type=mysql

--------------------------------------------------------------------------------------------

Application:

package com.cc.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


import zipkin.server.internal.EnableZipkinServer;

@EnableZipkinServer      //zipkin
@SpringBootApplication   //springboot 核心配置
public class Application {

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

此文件官网下载就可以;

3.创建3个trace,代码结构基本一致,最为服务依次调用测试:

pom:

<dependencies>
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <!-- 标示这个工程是一个服务的提供者,需要引入此jar -->
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
      </dependency>
      <!-- 动态刷新的一个模块jar -->
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-actuator</artifactId>
      </dependency>
      
      <!-- sleuth(抓取)  && zipkin -->
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-sleuth</artifactId>
      </dependency>
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-sleuth-zipkin</artifactId>
      </dependency>
      <!-- kafka 
      <dependency>
        <groupId>org.springframeword.cloud</groupId>
        <artifactId>spring-cloud-starter-stream-kafka</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframeword.cloud</groupId>
        <artifactId>spring-cloud-sleuth-zipkin-stream</artifactId>
    </dependency>-->
      
  </dependencies>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Edgware.SR4</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<build>
    <finalName>spring-cloud-08-trace-1</finalName>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <mainClass>com.cc.springcloud.Application</mainClass>
            </configuration>
        </plugin>
    </plugins>
</build>

---------------------------------------------------------------------------------------------

application.properties:

spring.application.name=trace-1
##微服务方式尽量不要加server.context-path,只用名字加方法实现
#server.context-path=/provider
server.context-path=/
server.port=7001

##需要引入eureka注册中心的地址
##下面两条配置代表注册到注册中心后显示自己的IP地址,实际工作中尽量加上
eureka.instance.prefer-ip-address=true
eureka.instance.instance-id=${spring.application.name}:${spring.cloud.client.ipAddress}:${server.port}

##租期到期时间间隔
eureka.instance.lease-expiration-duration-in-seconds=30
##租期更新时间间隔
eureka.instance.lease-renewal-interval-in-seconds=10

##开启健康检查,必须要引入spring-boot-starter-actuator动态刷新jar
eureka.client.healthcheck.enabled=true
eureka.client.service-url.defaultZone=http://eureka1:8001/eureka

## 配置zipkin地址以及sleuth服务抓取日志的采样百分比
spring.zipkin.base-url=http://localhost:9500
## 1.0代表100%
spring.sleuth.sampler.percentage=1.0

##配置kafka与zookeeper
#spring.cloud.stream.kafka.zkNodes=192.168.1.11:2182,192.168.1.11:2183,192.168.1.11:2184
#spring.cloud.stream.kafka.zkNodes=192.168.1.11:9092

---------------------------------------------------------------------------------------------

Application:

package com.cc.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

@EnableDiscoveryClient   //标示是一个具体的服务,需要向注册中心注册
@SpringBootApplication   //springboot 核心配置
public class Application {

    @Bean
    @LoadBalanced //用于实现内部的服务负载均衡机制:service-id service-name
    public RestTemplate restTemplate() {    //springcloud项目基于http通讯,所以此处构建RestTemplate
        HttpComponentsClientHttpRequestFactory httpComponentsClientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        httpComponentsClientHttpRequestFactory.setConnectTimeout(10000);
        httpComponentsClientHttpRequestFactory.setConnectionRequestTimeout(10000);
        httpComponentsClientHttpRequestFactory.setReadTimeout(20000);
        return new RestTemplate(httpComponentsClientHttpRequestFactory);
    }
    
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
---------------------------------------------------------------------------------------------

Trace1Controller:

package com.cc.springcloud.api;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class Trace1Controller {
    
    @Autowired
    private RestTemplate restTemplate;
    
    @RequestMapping(value="/trace1")
    public String trace1() {
        System.out.println("-----trace1-----");
        return restTemplate.getForObject("http://trace-2/trace2", String.class);
    }
}
---------------------------------------------------------------------------------------------

trace-2/Trace2Controller:

package com.cc.springcloud.api;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class Trace2Controller {
    
    @Autowired
    private RestTemplate restTemplate;
    
    @RequestMapping(value="/trace2")
    public String trace1() {
        System.out.println("-----trace2-----");
        return restTemplate.getForObject("http://trace-3/trace3", String.class);
    }
}
---------------------------------------------------------------------------------------------

trace-3/Trace3Controller:

package com.cc.springcloud.api;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class Trace3Controller {
    
    @Autowired
    private RestTemplate restTemplate;
    
    @RequestMapping(value="/trace3")
    public String trace1() {
        System.out.println("-----trace3-----");
        //return restTemplate.getForObject("http://trace-2/trace2", String.class);
        return "success!";
    }
}
---------------------------------------------------------------------------------------------

启动测试:

zipkin-server启动后数据库表自动创建(前提先手动创建zipkin数据库);

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值