diff --git a/README.md b/README.md
index 448010023..855871af0 100644
--- a/README.md
+++ b/README.md
@@ -68,6 +68,7 @@
* [《芋道 Spring Boot 监控端点 Actuator 入门》](http://www.iocoder.cn/Spring-Boot/Actuator/?github) 对应 [lab-34](https://github.com/YunaiV/SpringBoot-Labs/tree/master/lab-34) 。
* [《芋道 Spring Boot 监控工具 Admin 入门》](http://www.iocoder.cn/Spring-Boot/Admin/?github) 对应 [lab-35](https://github.com/YunaiV/SpringBoot-Labs/tree/master/lab-35) 。
* [《芋道 Spring Boot 监控平台 Prometheus + Grafana 入门》](http://www.iocoder.cn/Spring-Boot/Prometheus-and-Grafana/?github) 对应 [lab-36](https://github.com/YunaiV/SpringBoot-Labs/tree/master/lab-36) 。
+* 《芋道 Spring Boot 监控平台 CAT 入门》计划中...
## 日志管理
@@ -77,8 +78,9 @@
## 链路追踪
* [《芋道 Spring Boot 链路追踪 SkyWalking 入门》](http://www.iocoder.cn/Spring-Boot/SkyWalking/?github) 对应 [lab-39](https://github.com/YunaiV/SpringBoot-Labs/tree/master/lab-39) 。
-* [《芋道 Spring Boot 链路追踪 Zipkin 入门》](http://www.iocoder.cn/Spring-Boot/Zipkin/?github) 对应 [lab-38](https://github.com/YunaiV/SpringBoot-Labs/tree/master/lab-38) 。
-* [《芋道 Spring Boot 链路追踪 Pinpoint 入门》](http://www.iocoder.cn/Spring-Boot/Pinpoint/?github) 对应 [lab-39](https://github.com/YunaiV/SpringBoot-Labs/tree/master/lab-38) 。
+* [《芋道 Spring Boot 链路追踪 Zipkin 入门》](http://www.iocoder.cn/Spring-Boot/Zipkin/?github) 对应 [lab-40](https://github.com/YunaiV/SpringBoot-Labs/tree/master/lab-40) 。
+* 《芋道 Spring Boot 链路追踪 Pinpoint 入门》计划中...
+* 《芋道 Spring Boot 链路追踪 Elastic APM 入门》计划中...
## 性能测试
diff --git a/lab-40/lab-40-demo/pom.xml b/lab-40/lab-40-demo/pom.xml
index 6f5de8b9f..d12d4da06 100644
--- a/lab-40/lab-40-demo/pom.xml
+++ b/lab-40/lab-40-demo/pom.xml
@@ -11,6 +11,7 @@
4.0.0
lab-40-demo
+ jar
@@ -19,42 +20,46 @@
spring-boot-starter-web
-
+
org.apache.httpcomponents
httpclient
+
+
+
+ io.zipkin.brave
+ brave
+
+
+ io.zipkin.reporter2
+ zipkin-sender-okhttp3
+
+
+
io.zipkin.brave
brave-instrumentation-spring-webmvc
+
io.zipkin.brave
brave-instrumentation-httpclient
-
+
io.zipkin.brave
brave-context-slf4j
-
-
- io.zipkin.brave
- brave
-
-
- io.zipkin.reporter2
- zipkin-sender-okhttp3
-
-
+
io.zipkin.brave
@@ -66,4 +71,16 @@
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+ true
+
+
+
+
+
diff --git a/lab-40/lab-40-demo/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/Application2.java b/lab-40/lab-40-demo/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/Application2.java
index f4d134877..725a60bdf 100644
--- a/lab-40/lab-40-demo/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/Application2.java
+++ b/lab-40/lab-40-demo/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/Application2.java
@@ -1,9 +1,8 @@
package cn.iocoder.springboot.lab40.zipkindemo;
import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-@SpringBootApplication
+//@SpringBootApplication
public class Application2 {
public static void main(String[] args) {
diff --git a/lab-40/lab-40-demo/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java b/lab-40/lab-40-demo/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java
index b222d4803..2a5f3e95a 100644
--- a/lab-40/lab-40-demo/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java
+++ b/lab-40/lab-40-demo/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java
@@ -5,8 +5,6 @@
import brave.Tracing;
import brave.http.HttpTracing;
import brave.httpclient.TracingHttpClientBuilder;
-import brave.propagation.B3Propagation;
-import brave.propagation.ExtraFieldPropagation;
import brave.servlet.TracingFilter;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.beans.factory.annotation.Value;
@@ -25,6 +23,8 @@
@Configuration
public class ZipkinConfiguration {
+ // ==================== 通用配置 ====================
+
/**
* Configuration for how to send spans to Zipkin
*/
@@ -48,7 +48,6 @@ public AsyncReporter spanReporter() {
public Tracing tracing(@Value("${spring.application.name}") String serviceName) {
return Tracing.newBuilder()
.localServiceName(serviceName)
- .propagationFactory(ExtraFieldPropagation.newFactory(B3Propagation.FACTORY, "user-name"))
// .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder()
// .addScopeDecorator(MDCScopeDecorator.create()) // puts trace IDs into logs
// .build()
diff --git a/lab-40/lab-40-logback/pom.xml b/lab-40/lab-40-logback/pom.xml
new file mode 100644
index 000000000..2e4d6dc92
--- /dev/null
+++ b/lab-40/lab-40-logback/pom.xml
@@ -0,0 +1,61 @@
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.2.2.RELEASE
+
+
+ 4.0.0
+
+ lab-40-logback
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+
+ io.zipkin.brave
+ brave
+
+
+ io.zipkin.reporter2
+ zipkin-sender-okhttp3
+
+
+
+
+
+ io.zipkin.brave
+ brave-instrumentation-spring-webmvc
+
+
+
+
+ io.zipkin.brave
+ brave-context-slf4j
+
+
+
+
+
+
+
+
+ io.zipkin.brave
+ brave-bom
+ 5.9.1
+ pom
+ import
+
+
+
+
+
diff --git a/lab-40/lab-40-logback/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/LogbackApplication.java b/lab-40/lab-40-logback/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/LogbackApplication.java
new file mode 100644
index 000000000..eca243d7b
--- /dev/null
+++ b/lab-40/lab-40-logback/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/LogbackApplication.java
@@ -0,0 +1,13 @@
+package cn.iocoder.springboot.lab40.zipkindemo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class LogbackApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(LogbackApplication.class, args);
+ }
+
+}
diff --git a/lab-40/lab-40-logback/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/SpringMvcConfiguration.java b/lab-40/lab-40-logback/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/SpringMvcConfiguration.java
new file mode 100644
index 000000000..b56fd2d01
--- /dev/null
+++ b/lab-40/lab-40-logback/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/SpringMvcConfiguration.java
@@ -0,0 +1,25 @@
+package cn.iocoder.springboot.lab40.zipkindemo.config;
+
+import brave.spring.webmvc.SpanCustomizingAsyncHandlerInterceptor;
+import org.springframework.beans.factory.annotation.Autowired;
+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;
+
+@Configuration
+@Import(SpanCustomizingAsyncHandlerInterceptor.class)
+public class SpringMvcConfiguration implements WebMvcConfigurer {
+
+ @Autowired
+ public SpanCustomizingAsyncHandlerInterceptor webMvcTracingCustomizer;
+
+ /**
+ * Decorates server spans with application-defined web tags
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ registry.addInterceptor(webMvcTracingCustomizer);
+ }
+
+}
diff --git a/lab-40/lab-40-logback/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java b/lab-40/lab-40-logback/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java
new file mode 100644
index 000000000..7adf03662
--- /dev/null
+++ b/lab-40/lab-40-logback/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java
@@ -0,0 +1,84 @@
+package cn.iocoder.springboot.lab40.zipkindemo.config;
+
+import brave.CurrentSpanCustomizer;
+import brave.SpanCustomizer;
+import brave.Tracing;
+import brave.context.slf4j.MDCScopeDecorator;
+import brave.http.HttpTracing;
+import brave.propagation.ThreadLocalCurrentTraceContext;
+import brave.servlet.TracingFilter;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import zipkin2.Span;
+import zipkin2.reporter.AsyncReporter;
+import zipkin2.reporter.Sender;
+import zipkin2.reporter.okhttp3.OkHttpSender;
+
+import javax.servlet.Filter;
+
+@Configuration
+public class ZipkinConfiguration {
+
+ // ==================== 通用配置 ====================
+
+ /**
+ * Configuration for how to send spans to Zipkin
+ */
+ @Bean
+ public Sender sender() {
+ return OkHttpSender.create("http://127.0.0.1:9411/api/v2/spans");
+ }
+
+ /**
+ * Configuration for how to buffer spans into messages for Zipkin
+ */
+ @Bean
+ public AsyncReporter spanReporter() {
+ return AsyncReporter.create(sender());
+ }
+
+ /**
+ * Controls aspects of tracing such as the service name that shows up in the UI
+ */
+ @Bean
+ public Tracing tracing(@Value("${spring.application.name}") String serviceName) {
+ return Tracing.newBuilder()
+ .localServiceName(serviceName)
+ .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder()
+ .addScopeDecorator(MDCScopeDecorator.create()) // puts trace IDs into logs
+ .build()
+ )
+ .spanReporter(spanReporter()).build();
+ }
+
+ /**
+ * Allows someone to add tags to a span if a trace is in progress
+ */
+ @Bean
+ public SpanCustomizer spanCustomizer(Tracing tracing) {
+ return CurrentSpanCustomizer.create(tracing);
+ }
+
+ // ==================== HTTP 相关 ====================
+
+ /**
+ * Decides how to name and tag spans. By default they are named the same as the http method
+ */
+ @Bean
+ public HttpTracing httpTracing(Tracing tracing) {
+ return HttpTracing.create(tracing);
+ }
+
+ /**
+ * Creates server spans for http requests
+ */
+ @Bean
+ public Filter tracingFilter(HttpTracing httpTracing) {
+ return TracingFilter.create(httpTracing);
+ }
+
+ // ==================== SpringMVC 相关 ====================
+ // @see SpringMvcConfiguration 类上的,@Import(SpanCustomizingAsyncHandlerInterceptor.class)
+
+}
diff --git a/lab-40/lab-40-logback/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/controller/DemoController.java b/lab-40/lab-40-logback/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/controller/DemoController.java
new file mode 100644
index 000000000..6ef5f5d34
--- /dev/null
+++ b/lab-40/lab-40-logback/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/controller/DemoController.java
@@ -0,0 +1,21 @@
+package cn.iocoder.springboot.lab40.zipkindemo.controller;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/demo")
+public class DemoController {
+
+ private Logger logger = LoggerFactory.getLogger(getClass());
+
+ @GetMapping("/logback")
+ public String echo() {
+ logger.info("测试日志");
+ return "logback";
+ }
+
+}
diff --git a/lab-40/lab-40-logback/src/main/resources/application.yaml b/lab-40/lab-40-logback/src/main/resources/application.yaml
new file mode 100644
index 000000000..28a35b7ef
--- /dev/null
+++ b/lab-40/lab-40-logback/src/main/resources/application.yaml
@@ -0,0 +1,8 @@
+spring:
+ application:
+ name: demo-application-springmvc
+
+logging:
+ pattern:
+ console: "%clr(%d{${LOG_DATEFORMAT_PATTERN:yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %X{traceId}/%X{spanId} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:%wEx}"
+ file: "%d{${LOG_DATEFORMAT_PATTERN:yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } %X{traceId}/%X{spanId} --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:%wEx}"
diff --git a/lab-40/lab-40-mysql/pom.xml b/lab-40/lab-40-mysql/pom.xml
new file mode 100644
index 000000000..3f521710e
--- /dev/null
+++ b/lab-40/lab-40-mysql/pom.xml
@@ -0,0 +1,72 @@
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.2.2.RELEASE
+
+
+ 4.0.0
+
+ lab-40-mysql
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+ mysql
+ mysql-connector-java
+ 5.1.46
+
+
+
+
+
+ io.zipkin.brave
+ brave
+
+
+ io.zipkin.reporter2
+ zipkin-sender-okhttp3
+
+
+
+
+
+ io.zipkin.brave
+ brave-instrumentation-spring-webmvc
+
+
+
+
+ io.zipkin.brave
+ brave-instrumentation-mysql
+
+
+
+
+
+
+
+
+ io.zipkin.brave
+ brave-bom
+ 5.9.1
+ pom
+ import
+
+
+
+
+
diff --git a/lab-40/lab-40-mysql/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/MySQLApplication.java b/lab-40/lab-40-mysql/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/MySQLApplication.java
new file mode 100644
index 000000000..7310ea5d2
--- /dev/null
+++ b/lab-40/lab-40-mysql/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/MySQLApplication.java
@@ -0,0 +1,13 @@
+package cn.iocoder.springboot.lab40.zipkindemo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class MySQLApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(MySQLApplication.class, args);
+ }
+
+}
diff --git a/lab-40/lab-40-mysql/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/SpringMvcConfiguration.java b/lab-40/lab-40-mysql/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/SpringMvcConfiguration.java
new file mode 100644
index 000000000..b56fd2d01
--- /dev/null
+++ b/lab-40/lab-40-mysql/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/SpringMvcConfiguration.java
@@ -0,0 +1,25 @@
+package cn.iocoder.springboot.lab40.zipkindemo.config;
+
+import brave.spring.webmvc.SpanCustomizingAsyncHandlerInterceptor;
+import org.springframework.beans.factory.annotation.Autowired;
+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;
+
+@Configuration
+@Import(SpanCustomizingAsyncHandlerInterceptor.class)
+public class SpringMvcConfiguration implements WebMvcConfigurer {
+
+ @Autowired
+ public SpanCustomizingAsyncHandlerInterceptor webMvcTracingCustomizer;
+
+ /**
+ * Decorates server spans with application-defined web tags
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ registry.addInterceptor(webMvcTracingCustomizer);
+ }
+
+}
diff --git a/lab-40/lab-40-mysql/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java b/lab-40/lab-40-mysql/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java
new file mode 100644
index 000000000..ba4ea09ca
--- /dev/null
+++ b/lab-40/lab-40-mysql/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java
@@ -0,0 +1,78 @@
+package cn.iocoder.springboot.lab40.zipkindemo.config;
+
+import brave.CurrentSpanCustomizer;
+import brave.SpanCustomizer;
+import brave.Tracing;
+import brave.http.HttpTracing;
+import brave.servlet.TracingFilter;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import zipkin2.Span;
+import zipkin2.reporter.AsyncReporter;
+import zipkin2.reporter.Sender;
+import zipkin2.reporter.okhttp3.OkHttpSender;
+
+import javax.servlet.Filter;
+
+@Configuration
+public class ZipkinConfiguration {
+
+ // ==================== 通用配置 ====================
+
+ /**
+ * Configuration for how to send spans to Zipkin
+ */
+ @Bean
+ public Sender sender() {
+ return OkHttpSender.create("http://127.0.0.1:9411/api/v2/spans");
+ }
+
+ /**
+ * Configuration for how to buffer spans into messages for Zipkin
+ */
+ @Bean
+ public AsyncReporter spanReporter() {
+ return AsyncReporter.create(sender());
+ }
+
+ /**
+ * Controls aspects of tracing such as the service name that shows up in the UI
+ */
+ @Bean
+ public Tracing tracing(@Value("${spring.application.name}") String serviceName) {
+ return Tracing.newBuilder()
+ .localServiceName(serviceName)
+ .spanReporter(spanReporter()).build();
+ }
+
+ /**
+ * Allows someone to add tags to a span if a trace is in progress
+ */
+ @Bean
+ public SpanCustomizer spanCustomizer(Tracing tracing) {
+ return CurrentSpanCustomizer.create(tracing);
+ }
+
+ // ==================== HTTP 相关 ====================
+
+ /**
+ * Decides how to name and tag spans. By default they are named the same as the http method
+ */
+ @Bean
+ public HttpTracing httpTracing(Tracing tracing) {
+ return HttpTracing.create(tracing);
+ }
+
+ /**
+ * Creates server spans for http requests
+ */
+ @Bean
+ public Filter tracingFilter(HttpTracing httpTracing) {
+ return TracingFilter.create(httpTracing);
+ }
+
+ // ==================== SpringMVC 相关 ====================
+ // @see SpringMvcConfiguration 类上的,@Import(SpanCustomizingAsyncHandlerInterceptor.class)
+
+}
diff --git a/lab-40/lab-40-mysql/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/controller/DemoController.java b/lab-40/lab-40-mysql/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/controller/DemoController.java
new file mode 100644
index 000000000..aa22ccda7
--- /dev/null
+++ b/lab-40/lab-40-mysql/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/controller/DemoController.java
@@ -0,0 +1,29 @@
+package cn.iocoder.springboot.lab40.zipkindemo.controller;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/demo")
+public class DemoController {
+
+ @Autowired
+ private JdbcTemplate template;
+
+ @GetMapping("/mysql")
+ public String echo() {
+ this.selectById(1);
+ return "mysql";
+ }
+
+ public Object selectById(Integer id) {
+ return template.queryForObject("SELECT id, username, password FROM t_user WHERE id = ?",
+ new BeanPropertyRowMapper<>(Object.class), // 结果转换成对应的对象。Object 理论来说是 UserDO.class ,这里偷懒了。
+ id);
+ }
+
+}
diff --git a/lab-40/lab-40-mysql/src/main/resources/application.yaml b/lab-40/lab-40-mysql/src/main/resources/application.yaml
new file mode 100644
index 000000000..87d7243fa
--- /dev/null
+++ b/lab-40/lab-40-mysql/src/main/resources/application.yaml
@@ -0,0 +1,10 @@
+spring:
+ application:
+ name: demo-application-mysql
+
+ # datasource 数据源配置内容
+ datasource:
+ url: jdbc:mysql://127.0.0.1:3306/lab-39-mysql?useSSL=false&useUnicode=true&characterEncoding=UTF-8&statementInterceptors=brave.mysql.TracingStatementInterceptor&zipkinServiceName=demo-db-mysql
+ driver-class-name: com.mysql.jdbc.Driver
+ username: root
+ password:
diff --git a/lab-40/lab-40-redis/pom.xml b/lab-40/lab-40-redis/pom.xml
new file mode 100644
index 000000000..5c846dbe8
--- /dev/null
+++ b/lab-40/lab-40-redis/pom.xml
@@ -0,0 +1,93 @@
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.2.2.RELEASE
+
+
+ 4.0.0
+
+ lab-40-redis
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+ io.lettuce
+ lettuce-core
+
+
+
+
+
+
+ redis.clients
+ jedis
+
+
+
+
+
+ io.zipkin.brave
+ brave
+
+
+ io.zipkin.reporter2
+ zipkin-sender-okhttp3
+
+
+
+
+
+ io.zipkin.brave
+ brave-instrumentation-spring-webmvc
+
+
+
+
+ io.opentracing.brave
+ brave-opentracing
+ 0.35.0
+
+
+
+
+ io.opentracing.contrib
+ opentracing-redis-jedis3
+ 0.1.14
+
+
+ io.opentracing.contrib
+ opentracing-redis-spring-data
+ 0.1.14
+
+
+
+
+
+
+
+
+ io.zipkin.brave
+ brave-bom
+ 5.9.1
+ pom
+ import
+
+
+
+
+
diff --git a/lab-40/lab-40-redis/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/RedisApplication.java b/lab-40/lab-40-redis/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/RedisApplication.java
new file mode 100644
index 000000000..0659aab94
--- /dev/null
+++ b/lab-40/lab-40-redis/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/RedisApplication.java
@@ -0,0 +1,13 @@
+package cn.iocoder.springboot.lab40.zipkindemo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class RedisApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(RedisApplication.class, args);
+ }
+
+}
diff --git a/lab-40/lab-40-redis/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/SpringMvcConfiguration.java b/lab-40/lab-40-redis/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/SpringMvcConfiguration.java
new file mode 100644
index 000000000..b56fd2d01
--- /dev/null
+++ b/lab-40/lab-40-redis/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/SpringMvcConfiguration.java
@@ -0,0 +1,25 @@
+package cn.iocoder.springboot.lab40.zipkindemo.config;
+
+import brave.spring.webmvc.SpanCustomizingAsyncHandlerInterceptor;
+import org.springframework.beans.factory.annotation.Autowired;
+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;
+
+@Configuration
+@Import(SpanCustomizingAsyncHandlerInterceptor.class)
+public class SpringMvcConfiguration implements WebMvcConfigurer {
+
+ @Autowired
+ public SpanCustomizingAsyncHandlerInterceptor webMvcTracingCustomizer;
+
+ /**
+ * Decorates server spans with application-defined web tags
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ registry.addInterceptor(webMvcTracingCustomizer);
+ }
+
+}
diff --git a/lab-40/lab-40-redis/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java b/lab-40/lab-40-redis/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java
new file mode 100644
index 000000000..24fb52c64
--- /dev/null
+++ b/lab-40/lab-40-redis/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java
@@ -0,0 +1,104 @@
+package cn.iocoder.springboot.lab40.zipkindemo.config;
+
+import brave.CurrentSpanCustomizer;
+import brave.SpanCustomizer;
+import brave.Tracing;
+import brave.http.HttpTracing;
+import brave.opentracing.BraveTracer;
+import brave.servlet.TracingFilter;
+import io.opentracing.Tracer;
+import io.opentracing.contrib.redis.common.TracingConfiguration;
+import io.opentracing.contrib.redis.spring.data.connection.TracingRedisConnectionFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
+import zipkin2.Span;
+import zipkin2.reporter.AsyncReporter;
+import zipkin2.reporter.Sender;
+import zipkin2.reporter.okhttp3.OkHttpSender;
+
+import javax.servlet.Filter;
+
+@Configuration
+public class ZipkinConfiguration {
+
+ // ==================== 通用配置 ====================
+
+ /**
+ * Configuration for how to send spans to Zipkin
+ */
+ @Bean
+ public Sender sender() {
+ return OkHttpSender.create("http://127.0.0.1:9411/api/v2/spans");
+ }
+
+ /**
+ * Configuration for how to buffer spans into messages for Zipkin
+ */
+ @Bean
+ public AsyncReporter spanReporter() {
+ return AsyncReporter.create(sender());
+ }
+
+ /**
+ * Controls aspects of tracing such as the service name that shows up in the UI
+ */
+ @Bean
+ public Tracing tracing(@Value("${spring.application.name}") String serviceName) {
+ return Tracing.newBuilder()
+ .localServiceName(serviceName)
+ .spanReporter(spanReporter()).build();
+ }
+
+ @Bean
+ public Tracer openTracer(Tracing tracing) {
+ return BraveTracer.create(tracing);
+ }
+
+ /**
+ * Allows someone to add tags to a span if a trace is in progress
+ */
+ @Bean
+ public SpanCustomizer spanCustomizer(Tracing tracing) {
+ return CurrentSpanCustomizer.create(tracing);
+ }
+
+ // ==================== HTTP 相关 ====================
+
+ /**
+ * Decides how to name and tag spans. By default they are named the same as the http method
+ */
+ @Bean
+ public HttpTracing httpTracing(Tracing tracing) {
+ return HttpTracing.create(tracing);
+ }
+
+ /**
+ * Creates server spans for http requests
+ */
+ @Bean
+ public Filter tracingFilter(HttpTracing httpTracing) {
+ return TracingFilter.create(httpTracing);
+ }
+
+ // ==================== SpringMVC 相关 ====================
+ // @see SpringMvcConfiguration 类上的,@Import(SpanCustomizingAsyncHandlerInterceptor.class)
+
+ // ==================== Redis 相关 ====================
+ @Bean
+ public RedisConnectionFactory redisConnectionFactory(Tracer tracer, RedisProperties redisProperties) {
+ // 创建 JedisConnectionFactory 对象
+ RedisConnectionFactory connectionFactory = new JedisConnectionFactory();
+ // 创建 TracingConfiguration 对象
+ TracingConfiguration tracingConfiguration = new TracingConfiguration.Builder(tracer)
+ // 设置拓展 Tag ,设置 Redis 服务器地址。因为默认情况下,不会在操作 Redis 链路的 Span 上记录 Redis 服务器的地址,所以这里需要设置。
+ .extensionTag("Server Address", redisProperties.getHost() + ":" + redisProperties.getPort())
+ .build();
+ // 创建 TracingRedisConnectionFactory 对象
+ return new TracingRedisConnectionFactory(connectionFactory, tracingConfiguration);
+ }
+
+}
diff --git a/lab-40/lab-40-redis/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/controller/DemoController.java b/lab-40/lab-40-redis/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/controller/DemoController.java
new file mode 100644
index 000000000..fe11fb732
--- /dev/null
+++ b/lab-40/lab-40-redis/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/controller/DemoController.java
@@ -0,0 +1,26 @@
+package cn.iocoder.springboot.lab40.zipkindemo.controller;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/demo")
+public class DemoController {
+
+ @Autowired
+ private StringRedisTemplate redisTemplate;
+
+ @GetMapping("/redis")
+ public String redis() {
+ this.get("demo");
+ return "redis";
+ }
+
+ public void get(String key) {
+ redisTemplate.opsForValue().get(key);
+ }
+
+}
diff --git a/lab-40/lab-40-redis/src/main/resources/application.yaml b/lab-40/lab-40-redis/src/main/resources/application.yaml
new file mode 100644
index 000000000..a83378736
--- /dev/null
+++ b/lab-40/lab-40-redis/src/main/resources/application.yaml
@@ -0,0 +1,18 @@
+spring:
+ application:
+ name: demo-application-redis
+
+ # 对应 RedisProperties 类
+ redis:
+ host: 127.0.0.1
+ port: 6379
+ password: # Redis 服务器密码,默认为空。生产中,一定要设置 Redis 密码!
+ database: 0 # Redis 数据库号,默认为 0 。
+ timeout: 0 # Redis 连接超时时间,单位:毫秒。
+ # 对应 RedisProperties.Jedis 内部类
+ jedis:
+ pool:
+ max-active: 8 # 连接池最大连接数,默认为 8 。使用负数表示没有限制。
+ max-idle: 8 # 默认连接数最小空闲的连接数,默认为 8 。使用负数表示没有限制。
+ min-idle: 0 # 默认连接池最小空闲的连接数,默认为 0 。允许设置 0 和 正数。
+ max-wait: -1 # 连接池最大阻塞等待时间,单位:毫秒。默认为 -1 ,表示不限制。
diff --git a/lab-40/lab-40-springmvc/pom.xml b/lab-40/lab-40-springmvc/pom.xml
new file mode 100644
index 000000000..f2d6c4714
--- /dev/null
+++ b/lab-40/lab-40-springmvc/pom.xml
@@ -0,0 +1,55 @@
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.2.2.RELEASE
+
+
+ 4.0.0
+
+ lab-40-springmvc
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+
+ io.zipkin.brave
+ brave
+
+
+ io.zipkin.reporter2
+ zipkin-sender-okhttp3
+
+
+
+
+
+ io.zipkin.brave
+ brave-instrumentation-spring-webmvc
+
+
+
+
+
+
+
+
+ io.zipkin.brave
+ brave-bom
+ 5.9.1
+ pom
+ import
+
+
+
+
+
diff --git a/lab-40/lab-40-springmvc/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/SpringMVCApplication.java b/lab-40/lab-40-springmvc/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/SpringMVCApplication.java
new file mode 100644
index 000000000..9d195d2fd
--- /dev/null
+++ b/lab-40/lab-40-springmvc/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/SpringMVCApplication.java
@@ -0,0 +1,13 @@
+package cn.iocoder.springboot.lab40.zipkindemo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class SpringMVCApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(SpringMVCApplication.class, args);
+ }
+
+}
diff --git a/lab-40/lab-40-springmvc/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/SpringMvcConfiguration.java b/lab-40/lab-40-springmvc/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/SpringMvcConfiguration.java
new file mode 100644
index 000000000..8a854aeac
--- /dev/null
+++ b/lab-40/lab-40-springmvc/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/SpringMvcConfiguration.java
@@ -0,0 +1,25 @@
+package cn.iocoder.springboot.lab40.zipkindemo.config;
+
+import brave.spring.webmvc.SpanCustomizingAsyncHandlerInterceptor;
+import org.springframework.beans.factory.annotation.Autowired;
+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;
+
+@Configuration
+@Import(SpanCustomizingAsyncHandlerInterceptor.class) // 创建拦截器 SpanCustomizingAsyncHandlerInterceptor Bean
+public class SpringMvcConfiguration implements WebMvcConfigurer {
+
+ @Autowired
+ public SpanCustomizingAsyncHandlerInterceptor webMvcTracingCustomizer;
+
+ /**
+ * Decorates server spans with application-defined web tags
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) { // 记录 SpringMVC 相关信息到 Span 中
+ registry.addInterceptor(webMvcTracingCustomizer);
+ }
+
+}
diff --git a/lab-40/lab-40-springmvc/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java b/lab-40/lab-40-springmvc/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java
new file mode 100644
index 000000000..c30779808
--- /dev/null
+++ b/lab-40/lab-40-springmvc/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java
@@ -0,0 +1,78 @@
+package cn.iocoder.springboot.lab40.zipkindemo.config;
+
+import brave.CurrentSpanCustomizer;
+import brave.SpanCustomizer;
+import brave.Tracing;
+import brave.http.HttpTracing;
+import brave.servlet.TracingFilter;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import zipkin2.Span;
+import zipkin2.reporter.AsyncReporter;
+import zipkin2.reporter.Sender;
+import zipkin2.reporter.okhttp3.OkHttpSender;
+
+import javax.servlet.Filter;
+
+@Configuration
+public class ZipkinConfiguration {
+
+ // ==================== 通用配置 ====================
+
+ /**
+ * Configuration for how to send spans to Zipkin
+ */
+ @Bean
+ public Sender sender() { // Sender 采用 HTTP 通信方式
+ return OkHttpSender.create("http://127.0.0.1:9411/api/v2/spans");
+ }
+
+ /**
+ * Configuration for how to buffer spans into messages for Zipkin
+ */
+ @Bean
+ public AsyncReporter spanReporter() { // 异步 Reporter
+ return AsyncReporter.create(sender());
+ }
+
+ /**
+ * Controls aspects of tracing such as the service name that shows up in the UI
+ */
+ @Bean
+ public Tracing tracing(@Value("${spring.application.name}") String serviceName) {
+ return Tracing.newBuilder()
+ .localServiceName(serviceName) // 应用名
+ .spanReporter(this.spanReporter()).build();
+ }
+
+ /**
+ * Allows someone to add tags to a span if a trace is in progress
+ */
+ @Bean
+ public SpanCustomizer spanCustomizer(Tracing tracing) {
+ return CurrentSpanCustomizer.create(tracing);
+ }
+
+ // ==================== HTTP 相关 ====================
+
+ /**
+ * Decides how to name and tag spans. By default they are named the same as the http method
+ */
+ @Bean
+ public HttpTracing httpTracing(Tracing tracing) {
+ return HttpTracing.create(tracing);
+ }
+
+ /**
+ * Creates server spans for http requests
+ */
+ @Bean
+ public Filter tracingFilter(HttpTracing httpTracing) { // 拦截请求,记录 HTTP 请求的链路信息
+ return TracingFilter.create(httpTracing);
+ }
+
+ // ==================== SpringMVC 相关 ====================
+ // @see SpringMvcConfiguration 类上的,@Import(SpanCustomizingAsyncHandlerInterceptor.class) 。因为 SpanCustomizingAsyncHandlerInterceptor 未提供 public 构造方法
+
+}
diff --git a/lab-40/lab-40-springmvc/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/controller/DemoController.java b/lab-40/lab-40-springmvc/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/controller/DemoController.java
new file mode 100644
index 000000000..8a05d588f
--- /dev/null
+++ b/lab-40/lab-40-springmvc/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/controller/DemoController.java
@@ -0,0 +1,16 @@
+package cn.iocoder.springboot.lab40.zipkindemo.controller;
+
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/demo")
+public class DemoController {
+
+ @GetMapping("/springmvc")
+ public String echo() {
+ return "springmvc";
+ }
+
+}
diff --git a/lab-40/lab-40-springmvc/src/main/resources/application.yaml b/lab-40/lab-40-springmvc/src/main/resources/application.yaml
new file mode 100644
index 000000000..f43d7aa24
--- /dev/null
+++ b/lab-40/lab-40-springmvc/src/main/resources/application.yaml
@@ -0,0 +1,3 @@
+spring:
+ application:
+ name: demo-application-springmvc
diff --git a/lab-40/pom.xml b/lab-40/pom.xml
index 75f1eee48..76a36bf11 100644
--- a/lab-40/pom.xml
+++ b/lab-40/pom.xml
@@ -13,6 +13,12 @@
pom
lab-40-demo
+ lab-40-springmvc
+ lab-40-mysql
+
+ lab-40-redis
+
+ lab-40-logback