增加 zipkin 示例

This commit is contained in:
YunaiV
2020-01-07 22:15:35 +08:00
parent cdef8e8780
commit f93680d62e
29 changed files with 956 additions and 25 deletions

View File

@@ -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 入门》计划中...
## 性能测试

View File

@@ -11,6 +11,7 @@
<modelVersion>4.0.0</modelVersion>
<artifactId>lab-40-demo</artifactId>
<packaging>jar</packaging>
<dependencies>
<!-- 实现对 SpringMVC 的自动化配置 -->
@@ -19,29 +20,13 @@
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- HttpClient 库 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<!-- Adds the MVC class and method names to server spans -->
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-instrumentation-spring-webmvc</artifactId>
</dependency>
<!-- Instruments the underlying HttpClient requests that call the backend -->
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-instrumentation-httpclient</artifactId>
</dependency>
<!-- Integrates so you can use log patterns like %X{traceId}/%X{spanId} -->
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-context-slf4j</artifactId>
</dependency>
<!-- Brave 核心库 -->
<!-- The below are needed to report traces to http://localhost:9411/api/v2/spans -->
<dependency>
<groupId>io.zipkin.brave</groupId>
@@ -52,9 +37,29 @@
<artifactId>zipkin-sender-okhttp3</artifactId>
</dependency>
<!-- Adds the MVC class and method names to server spans -->
<!-- Brave 对 Spring MVC 的支持 -->
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-instrumentation-spring-webmvc</artifactId>
</dependency>
<!-- Instruments the underlying HttpClient requests that call the backend -->
<!-- Brave 对 HttpClient 的支持 -->
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-instrumentation-httpclient</artifactId>
</dependency>
<!-- Integrates so you can use log patterns like %X{traceId}/%X{spanId} -->
<!-- Brave 对 SLF4J 的支持 -->
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-context-slf4j</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<!-- Brave Bom 文件 -->
<dependencies>
<dependency>
<groupId>io.zipkin.brave</groupId>
@@ -66,4 +71,16 @@
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -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) {

View File

@@ -5,8 +5,6 @@ import brave.SpanCustomizer;
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 @@ import javax.servlet.Filter;
@Configuration
public class ZipkinConfiguration {
// ==================== 通用配置 ====================
/**
* Configuration for how to send spans to Zipkin
*/
@@ -48,7 +48,6 @@ public class ZipkinConfiguration {
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()

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>lab-40-logback</artifactId>
<dependencies>
<!-- 实现对 SpringMVC 的自动化配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Brave 核心库 -->
<!-- The below are needed to report traces to http://localhost:9411/api/v2/spans -->
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-sender-okhttp3</artifactId>
</dependency>
<!-- Adds the MVC class and method names to server spans -->
<!-- Brave 对 Spring MVC 的支持 -->
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-instrumentation-spring-webmvc</artifactId>
</dependency>
<!-- Integrates so you can use log patterns like %X{traceId}/%X{spanId} -->
<!-- Brave 对 SLF4J 的支持 -->
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-context-slf4j</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<!-- Brave Bom 文件 -->
<dependencies>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-bom</artifactId>
<version>5.9.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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<Span> 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)
}

View File

@@ -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";
}
}

View File

@@ -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}"

View File

@@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>lab-40-mysql</artifactId>
<dependencies>
<!-- 实现对 SpringMVC 的自动化配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 实现对数据库连接池的自动化配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency> <!-- 本示例,我们使用 MySQL -->
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<!-- Brave 核心库 -->
<!-- The below are needed to report traces to http://localhost:9411/api/v2/spans -->
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-sender-okhttp3</artifactId>
</dependency>
<!-- Adds the MVC class and method names to server spans -->
<!-- Brave 对 Spring MVC 的支持 -->
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-instrumentation-spring-webmvc</artifactId>
</dependency>
<!-- Brave 对 MySQL 的支持 -->
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-instrumentation-mysql</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<!-- Brave Bom 文件 -->
<dependencies>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-bom</artifactId>
<version>5.9.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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<Span> 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)
}

View File

@@ -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);
}
}

View File

@@ -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:

View File

@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>lab-40-redis</artifactId>
<dependencies>
<!-- 实现对 SpringMVC 的自动化配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 实现对 Spring Data Redis 的自动化配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<!-- 去掉对 Lettuce 的依赖,因为 Spring Boot 优先使用 Lettuce 作为 Redis 客户端 -->
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 引入 Jedis 的依赖,这样 Spring Boot 实现对 Jedis 的自动化配置 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<!-- Brave 核心库 -->
<!-- The below are needed to report traces to http://localhost:9411/api/v2/spans -->
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-sender-okhttp3</artifactId>
</dependency>
<!-- Adds the MVC class and method names to server spans -->
<!-- Brave 对 Spring MVC 的支持 -->
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-instrumentation-spring-webmvc</artifactId>
</dependency>
<!-- Brave 对 Opentracing 的实现 -->
<dependency>
<groupId>io.opentracing.brave</groupId>
<artifactId>brave-opentracing</artifactId>
<version>0.35.0</version>
</dependency>
<!-- Opentracing 对 Redis 的支持 -->
<dependency>
<groupId>io.opentracing.contrib</groupId>
<artifactId>opentracing-redis-jedis3</artifactId>
<version>0.1.14</version>
</dependency>
<dependency>
<groupId>io.opentracing.contrib</groupId>
<artifactId>opentracing-redis-spring-data</artifactId>
<version>0.1.14</version>
</dependency>
</dependencies>
<dependencyManagement>
<!-- Brave Bom 文件 -->
<dependencies>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-bom</artifactId>
<version>5.9.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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<Span> 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);
}
}

View File

@@ -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);
}
}

View File

@@ -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 ,表示不限制。

View File

@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>lab-40-springmvc</artifactId>
<dependencies>
<!-- 实现对 SpringMVC 的自动化配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Brave 核心库 -->
<!-- The below are needed to report traces to http://localhost:9411/api/v2/spans -->
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-sender-okhttp3</artifactId>
</dependency>
<!-- Adds the MVC class and method names to server spans -->
<!-- Brave 对 Spring MVC 的支持 -->
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-instrumentation-spring-webmvc</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<!-- Brave Bom 文件 -->
<dependencies>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-bom</artifactId>
<version>5.9.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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<Span> 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 构造方法
}

View File

@@ -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";
}
}

View File

@@ -0,0 +1,3 @@
spring:
application:
name: demo-application-springmvc

View File

@@ -13,6 +13,12 @@
<packaging>pom</packaging>
<modules>
<module>lab-40-demo</module>
<module>lab-40-springmvc</module>
<module>lab-40-mysql</module>
<module>lab-40-redis</module>
<module>lab-40-logback</module>
</modules>