首页 > 技术文章 > 使用zipkin2在SpringCloud2.0环境下追踪服务调用情况

jizhong 2019-09-15 22:33 原文

1.目的:

使用zipkin2.0在Spring Cloud 2.0环境下,追踪服务调用情况。

2.所需组件:

zipkin2.0,Spring Cloud 2.0,Eureka Server,Eureka Client.

3.项目整体组成

如下图所示:

4.详细介绍及配置:

zipkinp的pom配置为:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.****</groupId>
    <artifactId>zipkin-p</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <modules>
        <module>customer</module>
        <module>eurekaserver</module>
        <module>service</module>
    </modules>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.RELEASE</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <zipkin-version>2.11.8</zipkin-version>
    </properties>
    
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-zipkin</artifactId>
                <version>2.0.1.RELEASE</version>
            </dependency>
            <!--            <dependency>
                            <artifactId>parent</artifactId>
                            <groupId>io.zipkin.zipkin2</groupId>
                            <version>${zipkin-version}</version>
                            <scope>import</scope>
                        </dependency>-->
            <dependency>
                <groupId>io.zipkin.java</groupId>
                <artifactId>zipkin-server</artifactId>
                <version>${zipkin-version}</version>
            </dependency>
            <dependency>
                <groupId>io.zipkin.java</groupId>
                <artifactId>zipkin-autoconfigure-ui</artifactId>
                <version>${zipkin-version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

zipkinserver项目的pom文件配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.****</groupId>
        <artifactId>zipkin-p</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <groupId>com.****</groupId>
    <artifactId>zipkinserver</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>zipkinserver</name>
    <packaging>jar</packaging>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <version>2.0.1.RELEASE</version>
        </dependency>
        <dependency>
                <groupId>io.zipkin.java</groupId>
                <artifactId>zipkin-server</artifactId>
        </dependency>
        <dependency>
            <groupId>io.zipkin.java</groupId>
            <artifactId>zipkin-autoconfigure-ui</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

配置完成后,在启动类,配置如下:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import zipkin2.server.internal.EnableZipkinServer;

@EnableZipkinServer
@EnableDiscoveryClient
@SpringBootApplication
public class ZipkinserverApplication {

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

}

之后,配置yaml文件:

server:
  port: 9411
eureka:
  instance:
    prefer-ip-address: true
    hostname: localhost
  client:
    service-url:
      defaultZone: http://admin:123456@localhost:8888/eureka/
spring:
  application:
    name: zipkinserver

配置eurekaserver项目,pom及启动类的配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.****</groupId>
        <artifactId>zipkin-p</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <groupId>com.****</groupId>
    <artifactId>eurekaserver</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>eurekaserver</name>
    <description>Demo project for Spring Boot</description>


    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            <version>2.0.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>
    </dependencies>


    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@EnableEurekaServer
@SpringBootApplication
public class EurekaserverApplication {

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

}

配置完成后,配置yaml文件:

server:
  port: 8888

eureka:
  instance:
    hostname: localhost
    lease-expiration-duration-in-seconds: 60
    lease-renewal-interval-in-seconds: 20
  client:
    registerWithEureka: false
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://admin:123456@${eureka.instance.hostname}:${server.port}/eureka/
    healthcheck:
      enabled: true
spring:
  application:
    name: euraka-server
management:
  endpoint:
    health:
      enabled: true
login:
  user:
    name: admin
    password: 123456

至此Eureka配置完成,剩下配置service及customer项目,先看service项目:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.****</groupId>
        <artifactId>zipkin-p</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <groupId>com.****</groupId>
    <artifactId>service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>service</name>
    <description>Demo project for Spring Boot</description>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <version>2.0.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@EnableDiscoveryClient
@SpringBootApplication
public class ServiceApplication {

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

}
eureka:
  client:
    serviceUrl:
      defaultZone: http://admin:123456@localhost:8888/eureka/
server:
  port: 8001
spring:
  application:
    name: user-service
  zipkin:
    base-url: http://localhost:9411
  sleuth:
    sampler:
      percentage: 1.0

业务代码为:

@RestController
@RequestMapping("/home")
public class homeController {

    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    public String hello()
    {
        return "Hello,this is the service response.";
    }
}

customer项目配置为:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.****</groupId>
        <artifactId>zipkin-p</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <groupId>com.****</groupId>
    <artifactId>customer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>customer</name>
    <description>Demo project for Spring Boot</description>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <version>2.0.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>2.0.1.RELEASE</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients
public class CustomerApplication {

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

}

业务代码为:

@Component
public class helloHystrix implements service {
    @Override
    public String hello() {
        return null;
    }
}
@FeignClient(value = "${service.request.name}", fallback = helloHystrix.class)
public interface service extends BaseService {
    @RequestMapping(method = RequestMethod.GET, value = path + "/home/hello")
    String hello();
}
@RestController
@RequestMapping("/home")
public class homeController {
    @Autowired
    private service service;

    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    public String hello()
    {
        String x = service.hello();
        return "返回:"+x;
    }
}
eureka:
  client:
    serviceUrl:
      defaultZone: http://admin:123456@localhost:8888/eureka/
server:
  port: 8002
spring:
  application:
    name: customer
  zipkin:
    base-url: http://localhost:9411
  sleuth:
    sampler:
      percentage: 1.0
service:
  request:
    name: USER-SERVICE

5.运行及结果

全部完成后,启动4个项目,在8888端口查看3个项目的启动情况,之后打开9411端口,查看追踪页面,报如下错误:

This application has no explicit mapping for /error, so you are seeing this as a fallback.

Sun Sep 15 22:19:00 CST 2019
There was an unexpected error (type=Internal Server Error, status=500).
Prometheus requires that all meters with the same name have the same set of tag keys. There is already an existing meter containing tag keys [method, status, uri]. The meter you are attempting to register has keys [exception, method, status, uri].

经过查询,发现是zipkinserver项目缺失配置所致,在配置文件中添加配置即可:

management:
  metrics:
    web:
      server:
        auto-time-requests: false

重启后,查看结果,一切正常。

推荐阅读