文档章节

采用brave接入zipkin实现自定义rpc跟踪

郑浩锋
 郑浩锋
发布于 2016/08/23 20:35
字数 856
阅读 3170
收藏 8

本文假设你已经阅读过Dapper文章:http://bigbully.github.io/Dapper-translation/,对分布式服务跟踪有了初步了解。另一篇zipkin的介绍文章(基础篇)可以参考:http://www.tangrui.net/implement-distributed-tracking-system-with-zipkin-and-brave/?utm_source=tuicool&utm_medium=referral

本文旨在介绍最新的Brave版本的使用,如何模拟出Dapper的调用链效果。

实现效果

定义有两个模块之间的调用,appserver服务调用datacenter服务。

其中由外部网络调用appserver的group_data接口,然后group_data再分别调用datacenter的get_radio_list、get_user_list、get_program_list三个接口。

代码

现在,为了模拟出这个调用层级,给大家理解brave的使用。给出了模拟的代码例子:

import java.util.ArrayList;
import java.util.Collection;
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

import com.github.kristofa.brave.Brave;
import com.github.kristofa.brave.ClientRequestAdapter;
import com.github.kristofa.brave.ClientRequestInterceptor;
import com.github.kristofa.brave.ClientResponseAdapter;
import com.github.kristofa.brave.ClientResponseInterceptor;
import com.github.kristofa.brave.EmptySpanCollectorMetricsHandler;
import com.github.kristofa.brave.KeyValueAnnotation;
import com.github.kristofa.brave.ServerRequestAdapter;
import com.github.kristofa.brave.ServerRequestInterceptor;
import com.github.kristofa.brave.ServerResponseAdapter;
import com.github.kristofa.brave.ServerResponseInterceptor;
import com.github.kristofa.brave.SpanId;
import com.github.kristofa.brave.TraceData;
import com.github.kristofa.brave.http.HttpSpanCollector;
import com.twitter.zipkin.gen.Endpoint;

public class BraveTest {
	
	private static HttpSpanCollector collector = null;
	private static Brave brave = null;
	private static Brave brave2 = null;
	
	private static void braveInit(){
		collector = HttpSpanCollector.create("http://localhost:9411/", new EmptySpanCollectorMetricsHandler());

		brave = new Brave.Builder("appserver").spanCollector(collector).build();
		brave2 = new Brave.Builder("datacenter").spanCollector(collector).build();
	}
	
	static class Task {
		String name;
		SpanId spanId;
		public Task(String name, SpanId spanId) {
			super();
			this.name = name;
			this.spanId = spanId;
		}
	}

	public static void main(String[] args) throws Exception {
		braveInit();
		
		final BlockingQueue<Task> queue = new ArrayBlockingQueue<Task>(10);
		Thread thread = new Thread(){
			public void run() {
				while (true) {
					try {
						Task task = queue.take();
						dcHandle(task.name, task.spanId);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			}
		};
		thread.start();
		
		{
			ServerRequestInterceptor serverRequestInterceptor = brave.serverRequestInterceptor();
			ServerResponseInterceptor serverResponseInterceptor = brave.serverResponseInterceptor();
			ClientRequestInterceptor clientRequestInterceptor = brave.clientRequestInterceptor();
			ClientResponseInterceptor clientResponseInterceptor = brave.clientResponseInterceptor();
			
			serverRequestInterceptor.handle(new ServerRequestAdapterImpl("group_data"));
			
			ClientRequestAdapterImpl clientRequestAdapterImpl = new ClientRequestAdapterImpl("get_radio_list");
			clientRequestInterceptor.handle(clientRequestAdapterImpl);
			queue.offer(new Task("get_radio_list", clientRequestAdapterImpl.getSpanId()));
			Thread.sleep(10);
			clientResponseInterceptor.handle(new ClientResponseAdapterImpl());
			
			clientRequestAdapterImpl = new ClientRequestAdapterImpl("get_user_list");
			clientRequestInterceptor.handle(clientRequestAdapterImpl);
			queue.offer(new Task("get_user_list", clientRequestAdapterImpl.getSpanId()));
			Thread.sleep(10);
			clientResponseInterceptor.handle(new ClientResponseAdapterImpl());
			
			clientRequestAdapterImpl = new ClientRequestAdapterImpl("get_program_list");
			clientRequestInterceptor.handle(clientRequestAdapterImpl);
			queue.offer(new Task("get_program_list", clientRequestAdapterImpl.getSpanId()));
			Thread.sleep(10);
			clientResponseInterceptor.handle(new ClientResponseAdapterImpl());
			
			serverResponseInterceptor.handle(new ServerResponseAdapterImpl());
		}
		Thread.sleep(3000);
	}
	
	public static void dcHandle(String spanName, SpanId spanId){
		ServerRequestInterceptor serverRequestInterceptor = brave2.serverRequestInterceptor();
		ServerResponseInterceptor serverResponseInterceptor = brave2.serverResponseInterceptor();
		serverRequestInterceptor.handle(new ServerRequestAdapterImpl(spanName, spanId));
		serverResponseInterceptor.handle(new ServerResponseAdapterImpl());
	}
	
	
	static class ServerRequestAdapterImpl implements ServerRequestAdapter {
		
		Random randomGenerator = new Random();
		SpanId spanId;
		String spanName;
		
		ServerRequestAdapterImpl(String spanName){
			this.spanName = spanName;
			long startId = randomGenerator.nextLong();
			SpanId spanId = SpanId.builder().spanId(startId).traceId(startId).parentId(startId).build();
			this.spanId = spanId;
		}
		
		ServerRequestAdapterImpl(String spanName, SpanId spanId){
			this.spanName = spanName;
			this.spanId = spanId;
		}

		@Override
		public TraceData getTraceData() {
			if (this.spanId != null) {
				return TraceData.builder().spanId(this.spanId).build();
			}
			long startId = randomGenerator.nextLong();
			SpanId spanId = SpanId.builder().spanId(startId).traceId(startId).parentId(startId).build();
			return TraceData.builder().spanId(spanId).build();
		}

		@Override
		public String getSpanName() {
			return spanName;
		}

		@Override
		public Collection<KeyValueAnnotation> requestAnnotations() {
			Collection<KeyValueAnnotation> collection = new ArrayList<KeyValueAnnotation>();
			KeyValueAnnotation kv = KeyValueAnnotation.create("radioid", "165646485468486364");
			collection.add(kv);
			return collection;
		}
		
	}
	
	static class ServerResponseAdapterImpl implements ServerResponseAdapter {

		@Override
		public Collection<KeyValueAnnotation> responseAnnotations() {
			Collection<KeyValueAnnotation> collection = new ArrayList<KeyValueAnnotation>();
			KeyValueAnnotation kv = KeyValueAnnotation.create("radioid", "165646485468486364");
			collection.add(kv);
			return collection;
		}
		
	}
	
	static class ClientRequestAdapterImpl implements ClientRequestAdapter {
		
		String spanName;
		SpanId spanId;
		
		ClientRequestAdapterImpl(String spanName){
			this.spanName = spanName;
		}
		
		public SpanId getSpanId() {
			return spanId;
		}

		@Override
		public String getSpanName() {
			return this.spanName;
		}

		@Override
		public void addSpanIdToRequest(SpanId spanId) {
			//记录传输到远程服务
			System.out.println(spanId);
			if (spanId != null) {
				this.spanId = spanId;
				System.out.println(String.format("trace_id=%s, parent_id=%s, span_id=%s", spanId.traceId, spanId.parentId, spanId.spanId));
			}
		}

		@Override
		public Collection<KeyValueAnnotation> requestAnnotations() {
			Collection<KeyValueAnnotation> collection = new ArrayList<KeyValueAnnotation>();
			KeyValueAnnotation kv = KeyValueAnnotation.create("radioid", "165646485468486364");
			collection.add(kv);
			return collection;
		}

		@Override
		public Endpoint serverAddress() {
			return null;
		}
		
	}

	static class ClientResponseAdapterImpl implements ClientResponseAdapter {

		@Override
		public Collection<KeyValueAnnotation> responseAnnotations() {
			Collection<KeyValueAnnotation> collection = new ArrayList<KeyValueAnnotation>();
			KeyValueAnnotation kv = KeyValueAnnotation.create("radioname", "火星人1");
			collection.add(kv);
			return collection;
		}
		
	}
}

maven的依赖包:

    <dependency>
		<groupId>io.zipkin.brave</groupId>
		<artifactId>brave-spancollector-http</artifactId>
		<version>3.9.0</version>
	</dependency>

结果

把下载好的zipkin-server.jar包运行起来:java -jar zipkin-server.jar

然后运行上面测试代码后,用浏览器打开web UI:http://localhost:9411/

点击上面红色方框的记录

可以看到每个请求消耗的时间和调用顺序,点击第一个datacenter的调用记录,显示如下:

上面的弹窗框展示了一个调用从Client Send->Server Receive->Server Send->Client Receive的完整耗时。(Relative Time相对时间)

© 著作权归作者所有

郑浩锋
粉丝 8
博文 9
码字总数 6164
作品 0
广州
架构师
私信 提问
加载中

评论(2)

吴峻申
吴峻申
HttpSpanCollector已经找不到了。楼主要升级一下
吴峻申
吴峻申
HttpSpanCollector已经找不到了。楼主要升级一下
分布式跟踪系统-cicada

https://github.com/Yirendai/cicada/blob/master/cicada-docs/cicadadesign.md 背景与目标 面对日趋复杂的分布式系统,如服务框架、消息中间件、缓存、数据层等,我司在业务性能瓶颈定位、故...

tantexian
2016/11/02
968
1
各大厂分布式链路跟踪系统架构对比

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

james8888
2018/04/19
0
0
服务化改造实践(三) | Dubbo + Zipkin

随着业务的发展,应用的规模不断的扩大,传统的应用架构无法满足诉求,服务化架构改造势在必行,以 Dubbo 为代表的分布式服务框架成为了服务化改造架构中的基石。随着微服务理念逐渐被大众接...

阿里云云栖社区
2018/10/24
0
0
强子哥哥/MyEye

#MyEye 公司内部接入了64个产品,每天写入HBase数据量(100G/天).水平扩展就可以支持日TB级数据量。 上线12个月非常稳定! #官方QQ群: 120734278 技术选型如下:(其中MyThrift请参考本人的另外...

强子哥哥
2016/12/24
0
0
分布式调用链调研(pinpoint,skywalking,jaeger,zipkin等对比)

APM简述 APM (Application Performance Management)是对企业的应用系统进行实时监控,它是用于实现对应用程序性能管理和故障管理的系统化的解决方案。 2.APM主要解决的问题: 集中式度量系...

helplove
01/24
5.6K
0

没有更多内容

加载失败,请刷新页面

加载更多

mysql-connector-java升级到8.0后保存时间到数据库出现了时差

在一个新项目中用到了新版的mysql jdbc 驱动 <dependency>     <groupId>mysql</groupId>     <artifactId>mysql-connector-java</artifactId>     <version>8.0.18</version> ......

ValSong
56分钟前
5
0
Spring Boot 如何部署到 Linux 中的服务

打包完成后的 Spring Boot 程序如何部署到 Linux 上的服务? 你可以参考官方的有关部署 Spring Boot 为 Linux 服务的文档。 文档链接如下: https://docs.ossez.com/spring-boot-docs/docs/r...

honeymoose
58分钟前
5
0
Spring Boot 2 实战:使用 Spring Boot Admin 监控你的应用

1. 前言 生产上对 Web 应用 的监控是十分必要的。我们可以近乎实时来对应用的健康、性能等其他指标进行监控来及时应对一些突发情况。避免一些故障的发生。对于 Spring Boot 应用来说我们可以...

码农小胖哥
今天
6
0
ZetCode 教程翻译计划正式启动 | ApacheCN

原文:ZetCode 协议:CC BY-NC-SA 4.0 欢迎任何人参与和完善:一个人可以走的很快,但是一群人却可以走的更远。 ApacheCN 学习资源 贡献指南 本项目需要校对,欢迎大家提交 Pull Request。 ...

ApacheCN_飞龙
今天
4
0
CSS定位

CSS定位 relative相对定位 absolute绝对定位 fixed和sticky及zIndex relative相对定位 position特性:css position属性用于指定一个元素在文档中的定位方式。top、right、bottom、left属性则...

studywin
今天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部