最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

spring-cloud Sleuth的使用方法

 更新時間:2019年02月12日 11:15:17   作者:Degaulle  
這篇文章主要介紹了spring-cloud Sleuth的使用方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

一直沒弄明白sleuth的tracerContext是如何創(chuàng)建和傳遞的,閑來無事研究了一下。由于對sleuth的源碼不熟悉,準(zhǔn)備通過debug brave.Tracer的nextId()方法,查看方法調(diào)用棧來找來龍去脈。

首先創(chuàng)建兩個service A和B,記作srvA、srvB,在srvA中添加testA controller,sevB中添加testB controller,testA中通過Feign調(diào)用testB。

先看當(dāng)用戶通過瀏覽器調(diào)用srvA的時候,srvA是作為server的。

configuration:
TraceWebServletAutoConfiguration==>TracingFilter
TraceHttpAutoConfiguration==>HttpTracing
TraceAutoConfiguration==>Tracing
SleuthLogAutoConfiguration.Slf4jConfiguration==>CurrentTraceContext

配置中,TracingFilter在實(shí)例化時需要一個HttpTracing:

 public static Filter create(HttpTracing httpTracing) {
  return new TracingFilter(httpTracing);
 }

 //Servlet運(yùn)行時類
 final ServletRuntime servlet = ServletRuntime.get();
 //Slf4jCurrentTraceContext
 final CurrentTraceContext currentTraceContext;
 final Tracer tracer;
 final HttpServerHandler<HttpServletRequest, HttpServletResponse> handler;
 //TraceContext的數(shù)據(jù)提取器
 final TraceContext.Extractor<HttpServletRequest> extractor;

 TracingFilter(HttpTracing httpTracing) {
  tracer = httpTracing.tracing().tracer();
  currentTraceContext = httpTracing.tracing().currentTraceContext();
  handler = HttpServerHandler.create(httpTracing, ADAPTER);
  extractor = httpTracing.tracing().propagation().extractor(GETTER);
 }

HttpTracing Builder模式構(gòu)造時接收一個Tracing:

  Tracing tracing;
  //客戶端span解析器
  HttpClientParser clientParser;
  String serverName;
  //服務(wù)端span解析器
  HttpServerParser serverParser;
  HttpSampler clientSampler, serverSampler;

  Builder(Tracing tracing) {
   if (tracing == null) throw new NullPointerException("tracing == null");
   final ErrorParser errorParser = tracing.errorParser();
   this.tracing = tracing;
   this.serverName = "";
   // override to re-use any custom error parser from the tracing component
   this.clientParser = new HttpClientParser() {
    @Override protected ErrorParser errorParser() {
     return errorParser;
    }
   };
   this.serverParser = new HttpServerParser() {
    @Override protected ErrorParser errorParser() {
     return errorParser;
    }
   };
   this.clientSampler = HttpSampler.TRACE_ID;
   this.serverSampler(HttpSampler.TRACE_ID);
  }

Tracing實(shí)例化:

  @Bean
  @ConditionalOnMissingBean
  // NOTE: stable bean name as might be used outside sleuth
  Tracing tracing(@Value("${spring.zipkin.service.name:${spring.application.name:default}}") String serviceName,
      Propagation.Factory factory,
      CurrentTraceContext currentTraceContext,
      Reporter<zipkin2.Span> reporter,
      Sampler sampler,
      ErrorParser errorParser,
      SleuthProperties sleuthProperties
  ) {
    return Tracing.newBuilder()
        .sampler(sampler)
        .errorParser(errorParser)
        .localServiceName(serviceName)
        //ExtraFieldPropagation.Factory
        .propagationFactory(factory)
        .currentTraceContext(currentTraceContext)
        .spanReporter(adjustedReporter(reporter))
        .traceId128Bit(sleuthProperties.isTraceId128())
        .supportsJoin(sleuthProperties.isSupportsJoin())
        .build();
  }

下面看TracingFilter的doFilter:

  Span span = handler.handleReceive(extractor, httpRequest);

  // Add attributes for explicit access to customization or span context
  request.setAttribute(SpanCustomizer.class.getName(), span.customizer());
  request.setAttribute(TraceContext.class.getName(), span.context());

  Throwable error = null;
  Scope scope = currentTraceContext.newScope(span.context());
  try {
   // any downstream code can see Tracer.currentSpan() or use Tracer.currentSpanCustomizer()
   chain.doFilter(httpRequest, httpResponse);
  } catch (IOException | ServletException | RuntimeException | Error e) {
   error = e;
   throw e;
  } finally {
   scope.close();
   if (servlet.isAsync(httpRequest)) { // we don't have the actual response, handle later
    servlet.handleAsync(handler, httpRequest, httpResponse, span);
   } else { // we have a synchronous response, so we can finish the span
    handler.handleSend(ADAPTER.adaptResponse(httpRequest, httpResponse), error, span);
   }
  }
 }

在SleuthLogAutoConfiguration中如果有slfj的包,則注入CurrentTraceContext:

 @Configuration
  @ConditionalOnClass(MDC.class)
  @EnableConfigurationProperties(SleuthSlf4jProperties.class)
  protected static class Slf4jConfiguration {

    @Bean
    @ConditionalOnProperty(value = "spring.sleuth.log.slf4j.enabled", matchIfMissing = true)
    @ConditionalOnMissingBean
    public CurrentTraceContext slf4jSpanLogger() {
      return Slf4jCurrentTraceContext.create();
    }
    
    ...
   }

Slf4jCurrentTraceContext中,delegate就是CurrentTraceContext.Default.inheritable():

 public static final class Default extends CurrentTraceContext {
  static final ThreadLocal<TraceContext> DEFAULT = new ThreadLocal<>();
  // Inheritable as Brave 3's ThreadLocalServerClientAndLocalSpanState was inheritable
  static final InheritableThreadLocal<TraceContext> INHERITABLE = new InheritableThreadLocal<>();

  final ThreadLocal<TraceContext> local;

  //靜態(tài)方法create,local對象為ThreadLocal類型 
  /** Uses a non-inheritable static thread local */
  public static CurrentTraceContext create() {
   return new Default(DEFAULT);
  }

  //local對象為InheritableThreadLocal類型
  //官方文檔指出,inheritable方法在線程池的環(huán)境中需謹(jǐn)慎使用,可能會取出錯誤的TraceContext,這樣會導(dǎo)致Span等信息會記錄并關(guān)聯(lián)到錯誤的traceId上
  /**
   * Uses an inheritable static thread local which allows arbitrary calls to {@link
   * Thread#start()} to automatically inherit this context. This feature is available as it is was
   * the default in Brave 3, because some users couldn't control threads in their applications.
   *
   * <p>This can be a problem in scenarios such as thread pool expansion, leading to data being
   * recorded in the wrong span, or spans with the wrong parent. If you are impacted by this,
   * switch to {@link #create()}.
   */
  public static CurrentTraceContext inheritable() {
   return new Default(INHERITABLE);
  }

  Default(ThreadLocal<TraceContext> local) {
   if (local == null) throw new NullPointerException("local == null");
   this.local = local;
  }

  @Override public TraceContext get() {
   return local.get();
  }

  //替換當(dāng)前TraceContext,close方法將之前的TraceContext設(shè)置回去
  //Scope接口繼承了Closeable接口,在try中使用會自動調(diào)用close方法,為了避免用戶忘記close方法,還提供了Runnable,Callable,Executor,ExecutorService包裝方法
  @Override public Scope newScope(@Nullable TraceContext currentSpan) {
   final TraceContext previous = local.get();
   local.set(currentSpan);
   class DefaultCurrentTraceContextScope implements Scope {
    @Override public void close() {
     local.set(previous);
    }
   }
   return new DefaultCurrentTraceContextScope();
  }
 }

Slf4jCurrentTraceContext的delegate使用的就是一個InheritableThreadLocal,InheritableThreadLocal在創(chuàng)建子線程的時候,會將父線程的inheritableThreadLocals繼承下來。這樣就實(shí)現(xiàn)了TraceContext在父子線程中的傳遞。

看一下CurrentTraceContext的maybeScope:

 //返回一個新的scope,如果當(dāng)前scope就是傳入的scope,返回一個空scope
 public Scope maybeScope(@Nullable TraceContext currentSpan) {
  //獲取當(dāng)前TraceContext
  TraceContext currentScope = get();
  //如果傳入的TraceContext為空,且當(dāng)前TraceContext為空返回空scope
  if (currentSpan == null) {
   if (currentScope == null) return Scope.NOOP;
   return newScope(null);
  }
  return currentSpan.equals(currentScope) ? Scope.NOOP : newScope(currentSpan);
 }

TracingFilter中HttpServerHandler解析Request:請輸入代碼

2.srvA請求到servB時作為Client。

TraceLoadBalancerFeignClient-->LoadBalancerFeignClient-->FeignLoadBalancer-->LazyTracingFeignClient-->Client

 以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • SpringBoot使用spring retry重試機(jī)制的操作詳解

    SpringBoot使用spring retry重試機(jī)制的操作詳解

    實(shí)際工作中由于網(wǎng)絡(luò)波動等原因?qū)е麓a執(zhí)行失敗需要重新執(zhí)行,保證最終能夠完成業(yè)務(wù)功能,通常來說,會用try/catch,while循環(huán)或者定時任務(wù)重處理,但是這樣的做法缺乏統(tǒng)一性,要多寫很多代碼,spring-retry組件可以通過注解優(yōu)雅的實(shí)現(xiàn)重處理功能
    2024-12-12
  • String實(shí)例化及static final修飾符實(shí)現(xiàn)方法解析

    String實(shí)例化及static final修飾符實(shí)現(xiàn)方法解析

    這篇文章主要介紹了String實(shí)例化及static final修飾符實(shí)現(xiàn)方法解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-09-09
  • 詳解Java8新特性之interface中的static方法和default方法

    詳解Java8新特性之interface中的static方法和default方法

    這篇文章主要介紹了Java8新特性之interface中的static方法和default方法,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-08-08
  • java實(shí)現(xiàn)將ftp和http的文件直接傳送到hdfs

    java實(shí)現(xiàn)將ftp和http的文件直接傳送到hdfs

    前面幾篇文章,我們已經(jīng)做了很好的鋪墊了,幾個要用到的工具我們都做了出來,本文就是將他們集合起來,說下具體的用法,小伙伴們可以參考下。
    2015-03-03
  • Java中的clone方法詳解_動力節(jié)點(diǎn)Java學(xué)院整理

    Java中的clone方法詳解_動力節(jié)點(diǎn)Java學(xué)院整理

    clone顧名思義就是復(fù)制, 在Java語言中, clone方法被對象調(diào)用,所以會復(fù)制對象。下面通過本文給大家介紹java中的clone方法,感興趣的朋友一起看看吧
    2017-06-06
  • Spring boot redis cache的key的使用方法

    Spring boot redis cache的key的使用方法

    這篇文章主要介紹了Spring boot redis cache的key的使用方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • Eureka源碼核心類預(yù)備知識

    Eureka源碼核心類預(yù)備知識

    這篇文章主要為大家介紹了Eureka源碼核心類預(yù)備知識詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • java基礎(chǔ)的詳細(xì)了解第五天

    java基礎(chǔ)的詳細(xì)了解第五天

    這篇文章對Java編程語言的基礎(chǔ)知識作了一個較為全面的匯總,在這里給大家分享一下。需要的朋友可以參考,希望能給你帶來幫助
    2021-08-08
  • Java對象比較之equals與hashCode詳解

    Java對象比較之equals與hashCode詳解

    這篇文章主要介紹了Java對象比較之equals與hashCode詳解,equals?方法和?hashCode?方法是?Object?類中的兩個基礎(chǔ)方法,它們共同協(xié)作來判斷兩個對象是否相等,需要的朋友可以參考下
    2023-12-12
  • Java數(shù)據(jù)結(jié)構(gòu)之LinkedList的用法詳解

    Java數(shù)據(jù)結(jié)構(gòu)之LinkedList的用法詳解

    鏈表(Linked?list)是一種常見的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu),是一種線性表。Java的LinkedList(鏈表)?類似于?ArrayList,是一種常用的數(shù)據(jù)容器,本文就來簡單講講它的使用吧
    2023-05-05

最新評論

石柱| 谢通门县| 竹山县| 明水县| 永平县| 定襄县| 偃师市| 孝昌县| 高青县| 绍兴市| 乌拉特中旗| 浦东新区| 巢湖市| 永定县| 铁岭县| 洛南县| 忻城县| 京山县| 亳州市| 荣昌县| 鹰潭市| 定安县| 融水| 许昌市| 扶风县| 河南省| 天全县| 合阳县| 峨边| 和田县| 九台市| 建平县| 曲周县| 资兴市| 长沙市| 太白县| 凭祥市| 汝阳县| 夏河县| 保山市| 炉霍县|