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

原创
2016/08/23 20:35
阅读数 6K

本文假设你已经阅读过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相对时间)

展开阅读全文
打赏
1
8 收藏
分享
加载中
HttpSpanCollector已经找不到了。楼主要升级一下
2018/02/25 14:11
回复
举报
HttpSpanCollector已经找不到了。楼主要升级一下
2018/02/25 14:11
回复
举报
更多评论
打赏
2 评论
8 收藏
1
分享
返回顶部
顶部