<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【分布式日志系統(tǒng)】springboot+zipkin+dubbo實(shí)現(xiàn)鏈路跟蹤(下)

          共 10527字,需瀏覽 22分鐘

           ·

          2022-05-04 14:40


          上一篇寫了《【分布式日志系統(tǒng)】springboot+zipkin+dubbo實(shí)現(xiàn)鏈路跟蹤(上)》《【分布式日志系統(tǒng)】springboot+zipkin+dubbo實(shí)現(xiàn)鏈路跟蹤(中)》,有興趣的小伙伴可以往回翻翻,這一篇解決如何跟蹤。

          一、基本操作
          1. pom添加依賴(常規(guī)操作);

          2. 定義公共跟蹤配置類

          3. dubbo服務(wù)端和調(diào)用端集成相應(yīng)配置(主要是yaml中配置);

          4. 驗(yàn)證。

          二、環(huán)境介紹

          提示:可能不同的框架版本會(huì)導(dǎo)致有些地方不生效(如sleuth不支持apache版的dubbo),大家在集成的過(guò)程中有問(wèn)題可以私信我,共同探討。主框架版本如下:springboot 2.6.6、 dubbo 2.7.12、 zipkin 2.16.3、 brave 5.13.3 nacos-discovery-spring-boot-starter 0.2.10、 nacos-config-spring-boot-starter 0.2.10、

          三 工程結(jié)構(gòu)
          • basic-platform:父工程,管理框架版本等基礎(chǔ)依賴;

            • basic-common:基礎(chǔ)工具包,“定義公共跟蹤基礎(chǔ)配置類”等均在此工程,其他工程均依賴該工程;

            • basic-portal:門戶的父工程(pom工程),其下包含三個(gè)子工程:

              • server:前后端分離對(duì)應(yīng)的后端服務(wù) ;

              • portal-api:定義dubbo服務(wù)的接口;

              • portal-api-impl:定義portal-api對(duì)應(yīng)的接口實(shí)現(xiàn);

            • basic-foundation:基礎(chǔ)的父工程(pom工程),其下包含兩個(gè)子工程:

              • foundation-api:定義dubbo服務(wù)的接口;

              • foundation-api-impl:定義 foundation-api對(duì)應(yīng)的接口實(shí)現(xiàn);

          8296e03c25d2ced124cb425861ca1452.webp

          四、pom依賴

          主要的代碼均在basic-common的pom中,添加如下依賴:

          <dependency>            <groupId>org.apache.dubbogroupId>            <artifactId>dubboartifactId>            <scope>providedscope>        dependency>        <dependency>            <groupId>io.zipkin.bravegroupId>            <artifactId>brave-instrumentation-dubboartifactId>        dependency>        <dependency>            <groupId>io.zipkin.bravegroupId>            <artifactId>brave-spring-beansartifactId>        dependency>        <dependency>            <groupId>io.zipkin.bravegroupId>            <artifactId>brave-context-slf4jartifactId>        dependency>                <dependency>            <groupId>io.zipkin.reporter2groupId>            <artifactId>zipkin-sender-okhttp3artifactId>        dependency>                <dependency>            <groupId>io.zipkin.bravegroupId>            <artifactId>brave-instrumentation-spring-webmvcartifactId>        dependency>                <dependency>            <groupId>io.zipkin.bravegroupId>            <artifactId>brave-instrumentation-httpclientartifactId>        dependency>        <dependency>            <groupId>io.zipkin.reporter2groupId>            <artifactId>zipkin-sender-okhttp3artifactId>        dependency>

          另外,需要定義一個(gè)配置類,來(lái)處理RPC的tracing,要不會(huì)不生效。

          package com.wd.basic.common.support.trace;
          import brave.CurrentSpanCustomizer;import brave.SpanCustomizer;import brave.Tracing;import brave.context.slf4j.MDCScopeDecorator;import brave.http.HttpTracing;import brave.propagation.B3Propagation;import brave.propagation.ExtraFieldPropagation;import brave.propagation.ThreadLocalCurrentTraceContext;import brave.rpc.RpcTracing;import brave.sampler.Sampler;import brave.servlet.TracingFilter;import brave.spring.webmvc.SpanCustomizingAsyncHandlerInterceptor;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.Import;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import zipkin2.Span;import zipkin2.codec.Encoding;import zipkin2.reporter.AsyncReporter;import zipkin2.reporter.Sender;import zipkin2.reporter.okhttp3.OkHttpSender;
          import javax.servlet.Filter;
          @Configuration@Import(SpanCustomizingAsyncHandlerInterceptor.class)public class TracingConfig implements WebMvcConfigurer {
          @Bean Sender sender(@Value("${zipkin.base.url}") String url) { return OkHttpSender.newBuilder() .encoding(Encoding.PROTO3) .endpoint(url) .build(); }
          /** * Configuration for how to buffer spans into messages for Zipkin */ @Bean @ConditionalOnBean(Sender.class) AsyncReporter spanReporter(Sender sender) { AsyncReporter.Builder builder = AsyncReporter.builder(sender); builder.queuedMaxSpans(50000); builder.queuedMaxBytes(104857600); return builder.build(); }

          /** * Controls aspects of tracing such as the service name that shows up in the UI */ @Bean Tracing tracing(@Value("${dubbo.application.name}") String applicationName, @Value("${zipkin.enable:false}") Boolean enable, @Autowired(required = false) AsyncReporter spanReporter) { Tracing.Builder builder = Tracing.newBuilder() .localServiceName(applicationName) .propagationFactory(ExtraFieldPropagation.newFactory(B3Propagation.FACTORY, "user-name")) .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder() // puts trace IDs into logs .addScopeDecorator(MDCScopeDecorator.create()) .build() ); if (enable) { builder.spanReporter(spanReporter); builder.sampler(Sampler.ALWAYS_SAMPLE); } else { builder.sampler(Sampler.NEVER_SAMPLE); } return builder.build(); }
          @Bean SpanCustomizer spanCustomizer(Tracing tracing) { return CurrentSpanCustomizer.create(tracing); }
          /** * Decides how to name and tag spans. By default they are named the same as the http method */ @Bean HttpTracing httpTracing(Tracing tracing) { return HttpTracing.create(tracing); }

          @Bean RpcTracing rpcTracing(Tracing tracing) { return RpcTracing.create(tracing); }
          /** * Creates server spans for http requests */ @Bean Filter tracingFilter(HttpTracing httpTracing) { return TracingFilter.create(httpTracing);
          }
          @Autowired SpanCustomizingAsyncHandlerInterceptor webMvcTracingCustomizer;
          /** * Decorates server spans with application-defined web tags */ @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(webMvcTracingCustomizer); }}
          五、其他工程添加配置

          前提:所有工程均依賴basic-common。?dubbo工程的provider和consumer均添加如下配置(請(qǐng)注意必須添加dubbo.consumer.filter和dubbo.provider.filter

          dubbo:  application:    name: foundationRpc #服務(wù)名稱  consumer:    timeout: 3000 #消費(fèi)超時(shí)時(shí)間    retries: 1 #重試次數(shù)    filter: tracing # 請(qǐng)注意必須添加該配置    check: false  provider:    filter: tracing # 請(qǐng)注意必須添加該配置  protocol:    name: dubbozipkin:  enable: true  base:    url: http://127.0.0.1:9411/api/v2/spans
          六、測(cè)試

          設(shè)計(jì)如下調(diào)用關(guān)系:?f0c685782a4314521cd7663c0c0ebbf2.webp?server定義http入口:

              @GetMapping("tracing")    public String exec(){        log.info("come in tracing");        return rpcDemoService.tracing();    }

          rpcDemoService為server中定義的service,實(shí)現(xiàn)如下:

          package com.wd.basic.portal.server.modular.demo.service.impl;
          import cn.hutool.core.util.StrUtil;import com.wd.basic.foundation.rpc.test.service.DemoRpcService;import com.wd.basic.portal.rpc.IDemoService;import com.wd.basic.portal.rpc.ITraceDemoService;import com.wd.basic.portal.server.modular.demo.service.RpcDemoService;import lombok.extern.slf4j.Slf4j;import org.apache.dubbo.config.annotation.DubboReference;import org.springframework.stereotype.Service;
          /** * rpc演示服務(wù)impl * * @author 小塵哥 * @date 2022/04/14 */@Slf4j@Servicepublic class RpcDemoServiceImpl implements RpcDemoService {
          @DubboReference(interfaceClass = IDemoService.class, version = "2.0") private IDemoService demoService2;

          @DubboReference(interfaceClass = IDemoService.class, version = "1.0") private IDemoService demoService1;
          @DubboReference(interfaceClass = ITraceDemoService.class, version = "1.0") private ITraceDemoService traceDemoService;
          @DubboReference(interfaceClass = DemoRpcService.class, version = "1.0") private DemoRpcService demoRpcService;
          @Override public String tracing() { log.info("come in exec service"); String rpc2 = demoService2.testRpc(); return StrUtil.join(",", rpc2); }}

          IDemoService 定義在portal-api中,實(shí)現(xiàn)如下


          package com.wd.basic.portal.rpc.impl;

          import com.wd.basic.foundation.rpc.test.service.DemoRpcService;import com.wd.basic.portal.rpc.IDemoService;import lombok.extern.slf4j.Slf4j;import org.apache.dubbo.config.annotation.DubboReference;import org.apache.dubbo.config.annotation.DubboService;
          /** * 演示服務(wù)impl * * @author 小塵哥 * @date 2022/03/16 */@Slf4j@DubboService(interfaceClass = IDemoService.class,version = "2.0")public class DemoServiceV2Impl implements IDemoService {
          @DubboReference(interfaceClass = DemoRpcService.class, version = "1.0") private DemoRpcService demoRpcService;
          @Override public String testRpc() { log.info("來(lái)自統(tǒng)一門戶 RPC 測(cè)試"); demoRpcService.testRpc(); return "調(diào)用到了rpc服務(wù) version 2.0.0"; }}

          DemoRpcService 定義在foundation-api中,實(shí)現(xiàn)如下:

          package com.wd.basic.foundation.rpc.test.service.impl;
          import com.wd.basic.foundation.rpc.test.service.DemoRpcService;import lombok.extern.slf4j.Slf4j;import org.apache.dubbo.config.annotation.DubboService;
          /** * test Rpc服務(wù) * @author 上官婉兒 */@Slf4j@DubboService(interfaceClass = DemoRpcService.class,version = "1.0")public class DemoRpcServiceImpl implements DemoRpcService {
          @Override public String testRpc() { log.info("來(lái)自基礎(chǔ)服務(wù) RPC 測(cè)試"); return "RPC服務(wù)! from foundation"; }}


          七、日志配置

          臨門一腳了,以上都配置好了,但是哪里能看到效果呢?肯定是需要從日志來(lái)跟蹤,我們采用springboot推薦的logback來(lái)記錄日志,請(qǐng)注意日志記錄格式,添加了部分內(nèi)容“【%X{traceId},%X{spanId},%X{parentId}】”,完整配置如下:

          <configuration scan="true" scanPeriod="10 seconds">    <contextName>Logback For Basic PlatformcontextName>    
          <springProperty scope="context" name="logDir" source="custom.log.dir" defaultValue="D:/logback"/>
          <springProperty scope="context" name="logLevel" source="custom.log.level" defaultValue="info"/>
          <springProperty scope="context" name="logMaxHistory" source="custom.log.max-history" defaultValue="180"/>
          <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} 【%X{traceId},%X{spanId},%X{parentId}】 [%thread] %-5level %logger-%msg%n %ex{5}pattern> <charset class="java.nio.charset.Charset">UTF-8charset> encoder> appender>

          <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> <fileNamePattern>${logDir}/%d{yyyy-MM-dd}/pf.%i.log.zipfileNamePattern>
          <maxFileSize>50MBmaxFileSize> <maxHistory>${logMaxHistory}maxHistory> <totalSizeCap>10GBtotalSizeCap> rollingPolicy> <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} 【%X{traceId},%X{spanId},%X{parentId}】 [%thread] %-5level %logger-%msg%n %ex{5}pattern> encoder> appender>
          <appender name="dayLogAsyncAppender" class="ch.qos.logback.classic.AsyncAppender"> <includeCallerData>trueincludeCallerData> <discardingThreshold>0discardingThreshold> <queueSize>512queueSize> <appender-ref ref="FILE"/> appender>

          <logger name="org.springframework" level="${logLevel}"/>
          <root level="${logLevel}"> <appender-ref ref="STDOUT" /> <appender-ref ref="dayLogAsyncAppender" /> root>configuration>
          八、驗(yàn)證

          來(lái)自server的日志

          2022-04-26 16:44:25.817 【2926aa52265ad112,2926aa52265ad112,】 [http-nio-8080-exec-1] INFO  com.wd.basic.portal.server.modular.demo.controller.RpcDemoController-come in tracing 2022-04-26 16:44:25.826 【2926aa52265ad112,2926aa52265ad112,】 [http-nio-8080-exec-1] INFO  com.wd.basic.portal.server.modular.demo.service.impl.RpcDemoServiceImpl-come in exec service

          來(lái)自portal-api的日志

           2022-04-26 16:44:25.882 【2926aa52265ad112,6a4da6311934ab65,2926aa52265ad112[DubboServerHandler-10.1.252.224:20881-thread-5] INFO  com.wd.basic.portal.rpc.impl.DemoServiceV2Impl-來(lái)自統(tǒng)一門戶 RPC 測(cè)試

          來(lái)自foundation-api的日志

           2022-04-26 16:44:25.926 【2926aa52265ad112,53dbfb344223ef50,6a4da6311934ab65[DubboServerHandler-10.1.252.224:20880-thread-3] INFO  com.wd.basic.foundation.rpc.test.service.impl.DemoRpcServiceImpl-來(lái)自基礎(chǔ)服務(wù) RPC 測(cè)試
          九、日志分析

          提取三部分日志中括號(hào)中的內(nèi)容:

          統(tǒng)一門戶:traceId = 2926aa52265ad112,spanId=2926aa52265ad112,parentId=’’;統(tǒng)一門戶RPC服務(wù):traceId = 2926aa52265ad112,spanId=6a4da6311934ab65,parentId=2926aa52265ad112;基礎(chǔ)服務(wù)RPC服務(wù):traceId = 2926aa52265ad112,spanId=53dbfb344223ef50,parentId=6a4da6311934ab65;

          說(shuō)明:

          1. 對(duì)于server,作為請(qǐng)求入口,因此traceId和spanId相同,無(wú)上游服務(wù),因此parentId為空。

          2. 對(duì)于portal-api服務(wù),parentId=統(tǒng)一門戶請(qǐng)求入口的spanId,因此它是統(tǒng)一門戶的下游服務(wù)。

          3. 對(duì)于foundation-api服務(wù),parentId=同一門戶RPC服務(wù)的spanId,因此它是統(tǒng)一門戶RPC服務(wù)的下游服務(wù)。

          綜上,和測(cè)試開始時(shí)的設(shè)計(jì)邏輯一致,由traceId串聯(lián)整個(gè)請(qǐng)求過(guò)程,由spanId和parentId構(gòu)建上下游調(diào)用關(guān)系,完成dubbo服務(wù)之間調(diào)用的鏈路跟蹤。

          瀏覽 94
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲无码app | 影音先锋美女被操 | 丁香五月久久 | 91免费福利 | 美女滋味网站 |