dubbo + zipkin 實現全鏈路追蹤
阿新 • • 發佈:2019-02-20
lte parser gflags 成功 bstr factory arr hup 分布式系
隨著業務的發展,應用的規模不斷的擴大,傳統的應用架構無法滿足訴求,服務化架構改造勢在必行,以 Dubbo 為代表的分布式服務框架成為了服務化改造架構中的基石。隨著微服務理念逐漸被大眾接受,應用進一步向更細粒度拆分,並且,不同的應用由不同的開發團隊獨立負責,整個分布式系統變得十分復雜。沒有人能夠清晰及時的知道當前系統整體的依賴關系。當出現問題時,也無法及時知道具體是鏈路上的哪個環節出了問題。
本文介紹使用 dubbo zipkin 來實現全鏈路追蹤,便於清晰的看出項目中各服務的調用關系以及各鏈路的信息。
zipkin的介紹、安裝請參考http://dubbo.apache.org/zh-cn/blog/use-zipkin-in-dubbo.html 這篇文章介紹了zipkin 以及dubbo與zipkin的集成。
我主要來分享一下我在集成過程中遇到的問題:
報錯信息如下
Caused by: org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are: PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property ‘filter‘ threw exception; nested exception is java.lang.IllegalStateException: No such extension tracing forfilter/org.apache.dubbo.rpc.Filter at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:121) at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:75) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1566) ... 13 more
這裏主要是因為 我在註冊dubbo服務時添加的filter沒有找到所導致的錯誤
經過分析:註冊服務時添加的filter是從 com.alibaba.dubbo.rpc.Filter 文件中 tracing = brave.dubbo.rpc.TracingFilter 調用的TracingFilter 過濾器而不是我spring配置 文件中配置的bean。如下圖
我們配的filter=“tracing”實際調用的是下面文件中的過濾器
下面我們看一下brave.dubbo.rpc.TracingFilter中的代碼:
package brave.dubbo.rpc; import brave.Span; import brave.Span.Kind; import brave.Tracer; import brave.Tracing; import brave.internal.Platform; import brave.propagation.Propagation; import brave.propagation.TraceContext; import brave.propagation.TraceContextOrSamplingFlags; import com.alibaba.dubbo.common.Constants; import com.alibaba.dubbo.common.extension.Activate; import com.alibaba.dubbo.common.extension.ExtensionLoader; import com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory; import com.alibaba.dubbo.remoting.exchange.ResponseCallback; import com.alibaba.dubbo.rpc.Filter; import com.alibaba.dubbo.rpc.Invocation; import com.alibaba.dubbo.rpc.Invoker; import com.alibaba.dubbo.rpc.Result; import com.alibaba.dubbo.rpc.RpcContext; import com.alibaba.dubbo.rpc.RpcException; import com.alibaba.dubbo.rpc.protocol.dubbo.FutureAdapter; import com.alibaba.dubbo.rpc.support.RpcUtils; import java.net.InetSocketAddress; import java.util.Map; import java.util.concurrent.Future; @Activate(group = {Constants.PROVIDER, Constants.CONSUMER}, value = "tracing") // http://dubbo.io/books/dubbo-dev-book-en/impls/filter.html // public constructor permitted to allow dubbo to instantiate this public final class TracingFilter implements Filter { Tracer tracer; TraceContext.Extractor<Map<String, String>> extractor; TraceContext.Injector<Map<String, String>> injector; /** * {@link ExtensionLoader} supplies the tracing implementation which must be named "tracing". For * example, if using the {@link SpringExtensionFactory}, only a bean named "tracing" will be * injected. */ public void setTracing(Tracing tracing) { tracer = tracing.tracer(); extractor = tracing.propagation().extractor(GETTER); injector = tracing.propagation().injector(SETTER); } @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(); } } } static void parseRemoteAddress(RpcContext rpcContext, Span span) { InetSocketAddress remoteAddress = rpcContext.getRemoteAddress(); if (remoteAddress == null) return; span.remoteIpAndPort(Platform.get().getHostString(remoteAddress), remoteAddress.getPort()); } static void onError(Throwable error, Span span) { span.error(error); if (error instanceof RpcException) { span.tag("dubbo.error_code", Integer.toString(((RpcException) error).getCode())); } } static final Propagation.Getter<Map<String, String>, String> GETTER = new Propagation.Getter<Map<String, String>, String>() { @Override public String get(Map<String, String> carrier, String key) { return carrier.get(key); } @Override public String toString() { return "Map::get"; } }; static final Propagation.Setter<Map<String, String>, String> SETTER = new Propagation.Setter<Map<String, String>, String>() { @Override public void put(Map<String, String> carrier, String key, String value) { carrier.put(key, value); } @Override public String toString() { return "Map::set"; } }; static final class FinishSpanCallback implements ResponseCallback { final Span span; FinishSpanCallback(Span span) { this.span = span; } @Override public void done(Object response) { span.finish(); } @Override public void caught(Throwable exception) { onError(exception, span); span.finish(); } } }
我們可以發現類上面的這個註解 @Activate(group = {Constants.PROVIDER, Constants.CONSUMER}, value = "tracing")
註入的值是tracing 這時調用的才是我們在配置文件中的bean。
形象圖如下:
![技術分享圖片](http://image.bubuko.com/info/201902/20190220193630226385.png)
導包歷史如下:
調整完事啟動服務完美運行: 依賴關系展示成功
dubbo + zipkin 實現全鏈路追蹤