`

Dubbo + Zipkin + Brave 实现全链路追踪

阅读更多

       这两天看了好几篇帖子,写zipkin与dubbo整合的内容都不全面,忍不住亲自上手码一遍。

       利用zipkin可以对dubbo进行调用链监控,可以查到调用链中的dubbo服务的性能,并且dubbo提供了SPI的接口,能很容易完成并自定义相应的filter去监控dubbo服务。

ZipKin介绍 

Zipkin是一个致力于收集分布式服务的时间数据的分布式跟踪系统。

Zipkin 主要涉及四个组件:collector(数据采集),storage(数据存储),search(数据查询),UI(数据展示)。

github源码地址:https://github.com/openzipkin/zipkin。

Zipkin提供了可插拔数据存储方式:In-Memory,MySql, Cassandra, Elasticsearch

ZipKin部署与运行 (注意需要在linux下运行,JDK1.8)

1、下载zipkin

http://central.maven.org/maven2/io/zipkin/java/zipkin-server/2.11.7/zipkin-server-2.11.7-exec.jar

2、运行zipkin

(1)In-Memory方式 

nohup java -jar zipkin-server-2.11.7-exec.jar &

 

注意:内存存储,zipkin重启后数据会丢失,建议测试环境使用


(2)MySql方式 

目前只与MySQL的5.6-7。它的设计是易于理解,使用简单。但是,当数据量大时,查询很慢。性能不是很好。

创建数据库zipkin 
建表 

CREATE TABLE IF NOT EXISTS zipkin_spans ( 
`trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit', 
`trace_id` BIGINT NOT NULL, 
`id` BIGINT NOT NULL, 
`name` VARCHAR(255) NOT NULL, 
`parent_id` BIGINT, 
`debug` BIT(1), 
`start_ts` BIGINT COMMENT 'Span.timestamp(): epoch micros used for endTs query and to implement TTL', 
`duration` BIGINT COMMENT 'Span.duration(): micros used for minDuration and maxDuration query' 
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci; 
ALTER TABLE zipkin_spans ADD UNIQUE KEY(`trace_id_high`, `trace_id`, `id`) COMMENT 'ignore insert on duplicate'; 
ALTER TABLE zipkin_spans ADD INDEX(`trace_id_high`, `trace_id`, `id`) COMMENT 'for joining with zipkin_annotations'; 
ALTER TABLE zipkin_spans ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTracesByIds'; 
ALTER TABLE zipkin_spans ADD INDEX(`name`) COMMENT 'for getTraces and getSpanNames'; 
ALTER TABLE zipkin_spans ADD INDEX(`start_ts`) COMMENT 'for getTraces ordering and range'; 
CREATE TABLE IF NOT EXISTS zipkin_annotations ( 
`trace_id_high` BIGINT NOT NULL DEFAULT 0 COMMENT 'If non zero, this means the trace uses 128 bit traceIds instead of 64 bit', 
`trace_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.trace_id', 
`span_id` BIGINT NOT NULL COMMENT 'coincides with zipkin_spans.id', 
`a_key` VARCHAR(255) NOT NULL COMMENT 'BinaryAnnotation.key or Annotation.value if type == -1', 
`a_value` BLOB COMMENT 'BinaryAnnotation.value(), which must be smaller than 64KB', 
`a_type` INT NOT NULL COMMENT 'BinaryAnnotation.type() or -1 if Annotation', 
`a_timestamp` BIGINT COMMENT 'Used to implement TTL; Annotation.timestamp or zipkin_spans.timestamp', 
`endpoint_ipv4` INT COMMENT 'Null when Binary/Annotation.endpoint is null', 
`endpoint_ipv6` BINARY(16) COMMENT 'Null when Binary/Annotation.endpoint is null, or no IPv6 address', 
`endpoint_port` SMALLINT COMMENT 'Null when Binary/Annotation.endpoint is null', 
`endpoint_service_name` VARCHAR(255) COMMENT 'Null when Binary/Annotation.endpoint is null' 
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci; 
ALTER TABLE zipkin_annotations ADD UNIQUE KEY(`trace_id_high`, `trace_id`, `span_id`, `a_key`, `a_timestamp`) COMMENT 'Ignore insert on duplicate'; 
ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`, `span_id`) COMMENT 'for joining with zipkin_spans'; 
ALTER TABLE zipkin_annotations ADD INDEX(`trace_id_high`, `trace_id`) COMMENT 'for getTraces/ByIds'; 
ALTER TABLE zipkin_annotations ADD INDEX(`endpoint_service_name`) COMMENT 'for getTraces and getServiceNames'; 
ALTER TABLE zipkin_annotations ADD INDEX(`a_type`) COMMENT 'for getTraces'; 
ALTER TABLE zipkin_annotations ADD INDEX(`a_key`) COMMENT 'for getTraces'; 
ALTER TABLE zipkin_annotations ADD INDEX(`trace_id`, `span_id`, `a_key`) COMMENT 'for dependencies job'; 
CREATE TABLE IF NOT EXISTS zipkin_dependencies ( 
`day` DATE NOT NULL, 
`parent` VARCHAR(255) NOT NULL, 
`child` VARCHAR(255) NOT NULL, 
`call_count` BIGINT 
) ENGINE=InnoDB ROW_FORMAT=COMPRESSED CHARACTER SET=utf8 COLLATE utf8_general_ci; 
ALTER TABLE zipkin_dependencies ADD UNIQUE KEY(`day`, `parent`, `child`); 

 

启动zipkin命令 

 

STORAGE_TYPE=mysql MYSQL_HOST=IP MYSQL_TCP_PORT=3306 MYSQL_DB=zipkin MYSQL_USER=username MYSQL_PASS=password nohup java -jar zipkin-server-2.11.7-exec.jar &
 

(3)Elasticsearch方式 

创建elasticsearch用户,安装启动Elasticsearch服务 
官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html 
zipkin启动命令

STORAGE_TYPE=elasticsearch ES_HOSTS=http://IP:9200 nohup java -jar zipkin-server-2.11.7-exec.jar &
 启动成功访问地址:http://192.168.20.15:9411/zipkin/(192.168.20.15替换为对应zipkin部署服务器地址)

 效果图如下:

整合

  简单的描述一下,同ServletFilter一样,在dubbo中利用Filter过滤请求,传递TraceId等参数,生成相应的span传递给zipkin服务器。

  引入brave-instrumentation-dubbo-rpc包,这是一个SPI的Filter包。

<dependencies>
      <dependency>
	    <groupId>io.zipkin.reporter2</groupId>
	    <artifactId>zipkin-sender-okhttp3</artifactId>
	    <version>2.7.10</version>
      </dependency>

      <dependency>
             <groupId>io.zipkin.brave</groupId>
             <artifactId>brave-instrumentation-dubbo-rpc</artifactId>
             <version>5.4.3</version>
       </dependency>
</dependencies>
 brave-instrumentation-dubbo-rpc包里面有一个TracingFilter的类,在其invoke方法中实现了对span的一些操作。

 

@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
    if (tracer == null) return invoker.invoke(invocation);

    RpcContext rpcContext = RpcContext.getContext();
    Kind kind = rpcContext.isProviderSide() ? Kind.SERVER : Kind.CLIENT;
    final Span span;
    if (kind.equals(Kind.CLIENT)) {
      span = tracer.nextSpan();
      injector.inject(span.context(), invocation.getAttachments());
    } else {
      TraceContextOrSamplingFlags extracted = extractor.extract(invocation.getAttachments());
      span = extracted.context() != null
          ? tracer.joinSpan(extracted.context())
          : tracer.nextSpan(extracted);
    }

    if (!span.isNoop()) {
      span.kind(kind);
      String service = invoker.getInterface().getSimpleName();
      String method = RpcUtils.getMethodName(invocation);
      span.name(service + "/" + method);
      parseRemoteAddress(rpcContext, span);
      span.start();
    }

    boolean isOneway = false, deferFinish = false;
    try (Tracer.SpanInScope scope = tracer.withSpanInScope(span)) {
      Result result = invoker.invoke(invocation);
      if (result.hasException()) {
        onError(result.getException(), span);
      }
      isOneway = RpcUtils.isOneway(invoker.getUrl(), invocation);
      Future<Object> future = rpcContext.getFuture(); // the case on async client invocation
      if (future instanceof FutureAdapter) {
        deferFinish = true;
        ((FutureAdapter) future).getFuture().setCallback(new FinishSpanCallback(span));
      }
      return result;
    } catch (Error | RuntimeException e) {
      onError(e, span);
      throw e;
    } finally {
      if (isOneway) {
        span.flush();
      } else if (!deferFinish) {
        span.finish();
      }
    }
  }
   该Filter是以SPI的方式引入dubbo的,在默认文件/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter中,有这样的声明:
tracing=brave.dubbo.rpc.TracingFilter
   然后在dubbo的配置中引入该Filter即可。
wholly-dubbo-provider.xml
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
	http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

	<!--指定Spring配置中用到的属性文件 -->
	<bean id="propertyConfig"
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>classpath:brave.properties</value>
			</list>
		</property>
	</bean>
	
	<bean id="zipkinProperties" class="com.whollyframework.dubbo.config.ZipkinProperties">
		<property name="serviceName" value ="${brave.name}"/>
		<property name="url" value ="${http.sender.address}"/>
		<property name="connectTimeout" value ="${http.sender.connectTimeout}"/>
		<property name="readTimeout" value ="${http.sender.readTimeout}"/>
	</bean>
    <!-- 提供方应用信息,用于计算依赖关系 -->
    <dubbo:application name="demo-provider"/>

    <!-- 使用multicast广播注册中心暴露服务地址 -->
    <!-- <dubbo:registry address="multicast://224.5.6.7:1234"/> -->
    <dubbo:registry address="zookeeper://localhost:2181"/>

    <!-- 用dubbo协议在20880端口暴露服务 -->
    <dubbo:protocol name="dubbo" port="20880"/>

    <!-- 和本地bean一样实现服务 -->
    <bean id="demoService" class="com.whollyframework.dubbo.provider.DemoServiceImpl"/>

    <!-- 声明需要暴露的服务接口 -->
    <dubbo:service interface="com.whollyframework.dubbo.api.DemoService" ref="demoService"/>

	<context:component-scan base-package="com.whollyframework.dubbo" />
	<dubbo:provider filter="tracing" />
</beans>
wholly-dubbo-consumer.xml
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
	http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">

	<!--指定Spring配置中用到的属性文件 -->
	<bean id="propertyConfig"
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>classpath:brave.properties</value>
			</list>
		</property>
	</bean>
	
	<bean id="zipkinProperties" class="com.whollyframework.dubbo.config.ZipkinProperties">
		<property name="serviceName" value ="${brave.name}"/>
		<property name="url" value ="${http.sender.address}"/>
		<property name="connectTimeout" value ="${http.sender.connectTimeout}"/>
		<property name="readTimeout" value ="${http.sender.readTimeout}"/>
	</bean>
	
    <!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
    <dubbo:application name="demo-consumer"/>

    <!-- 使用multicast广播注册中心暴露发现服务地址 -->
    <!-- <dubbo:registry address="multicast://224.5.6.7:1234"/> -->
    <dubbo:registry address="zookeeper://localhost:2181"/>

    <!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
    <dubbo:reference id="demoService" check="false" interface="com.whollyframework.dubbo.api.DemoService"/>
	
	<context:component-scan base-package="com.whollyframework.dubbo" />
	<dubbo:consumer filter="tracing" />
</beans>
 brave.properties
brave.name=provider
http.sender.address=http://192.168.20.15:9411/api/v2/spans
http.sender.connectTimeout=5000
http.sender.readTimeout=10000
 然后还需要为该Filter注入一个Tracing实例,并且该实例名必须为tracing。
@Configuration
public class ZipkinConfiguration {

    @Autowired
    private ZipkinProperties properties;

    @Bean
    public Tracing tracing(){

        Sender sender = OkHttpSender.create(properties.getUrl());

        AsyncReporter reporter = AsyncReporter.builder(sender)
                .closeTimeout(properties.getConnectTimeout(), TimeUnit.MILLISECONDS)
                .messageTimeout(properties.getReadTimeout(), TimeUnit.MILLISECONDS)
                .build();

        Tracing tracing = Tracing.newBuilder()
                .localServiceName(properties.getServiceName())
                .propagationFactory(ExtraFieldPropagation.newFactory(B3Propagation.FACTORY, "shiliew"))
                .sampler(Sampler.ALWAYS_SAMPLE)
                .spanReporter(reporter)
                .build();
        return tracing;
    }
}
 Tracing类的主要作用是针对span的操作做一些配置,并设置上传zipkin服务器。

效果

  在这里不演示如何配置dubbo服务,之前的博文有相关介绍。效果图如下:


示例下载:zipkin+dubbo整合示例

 

参考:

zipkin与dubbo整合-https://shiliewrain.github.io/2018/07/20/zipkin2-dubbo/

dubbo+zipkin调用链监控-https://www.cnblogs.com/ASPNET2008/p/6709900.html

  • 大小: 28.9 KB
  • 大小: 14.9 KB
分享到:
评论

相关推荐

    springboot+dubbo+zookeeper构建的分布式调用服务框架

    在这个"springboot+dubbo+zookeeper"的项目中,开发者使用SpringBoot作为基础框架,构建微服务应用。SpringBoot的自动配置特性使得初始化和配置过程更加简洁。然后,Dubbo被引入作为服务治理框架,它允许服务提供者...

    dubbo+cloud全链路灰度设计

    dubbo+cloud全链路灰度设计是指在云原生平台下,使用dubbo和cloud技术实现全链路灰度发布的解决方案。该方案旨在解决微服务架构中服务之间的依赖关系错综复杂的问题,通过引流一小部分流量到新版本,可以及时发现...

    dubbo+zookeeper+spring+springMVC+mybatis

    【标题】"dubbo+zookeeper+spring+springMVC+mybatis" 描述了一个基于这些技术构建的服务消费方与服务提供方的项目架构。在这个架构中,`Dubbo`是核心的服务框架,它负责服务的注册与发现;`Zookeeper`作为注册中心...

    springcloudalibaba微服务dubbo+sentinel+gateway+zookeeper+nacos的demo

    这个“springcloudalibaba微服务dubbo+sentinel+gateway+zookeeper+nacos的demo”压缩包文件,显然是一个实战示例,旨在帮助开发者理解并实践这些关键组件的集成与使用。下面将详细解析这些组件以及它们在微服务架构...

    ZooKeeper+dubbo+springMvc+Mybatis+Mysql 例子

    ZooKeeper+dubbo+springMvc+Mybatis+Mysql实例,项目是由maven搭建的 整合Dubbo\spring\springMvc\Mybatis,整个压缩包中有两个项目分别是提供者和消费,启动方式是打成WAR形式放到tomcat中启动。

    基于SpringBoot+Dubbo+React+ELK+区块链的阿梨房屋中介系统.docx

    基于SpringBoot+Dubbo+React+ELK+区块链的阿梨房屋中介系统.docx基于SpringBoot+Dubbo+React+ELK+区块链的阿梨房屋中介系统.docx基于SpringBoot+Dubbo+React+ELK+区块链的阿梨房屋中介系统.docx基于SpringBoot+Dubbo...

    Springboot+Redis+Dubbo+Rocketmq

    标题 "Springboot+Redis+Dubbo+Rocketmq" 暗示了这是一个关于构建分布式系统的技术组合,其中Springboot作为基础框架,Redis用于缓存管理,Dubbo是服务治理框架,而Rocketmq则是消息中间件。现在,我们将深入探讨...

    基于SpringBoot+Dubbo+React+ELK+区块链的阿梨房屋中介系统.pdf

    基于SpringBoot+Dubbo+React+ELK+区块链的阿梨房屋中介系统.pdf基于SpringBoot+Dubbo+React+ELK+区块链的阿梨房屋中介系统.pdf基于SpringBoot+Dubbo+React+ELK+区块链的阿梨房屋中介系统.pdf基于SpringBoot+Dubbo+...

    zookeeper+dubbo+spring

    而“dubbo-provider”目录则包含了服务提供者的实现,它对外发布服务,供消费者调用。"dubbo-api"目录可能包含共享的接口定义,确保消费者和服务提供者之间的一致性。 **Spring** 是一个全面的Java应用开发框架,它...

    springBoot+dubbo+zookeeper分布式微服务

    本项目"springBoot+dubbo+zookeeper分布式微服务"充分利用了这三个组件的优势,构建了一个高效、可扩展且易于维护的服务网络。以下是对这些技术及其整合应用的详细说明: **SpringBoot** SpringBoot是Spring框架的...

    如何零基础搭建一套微服务框架(Spring Boot+Dubbo+Docker+Jenkins)

    如何零基础搭建一套微服务框架(Spring Boot+Dubbo+Docker+Jenkins)

    Springmvc+dubbo+mybatis+mysql+redis

    标题 "Springmvc+dubbo+mybatis+mysql+redis" 描述了一个基于Java技术栈的分布式微服务架构。在这个系统中,SpringMVC作为前端控制器处理HTTP请求,Dubbo用于服务治理,MyBatis是持久层框架,MySQL是关系型数据库,...

    springboot+dubbo+zookeeper+fluent-mybatis+swagger+mysql.zip

    使用springboot+dubbo+zookeeper+fluent-mybatis+swagger+mysql搭建的简单案例

    Spring Boot 整合 Dubbo + Zookeeper 实现服务者与消费者的数据调用

    1.SpringBoot聚合工程整合Dubbo,实现服务提供者与服务消费者的数据调用, 2.该项目提高了自己对Spring Boot整合Dubbo的理解,并深刻的认识到了服务者与消费者之间的调用及流程 4. Dubbo配置全部采用yml文件配置,...

    springboot+dubbo+nacos+mybatisplus+swagger+mysql

    【标题】"springboot+dubbo+nacos+mybatisplus+swagger+mysql" 是一个集成性的技术栈,用于构建高效、可扩展的企业级微服务应用。这个项目整合了多个流行的开源框架,包括Spring Boot、Dubbo、Nacos、MyBatis Plus、...

    dubbo+zk+ssm源码+dubbo-admin

    《深入理解Dubbo+SSM+Zookeeper:构建分布式服务架构》 在现代软件开发中,分布式服务架构已经成为企业级应用的重要组成部分。本资源包涵盖了"Dubbo+SSM+Zookeeper"这一经典组合,旨在帮助开发者更好地理解和运用...

    mavan+dubbo+spring+zookeeper

    在这个"Mavan+dubbo+spring+zookeeper"的项目实践中,我们将深入理解这些技术如何协同工作,以解决初学者可能遇到的问题。 1. Maven:Maven是一个项目管理和综合工具,它简化了Java项目的构建过程。通过定义项目的...

    DUBBO+Zookeeper小例子

    本示例"**DUBBO+Zookeeper小例子**"旨在演示如何利用SpringMVC、Dubbo和Zookeeper来实现一个微服务架构。这是一次将这些组件集成到一起的实际操作,通过IDEA(IntelliJ IDEA)开发环境进行。在开始之前,确保你已...

    nginx+springboot+zookeeper+dubbo+mybatis+dubboadmin一步到位

    自己手动搭建的nginx+springboot+zookeeper+dubbo+mybatis+dubboadmin,nginx做前后端分离,负载均衡,springboot+zookeeper+dubbo做后端接口,mybatis为数据库持久化层,dubboadmin做监控中心,解压直接用idea导入...

    dubbo+zookeper+jar demo

    在这个项目中,我们将深入理解Dubbo和ZooKeeper的核心概念,以及如何将它们结合起来实现服务的注册与发现。 **Dubbo** 是阿里巴巴开源的一款高性能、轻量级的Java RPC框架,它提供了丰富的服务治理功能,如服务注册...

Global site tag (gtag.js) - Google Analytics