什么是zipkin

Zipkin 是 Twitter 的一个开源项目,允许开发者收集 Twitter 各个服务上的监控数据,并提供查询接口

为什么要使用zipkin

随着业务发展,系统拆分导致系统调用链路愈发复杂一个前端请求可能最终需要调用很多次后端服务才能完成,当整个请求变慢或不可用时,我们是无法得知该请求是由某个或某些后端服务引起的,这时就需要解决如何快读定位服务故障点,以对症下药。于是就有了分布式系统调用跟踪的诞生。而zipkin就是开源分布式系统调用跟踪的佼佼者

zipkin基于google-Dapper的论文有兴趣的可以看下

google-Dapper

zipkin体系介绍

zipkin架构

zipkin怎么连接es集群_java

包含组件

  • controller 控制器
  • storage 存储
  • api 查询api
  • ui 界面

zipkin存储

zipkin存储默认使用inMemory

支持存储模式

  • inMemory
  • mysql
  • Cassandra
  • Elasticsearch

ZipKin数据模型

  • Trace:一组代表一次用户请求所包含的spans,其中根span只有一个。
  • Span: 一组代表一次HTTP/RPC请求所包含的annotations。
  • annotation:包括一个值,时间戳,主机名(留痕迹)。

几个时间

  • cs:客户端发起请求,标志Span的开始
  • sr:服务端接收到请求,并开始处理内部事务,其中sr - cs则为网络延迟和时钟抖动
  • ss:服务端处理完请求,返回响应内容,其中ss - sr则为服务端处理请求耗时
  • cr:客户端接收到服务端响应内容,标志着Span的结束,其中cr - ss则为网络延迟和时钟抖动

搭建zipkin

下载文件

启动zipkin

java -jar zipkin-server-1.22.1-exec.jar

使用elasticsearch-5.3.0作为存储启动zipkin

链接

java -jar zipkin-server-1.22.1-exec.jar --STORAGE_TYPE=elasticsearch --DES_HOSTS=http://localhost:9200
zipkin-server-1.22.1-exec.jar采用springboot编写,springboot传入参数使用--key=value.
当前为什么使用--STORAGE_TYPE,--DES_HOSTS由配置文件里面决定

zipkin 控制台

zipkin怎么连接es集群_大数据_02

zipkin 明细

zipkin怎么连接es集群_zipkin怎么连接es集群_03

zipkin 依赖

springboot+apache-httpclient使用zipkin

项目结构

zipkin怎么连接es集群_zipkin怎么连接es集群_04

pom.xml
<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.kite.zipkin</groupId>
	<artifactId>zipkin-demo-server</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>zipkin-demo-server</name>
	<url>http://maven.apache.org</url>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.2.RELEASE</version>
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<!-- brave core -->
		<dependency>
			<groupId>io.zipkin.brave</groupId>
			<artifactId>brave-core</artifactId>
			<version>3.9.0</version>
		</dependency>
		<dependency>
			<groupId>io.zipkin.brave</groupId>
			<artifactId>brave-spancollector-http</artifactId>
			<version>3.9.0</version>
		</dependency>
		<dependency>
			<groupId>io.zipkin.brave</groupId>
			<artifactId>brave-web-servlet-filter</artifactId>
			<version>3.9.0</version>
		</dependency>
		<dependency>
			<groupId>io.zipkin.brave</groupId>
			<artifactId>brave-apache-http-interceptors</artifactId>
			<version>3.9.0</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient -->
		<dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpclient</artifactId>
		</dependency>
	</dependencies>


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

			<plugin>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<source>1.7</source>
					<target>1.7</target>
					<encoding>UTF-8</encoding>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

ZipkinConfig

package com.kite.zipkin.config;


import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.github.kristofa.brave.Brave;
import com.github.kristofa.brave.Brave.Builder;
import com.github.kristofa.brave.EmptySpanCollectorMetricsHandler;
import com.github.kristofa.brave.Sampler;
import com.github.kristofa.brave.SpanCollector;
import com.github.kristofa.brave.http.DefaultSpanNameProvider;
import com.github.kristofa.brave.http.HttpSpanCollector;
import com.github.kristofa.brave.http.HttpSpanCollector.Config;
import com.github.kristofa.brave.httpclient.BraveHttpRequestInterceptor;
import com.github.kristofa.brave.httpclient.BraveHttpResponseInterceptor;
import com.github.kristofa.brave.servlet.BraveServletFilter;

@Configuration
public class ZipkinConfig {
    //span(一次请求信息或者一次链路调用)信息收集器  
    @Bean  
    public SpanCollector spanCollector() {  
        Config config = HttpSpanCollector.Config.builder()  
                .compressionEnabled(false)// 默认false,span在transport之前是否会被gzipped  
                .connectTimeout(5000)  
                .flushInterval(1)  
                .readTimeout(6000)  
                .build();  
        return HttpSpanCollector.create("http://localhost:9411", config, new EmptySpanCollectorMetricsHandler());  
    }  
      
    //作为各调用链路,只需要负责将指定格式的数据发送给zipkin  
    @Bean  
    public Brave brave(SpanCollector spanCollector){  
        Builder builder = new Builder("service1");//指定serviceName  
        builder.spanCollector(spanCollector);  
        builder.traceSampler(Sampler.create(1));//采集率  
        return builder.build();  
    }  
  
  
    //设置server的(服务端收到请求和服务端完成处理,并将结果发送给客户端)过滤器  
    @Bean  
    public BraveServletFilter braveServletFilter(Brave brave) {  
        BraveServletFilter filter = new BraveServletFilter(brave.serverRequestInterceptor(),  
                brave.serverResponseInterceptor(), new DefaultSpanNameProvider());  
        return filter;  
    }  
      
    //设置client的(发起请求和获取到服务端返回信息)拦截器  
    @Bean  
    public CloseableHttpClient okHttpClient(Brave brave){  
       CloseableHttpClient httpclient = HttpClients.custom()
                .addInterceptorFirst(new BraveHttpRequestInterceptor(brave.clientRequestInterceptor(), new DefaultSpanNameProvider()))
                .addInterceptorFirst(new BraveHttpResponseInterceptor(brave.clientResponseInterceptor()))
                .build();
        return httpclient;  
    }
    
}

ZipkinBraveController

package com.kite.zipkin.controller;

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ZipkinBraveController {

    @Autowired
    private CloseableHttpClient okHttpClient;
    
    @GetMapping("/service1")
    public String myboot() throws Exception {
        Thread.sleep(100);//100ms
        HttpGet get = new HttpGet("http://localhost:81/test");
        CloseableHttpResponse execute = okHttpClient.execute(get);
        /*
         * 1、执行execute()的前后,会执行相应的拦截器(cs,cr)
         * 2、请求在被调用方执行的前后,也会执行相应的拦截器(sr,ss)
         */
        return EntityUtils.toString(execute.getEntity(), "utf-8");
    }
}

Application启动类

package com.kite.zipkin;

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

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

======================

zipkin-demo-server-2 serviceName修改

public Brave brave(SpanCollector spanCollector){  
        Builder builder = new Builder("service2");//指定serviceName  
        builder.spanCollector(spanCollector);  
        builder.traceSampler(Sampler.create(1));//采集率  
        return builder.build();  
    }

controller修改

package com.kite.zipkin.controller;


import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ZipkinBraveController {

    @Autowired
    private CloseableHttpClient httpClient;

    @GetMapping("/test")
    public String myboot() throws Exception {
        Thread.sleep(200);//100ms
        HttpGet get1 = new HttpGet("http://localhost:82/test");
        CloseableHttpResponse execute1 = httpClient.execute(get1);
        /*
         * 1、执行execute()的前后,会执行相应的拦截器(cs,cr)
         * 2、请求在被调用方执行的前后,也会执行相应的拦截器(sr,ss)
         */
        HttpGet get2 = new HttpGet("http://localhost:83/test");
        CloseableHttpResponse execute2 = httpClient.execute(get2);

        return EntityUtils.toString(execute1.getEntity(), "utf-8") + "-" +EntityUtils.toString(execute2.getEntity(), "utf-8");
    }
}

zipkin-demo-server-3 serviceName修改

@Bean  
    public Brave brave(SpanCollector spanCollector){  
        Builder builder = new Builder("service3");//指定serviceName  
        builder.spanCollector(spanCollector);  
        builder.traceSampler(Sampler.create(1));//采集率  
        return builder.build();  
    }

controller修改

package com.kite.zipkin.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ZipkinBraveController {

    
    @GetMapping("/test")
    public String myboot() throws Exception {
        Thread.sleep(100);//100ms
        return "service3";
    }
}

zipkin-demo-server-4 serviceName修改

@Bean  
    public Brave brave(SpanCollector spanCollector){  
        Builder builder = new Builder("service4");//指定serviceName  
        builder.spanCollector(spanCollector);  
        builder.traceSampler(Sampler.create(1));//采集率  
        return builder.build();  
    }

controller修改

package com.kite.zipkin.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class ZipkinBraveController {

    
    @GetMapping("/test")
    public String myboot() throws Exception {
        Thread.sleep(100);//100ms
        return "service3";
    }
}

关注点point

  • zipkin 运行需要jdk8
  • pinpoint 可以关注下,同样是分布式链路追踪系统(ps:搭建环境1天下来,trace一直不能生成。。有谁碰到过这个问题可以回复下 0.0)

参考