From b9ea05b75fefec555fe1d8788b50bad22c0de134 Mon Sep 17 00:00:00 2001
From: YunaiV <>
Date: Wed, 8 Jan 2020 20:57:20 +0800
Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20zipkin=20=E7=A4=BA?=
=?UTF-8?q?=E4=BE=8B=EF=BC=8C=E5=90=84=E7=A7=8D=E6=8A=8A?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../skywalkingdemo/consumer/DemoConsumer.java | 2 +-
.../skywalkingdemo/message/DemoMessage.java | 2 +-
.../skywalkingdemo/producer/DemoProducer.java | 2 +-
lab-40/lab-40-activemq/pom.xml | 66 +++++++++
.../lab40/zipkindemo/ActiveMQApplication.java | 13 ++
.../config/SpringMvcConfiguration.java | 25 ++++
.../config/ZipkinConfiguration.java | 112 ++++++++++++++
.../zipkindemo/consumer/DemoConsumer.java | 19 +++
.../zipkindemo/controller/DemoController.java | 26 ++++
.../lab40/zipkindemo/message/DemoMessage.java | 30 ++++
.../zipkindemo/producer/DemoProducer.java | 22 +++
.../src/main/resources/application.yaml | 11 ++
lab-40/lab-40-elasticsearch/pom.xml | 75 ++++++++++
.../zipkindemo/ElasticsearchApplication.java | 13 ++
.../config/SpringMvcConfiguration.java | 25 ++++
.../config/ZipkinConfiguration.java | 110 ++++++++++++++
.../zipkindemo/controller/DemoController.java | 27 ++++
.../lab40/zipkindemo/dataobject/ESUserDO.java | 41 ++++++
.../repository/ESUserRepository.java | 8 +
.../lab40/zipkindemo/spring/ClusterNodes.java | 81 ++++++++++
.../TracingTransportClientFactoryBean.java | 138 ++++++++++++++++++
.../src/main/resources/application.yml | 9 ++
.../config/ZipkinConfiguration.java | 5 +-
lab-40/lab-40-mongodb/pom.xml | 74 ++++++++++
.../lab40/zipkin/MongoDBApplication.java | 13 ++
.../zipkin/config/SpringMvcConfiguration.java | 25 ++++
.../zipkin/config/ZipkinConfiguration.java | 97 ++++++++++++
.../zipkin/controller/DemoController.java | 29 ++++
.../lab40/zipkin/dataobject/UserDO.java | 39 +++++
.../src/main/resources/application.yml | 13 ++
lab-40/lab-40-opentracing/pom.xml | 67 +++++++++
.../zipkindemo/OpentracingApplication.java | 13 ++
.../config/SpringMvcConfiguration.java | 25 ++++
.../config/ZipkinConfiguration.java | 85 +++++++++++
.../zipkindemo/controller/DemoController.java | 25 ++++
.../src/main/resources/application.yml | 3 +
lab-40/lab-40-rabbitmq/pom.xml | 66 +++++++++
.../lab40/zipkindemo/RabbitMQApplication.java | 13 ++
.../lab40/zipkindemo/config/RabbitConfig.java | 40 +++++
.../config/SpringMvcConfiguration.java | 25 ++++
.../config/ZipkinConfiguration.java | 117 +++++++++++++++
.../zipkindemo/consumer/DemoConsumer.java | 21 +++
.../zipkindemo/controller/DemoController.java | 26 ++++
.../lab40/zipkindemo/message/DemoMessage.java | 34 +++++
.../zipkindemo/producer/DemoProducer.java | 22 +++
.../src/main/resources/application.yaml | 10 ++
lab-40/pom.xml | 5 +
47 files changed, 1745 insertions(+), 4 deletions(-)
create mode 100644 lab-40/lab-40-activemq/pom.xml
create mode 100644 lab-40/lab-40-activemq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/ActiveMQApplication.java
create mode 100644 lab-40/lab-40-activemq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/SpringMvcConfiguration.java
create mode 100644 lab-40/lab-40-activemq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java
create mode 100644 lab-40/lab-40-activemq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/consumer/DemoConsumer.java
create mode 100644 lab-40/lab-40-activemq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/controller/DemoController.java
create mode 100644 lab-40/lab-40-activemq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/message/DemoMessage.java
create mode 100644 lab-40/lab-40-activemq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/producer/DemoProducer.java
create mode 100644 lab-40/lab-40-activemq/src/main/resources/application.yaml
create mode 100644 lab-40/lab-40-elasticsearch/pom.xml
create mode 100644 lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/ElasticsearchApplication.java
create mode 100644 lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/SpringMvcConfiguration.java
create mode 100644 lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java
create mode 100644 lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/controller/DemoController.java
create mode 100644 lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/dataobject/ESUserDO.java
create mode 100644 lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/repository/ESUserRepository.java
create mode 100644 lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/spring/ClusterNodes.java
create mode 100644 lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/spring/TracingTransportClientFactoryBean.java
create mode 100644 lab-40/lab-40-elasticsearch/src/main/resources/application.yml
create mode 100644 lab-40/lab-40-mongodb/pom.xml
create mode 100644 lab-40/lab-40-mongodb/src/main/java/cn/iocoder/springboot/lab40/zipkin/MongoDBApplication.java
create mode 100644 lab-40/lab-40-mongodb/src/main/java/cn/iocoder/springboot/lab40/zipkin/config/SpringMvcConfiguration.java
create mode 100644 lab-40/lab-40-mongodb/src/main/java/cn/iocoder/springboot/lab40/zipkin/config/ZipkinConfiguration.java
create mode 100644 lab-40/lab-40-mongodb/src/main/java/cn/iocoder/springboot/lab40/zipkin/controller/DemoController.java
create mode 100644 lab-40/lab-40-mongodb/src/main/java/cn/iocoder/springboot/lab40/zipkin/dataobject/UserDO.java
create mode 100644 lab-40/lab-40-mongodb/src/main/resources/application.yml
create mode 100644 lab-40/lab-40-opentracing/pom.xml
create mode 100644 lab-40/lab-40-opentracing/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/OpentracingApplication.java
create mode 100644 lab-40/lab-40-opentracing/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/SpringMvcConfiguration.java
create mode 100644 lab-40/lab-40-opentracing/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java
create mode 100644 lab-40/lab-40-opentracing/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/controller/DemoController.java
create mode 100644 lab-40/lab-40-opentracing/src/main/resources/application.yml
create mode 100644 lab-40/lab-40-rabbitmq/pom.xml
create mode 100644 lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/RabbitMQApplication.java
create mode 100644 lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/RabbitConfig.java
create mode 100644 lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/SpringMvcConfiguration.java
create mode 100644 lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java
create mode 100644 lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/consumer/DemoConsumer.java
create mode 100644 lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/controller/DemoController.java
create mode 100644 lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/message/DemoMessage.java
create mode 100644 lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/producer/DemoProducer.java
create mode 100644 lab-40/lab-40-rabbitmq/src/main/resources/application.yaml
diff --git a/lab-39/lab-39-activemq/src/main/java/cn/iocoder/springboot/lab39/skywalkingdemo/consumer/DemoConsumer.java b/lab-39/lab-39-activemq/src/main/java/cn/iocoder/springboot/lab39/skywalkingdemo/consumer/DemoConsumer.java
index eb30414dc..648f7bec0 100644
--- a/lab-39/lab-39-activemq/src/main/java/cn/iocoder/springboot/lab39/skywalkingdemo/consumer/DemoConsumer.java
+++ b/lab-39/lab-39-activemq/src/main/java/cn/iocoder/springboot/lab39/skywalkingdemo/consumer/DemoConsumer.java
@@ -1,6 +1,6 @@
package cn.iocoder.springboot.lab39.skywalkingdemo.consumer;
-import cn.iocoder.springboot.lab32.activemqdemo.message.DemoMessage;
+import cn.iocoder.springboot.lab39.skywalkingdemo.message.DemoMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jms.annotation.JmsListener;
diff --git a/lab-39/lab-39-activemq/src/main/java/cn/iocoder/springboot/lab39/skywalkingdemo/message/DemoMessage.java b/lab-39/lab-39-activemq/src/main/java/cn/iocoder/springboot/lab39/skywalkingdemo/message/DemoMessage.java
index cbf76260d..041f777a6 100644
--- a/lab-39/lab-39-activemq/src/main/java/cn/iocoder/springboot/lab39/skywalkingdemo/message/DemoMessage.java
+++ b/lab-39/lab-39-activemq/src/main/java/cn/iocoder/springboot/lab39/skywalkingdemo/message/DemoMessage.java
@@ -1,4 +1,4 @@
-package cn.iocoder.springboot.lab32.activemqdemo.message;
+package cn.iocoder.springboot.lab39.skywalkingdemo.message;
import java.io.Serializable;
diff --git a/lab-39/lab-39-activemq/src/main/java/cn/iocoder/springboot/lab39/skywalkingdemo/producer/DemoProducer.java b/lab-39/lab-39-activemq/src/main/java/cn/iocoder/springboot/lab39/skywalkingdemo/producer/DemoProducer.java
index 1136eaaf2..8a39554da 100644
--- a/lab-39/lab-39-activemq/src/main/java/cn/iocoder/springboot/lab39/skywalkingdemo/producer/DemoProducer.java
+++ b/lab-39/lab-39-activemq/src/main/java/cn/iocoder/springboot/lab39/skywalkingdemo/producer/DemoProducer.java
@@ -1,6 +1,6 @@
package cn.iocoder.springboot.lab39.skywalkingdemo.producer;
-import cn.iocoder.springboot.lab32.activemqdemo.message.DemoMessage;
+import cn.iocoder.springboot.lab39.skywalkingdemo.message.DemoMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Component;
diff --git a/lab-40/lab-40-activemq/pom.xml b/lab-40/lab-40-activemq/pom.xml
new file mode 100644
index 000000000..30119c575
--- /dev/null
+++ b/lab-40/lab-40-activemq/pom.xml
@@ -0,0 +1,66 @@
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.2.1.RELEASE
+
+
+ 4.0.0
+
+ lab-40-activemq
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-activemq
+
+
+
+
+ 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-instrumentation-jms
+
+
+
+
+
+
+
+
+ io.zipkin.brave
+ brave-bom
+ 5.9.1
+ pom
+ import
+
+
+
+
+
diff --git a/lab-40/lab-40-activemq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/ActiveMQApplication.java b/lab-40/lab-40-activemq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/ActiveMQApplication.java
new file mode 100644
index 000000000..8fcc36d2f
--- /dev/null
+++ b/lab-40/lab-40-activemq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/ActiveMQApplication.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 ActiveMQApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ActiveMQApplication.class, args);
+ }
+
+}
diff --git a/lab-40/lab-40-activemq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/SpringMvcConfiguration.java b/lab-40/lab-40-activemq/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-activemq/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-activemq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java b/lab-40/lab-40-activemq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java
new file mode 100644
index 000000000..925b57d85
--- /dev/null
+++ b/lab-40/lab-40-activemq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java
@@ -0,0 +1,112 @@
+package cn.iocoder.springboot.lab40.zipkindemo.config;
+
+import brave.CurrentSpanCustomizer;
+import brave.SpanCustomizer;
+import brave.Tracing;
+import brave.http.HttpTracing;
+import brave.jms.JmsTracing;
+import brave.servlet.TracingFilter;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+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.jms.ConnectionFactory;
+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 构造方法
+
+ // ==================== RabbitMQ 相关 ====================
+
+ @Bean
+ public JmsTracing jmsTracing(Tracing tracing) {
+ return JmsTracing.newBuilder(tracing)
+ .remoteServiceName("demo-mq-activemq") // 远程 ActiveMQ 服务名,可自定义
+ .build();
+ }
+
+ @Bean
+ public BeanPostProcessor activeMQBeanPostProcessor(JmsTracing jmsTracing) {
+ return new BeanPostProcessor() {
+
+ @Override
+ public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
+ return bean;
+ }
+
+ @Override
+ public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
+ // 如果是 ConnectionFactory ,针对 ActiveMQ Producer 和 Consumer
+ if (bean instanceof ConnectionFactory) {
+ return jmsTracing.connectionFactory((ConnectionFactory) bean);
+ }
+ return bean;
+ }
+
+ };
+ }
+
+}
diff --git a/lab-40/lab-40-activemq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/consumer/DemoConsumer.java b/lab-40/lab-40-activemq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/consumer/DemoConsumer.java
new file mode 100644
index 000000000..e9c5e66ab
--- /dev/null
+++ b/lab-40/lab-40-activemq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/consumer/DemoConsumer.java
@@ -0,0 +1,19 @@
+package cn.iocoder.springboot.lab40.zipkindemo.consumer;
+
+import cn.iocoder.springboot.lab40.zipkindemo.message.DemoMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.jms.annotation.JmsListener;
+import org.springframework.stereotype.Component;
+
+@Component
+public class DemoConsumer {
+
+ private Logger logger = LoggerFactory.getLogger(getClass());
+
+ @JmsListener(destination = DemoMessage.QUEUE)
+ public void onMessage(DemoMessage message) {
+ logger.info("[onMessage][线程编号:{} 消息内容:{}]", Thread.currentThread().getId(), message);
+ }
+
+}
diff --git a/lab-40/lab-40-activemq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/controller/DemoController.java b/lab-40/lab-40-activemq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/controller/DemoController.java
new file mode 100644
index 000000000..7fa8c8d49
--- /dev/null
+++ b/lab-40/lab-40-activemq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/controller/DemoController.java
@@ -0,0 +1,26 @@
+package cn.iocoder.springboot.lab40.zipkindemo.controller;
+
+import cn.iocoder.springboot.lab40.zipkindemo.producer.DemoProducer;
+import org.springframework.beans.factory.annotation.Autowired;
+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 DemoProducer producer;
+
+ @GetMapping("/activemq")
+ public String echo() {
+ this.sendMessage(1);
+ return "activemq";
+ }
+
+ public void sendMessage(Integer id) {
+ producer.syncSend(id);
+ }
+
+}
diff --git a/lab-40/lab-40-activemq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/message/DemoMessage.java b/lab-40/lab-40-activemq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/message/DemoMessage.java
new file mode 100644
index 000000000..47ffc39ff
--- /dev/null
+++ b/lab-40/lab-40-activemq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/message/DemoMessage.java
@@ -0,0 +1,30 @@
+package cn.iocoder.springboot.lab40.zipkindemo.message;
+
+import java.io.Serializable;
+
+public class DemoMessage implements Serializable {
+
+ public static final String QUEUE = "QUEUE_DEMO_";
+
+ /**
+ * 编号
+ */
+ private Integer id;
+
+ public DemoMessage setId(Integer id) {
+ this.id = id;
+ return this;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ @Override
+ public String toString() {
+ return "DemoMessage{" +
+ "id=" + id +
+ '}';
+ }
+
+}
diff --git a/lab-40/lab-40-activemq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/producer/DemoProducer.java b/lab-40/lab-40-activemq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/producer/DemoProducer.java
new file mode 100644
index 000000000..30c3e4035
--- /dev/null
+++ b/lab-40/lab-40-activemq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/producer/DemoProducer.java
@@ -0,0 +1,22 @@
+package cn.iocoder.springboot.lab40.zipkindemo.producer;
+
+import cn.iocoder.springboot.lab40.zipkindemo.message.DemoMessage;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jms.core.JmsMessagingTemplate;
+import org.springframework.stereotype.Component;
+
+@Component
+public class DemoProducer {
+
+ @Autowired
+ private JmsMessagingTemplate jmsTemplate;
+
+ public void syncSend(Integer id) {
+ // 创建 DemoMessage 消息
+ DemoMessage message = new DemoMessage();
+ message.setId(id);
+ // 同步发送消息
+ jmsTemplate.convertAndSend(DemoMessage.QUEUE, message);
+ }
+
+}
diff --git a/lab-40/lab-40-activemq/src/main/resources/application.yaml b/lab-40/lab-40-activemq/src/main/resources/application.yaml
new file mode 100644
index 000000000..375a4a1ce
--- /dev/null
+++ b/lab-40/lab-40-activemq/src/main/resources/application.yaml
@@ -0,0 +1,11 @@
+spring:
+ application:
+ name: demo-application-activemq
+
+ # ActiveMQ 配置项,对应 ActiveMQProperties 配置类
+ activemq:
+ broker-url: tcp://127.0.0.1:61616 # Activemq Broker 的地址
+ user: admin # 账号
+ password: admin # 密码
+ packages:
+ trust-all: true # 可信任的反序列化包
diff --git a/lab-40/lab-40-elasticsearch/pom.xml b/lab-40/lab-40-elasticsearch/pom.xml
new file mode 100644
index 000000000..b9133bca2
--- /dev/null
+++ b/lab-40/lab-40-elasticsearch/pom.xml
@@ -0,0 +1,75 @@
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.2.1.RELEASE
+
+
+ 4.0.0
+
+ lab-40-elasticsearch
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-elasticsearch
+
+
+
+
+
+ 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-elasticsearch6-client
+ 0.1.6
+
+
+
+
+
+
+
+
+ io.zipkin.brave
+ brave-bom
+ 5.9.1
+ pom
+ import
+
+
+
+
+
diff --git a/lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/ElasticsearchApplication.java b/lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/ElasticsearchApplication.java
new file mode 100644
index 000000000..cad36f966
--- /dev/null
+++ b/lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/ElasticsearchApplication.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 ElasticsearchApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(ElasticsearchApplication.class, args);
+ }
+
+}
diff --git a/lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/SpringMvcConfiguration.java b/lab-40/lab-40-elasticsearch/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-elasticsearch/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-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java b/lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java
new file mode 100644
index 000000000..a29b2be65
--- /dev/null
+++ b/lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java
@@ -0,0 +1,110 @@
+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 cn.iocoder.springboot.lab40.zipkindemo.spring.TracingTransportClientFactoryBean;
+import io.opentracing.Tracer;
+import org.elasticsearch.client.transport.TransportClient;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchProperties;
+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;
+import java.util.Properties;
+
+@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)
+
+ // ==================== Elasticsearch 相关 ====================
+
+ @Bean
+ public TransportClient elasticsearchClient(Tracer tracer, ElasticsearchProperties elasticsearchProperties) throws Exception {
+ // 创建 TracingTransportClientFactoryBean 对象
+ TracingTransportClientFactoryBean factory = new TracingTransportClientFactoryBean(tracer);
+ // 设置其属性
+ factory.setClusterNodes(elasticsearchProperties.getClusterNodes());
+ factory.setProperties(this.createElasticsearch(elasticsearchProperties));
+ // 创建 TransportClient 对象,并返回
+ factory.afterPropertiesSet();
+ return factory.getObject();
+ }
+
+ private Properties createElasticsearch(ElasticsearchProperties elasticsearchProperties) {
+ Properties properties = new Properties();
+ properties.put("cluster.name", elasticsearchProperties.getClusterName());
+ properties.putAll(elasticsearchProperties.getProperties());
+ return properties;
+ }
+
+}
diff --git a/lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/controller/DemoController.java b/lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/controller/DemoController.java
new file mode 100644
index 000000000..9e581a9ba
--- /dev/null
+++ b/lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/controller/DemoController.java
@@ -0,0 +1,27 @@
+package cn.iocoder.springboot.lab40.zipkindemo.controller;
+
+import cn.iocoder.springboot.lab40.zipkindemo.dataobject.ESUserDO;
+import cn.iocoder.springboot.lab40.zipkindemo.repository.ESUserRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+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 ESUserRepository userRepository;
+
+ @GetMapping("/elasticsearch")
+ public String mysql() {
+ this.findById(1);
+ return "elasticsearch";
+ }
+
+ public ESUserDO findById(Integer id) {
+ return userRepository.findById(id).orElse(null);
+ }
+
+}
diff --git a/lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/dataobject/ESUserDO.java b/lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/dataobject/ESUserDO.java
new file mode 100644
index 000000000..66d915969
--- /dev/null
+++ b/lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/dataobject/ESUserDO.java
@@ -0,0 +1,41 @@
+package cn.iocoder.springboot.lab40.zipkindemo.dataobject;
+
+import org.springframework.data.annotation.Id;
+import org.springframework.data.elasticsearch.annotations.Document;
+
+import java.util.Date;
+
+@Document(indexName = "user", // 索引名
+ type = "user", // 类型。未来的版本即将废弃
+ shards = 1, // 默认索引分区数
+ replicas = 0, // 每个分区的备份数
+ refreshInterval = "-1" // 刷新间隔
+)
+public class ESUserDO {
+
+ @Id
+ private Integer id;
+ /**
+ * 账号
+ */
+ private String username;
+ /**
+ * 密码
+ */
+ private String password;
+ /**
+ * 创建时间
+ */
+ private Date createTime;
+
+ @Override
+ public String toString() {
+ return "UserDO{" +
+ "id=" + id +
+ ", username='" + username + '\'' +
+ ", password='" + password + '\'' +
+ ", createTime=" + createTime +
+ '}';
+ }
+
+}
diff --git a/lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/repository/ESUserRepository.java b/lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/repository/ESUserRepository.java
new file mode 100644
index 000000000..4add2c4ce
--- /dev/null
+++ b/lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/repository/ESUserRepository.java
@@ -0,0 +1,8 @@
+package cn.iocoder.springboot.lab40.zipkindemo.repository;
+
+import cn.iocoder.springboot.lab40.zipkindemo.dataobject.ESUserDO;
+import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
+
+public interface ESUserRepository extends ElasticsearchRepository {
+
+}
diff --git a/lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/spring/ClusterNodes.java b/lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/spring/ClusterNodes.java
new file mode 100644
index 000000000..0643d7487
--- /dev/null
+++ b/lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/spring/ClusterNodes.java
@@ -0,0 +1,81 @@
+package cn.iocoder.springboot.lab40.zipkindemo.spring;
+
+import org.elasticsearch.common.transport.TransportAddress;
+import org.springframework.data.util.Streamable;
+import org.springframework.util.Assert;
+import org.springframework.util.StringUtils;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.stream.Collectors;
+
+class ClusterNodes implements Streamable {
+
+ public static ClusterNodes DEFAULT = ClusterNodes.of("127.0.0.1:9300");
+
+ private static final String COLON = ":";
+ private static final String COMMA = ",";
+
+ private final List clusterNodes;
+
+ /**
+ * Creates a new {@link ClusterNodes} by parsing the given source.
+ *
+ * @param source must not be {@literal null} or empty.
+ */
+ private ClusterNodes(String source) {
+
+ Assert.hasText(source, "Cluster nodes source must not be null or empty!");
+
+ String[] nodes = StringUtils.delimitedListToStringArray(source, COMMA);
+
+ this.clusterNodes = Arrays.stream(nodes).map(node -> {
+
+ String[] segments = StringUtils.delimitedListToStringArray(node, COLON);
+
+ Assert.isTrue(segments.length == 2,
+ () -> String.format("Invalid cluster node %s in %s! Must be in the format host:port!", node, source));
+
+ String host = segments[0].trim();
+ String port = segments[1].trim();
+
+ Assert.hasText(host, () -> String.format("No host name given cluster node %s!", node));
+ Assert.hasText(port, () -> String.format("No port given in cluster node %s!", node));
+
+ return new TransportAddress(toInetAddress(host), Integer.valueOf(port));
+
+ }).collect(Collectors.toList());
+ }
+
+ /**
+ * Creates a new {@link ClusterNodes} by parsing the given source. The expected format is a comma separated list of
+ * host-port-combinations separated by a colon: {@code host:port,host:port,…}.
+ *
+ * @param source must not be {@literal null} or empty.
+ * @return
+ */
+ public static ClusterNodes of(String source) {
+ return new ClusterNodes(source);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see java.lang.Iterable#iterator()
+ */
+ @Override
+ public Iterator iterator() {
+ return clusterNodes.iterator();
+ }
+
+ private static InetAddress toInetAddress(String host) {
+
+ try {
+ return InetAddress.getByName(host);
+ } catch (UnknownHostException o_O) {
+ throw new IllegalArgumentException(o_O);
+ }
+ }
+}
diff --git a/lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/spring/TracingTransportClientFactoryBean.java b/lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/spring/TracingTransportClientFactoryBean.java
new file mode 100644
index 000000000..6076b98d0
--- /dev/null
+++ b/lab-40/lab-40-elasticsearch/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/spring/TracingTransportClientFactoryBean.java
@@ -0,0 +1,138 @@
+package cn.iocoder.springboot.lab40.zipkindemo.spring;
+
+import io.opentracing.Tracer;
+import io.opentracing.contrib.elasticsearch6.TracingPreBuiltTransportClient;
+import org.elasticsearch.client.transport.TransportClient;
+import org.elasticsearch.common.settings.Settings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.data.elasticsearch.client.TransportClientFactoryBean;
+
+import java.util.Properties;
+
+/**
+ * 参考 {@link TransportClientFactoryBean} 来实现。
+ */
+public class TracingTransportClientFactoryBean implements FactoryBean, InitializingBean, DisposableBean {
+
+ private static final Logger logger = LoggerFactory.getLogger(TransportClientFactoryBean.class);
+ private ClusterNodes clusterNodes = ClusterNodes.of("127.0.0.1:9300");
+ private String clusterName = "elasticsearch";
+ private Boolean clientTransportSniff = true;
+ private Boolean clientIgnoreClusterName = Boolean.FALSE;
+ private String clientPingTimeout = "5s";
+ private String clientNodesSamplerInterval = "5s";
+ private TransportClient client;
+ private Properties properties;
+
+ private Tracer tracer;
+
+ public TracingTransportClientFactoryBean(Tracer tracer) {
+ this.tracer = tracer;
+ }
+
+ @Override
+ public void destroy() throws Exception {
+ try {
+ logger.info("Closing elasticSearch client");
+ if (client != null) {
+ client.close();
+ }
+ } catch (final Exception e) {
+ logger.error("Error closing ElasticSearch client: ", e);
+ }
+ }
+
+ @Override
+ public TransportClient getObject() throws Exception {
+ return client;
+ }
+
+ @Override
+ public Class getObjectType() {
+ return TransportClient.class;
+ }
+
+ @Override
+ public boolean isSingleton() {
+ return true;
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ buildClient();
+ }
+
+ protected void buildClient() throws Exception {
+ // 创建可追踪的 TracingPreBuiltTransportClient
+ client = new TracingPreBuiltTransportClient(tracer, settings());
+
+ clusterNodes.stream() //
+ .peek(it -> logger.info("Adding transport node : " + it.toString())) //
+ .forEach(client::addTransportAddress);
+
+ client.connectedNodes();
+ }
+
+ private Settings settings() {
+ if (properties != null) {
+ Settings.Builder builder = Settings.builder();
+
+ properties.forEach((key, value) -> {
+ builder.put(key.toString(), value.toString());
+ });
+
+ return builder.build();
+ }
+ return Settings.builder()
+ .put("cluster.name", clusterName)
+ .put("client.transport.sniff", clientTransportSniff)
+ .put("client.transport.ignore_cluster_name", clientIgnoreClusterName)
+ .put("client.transport.ping_timeout", clientPingTimeout)
+ .put("client.transport.nodes_sampler_interval", clientNodesSamplerInterval)
+ .build();
+ }
+
+ public void setClusterNodes(String clusterNodes) {
+ this.clusterNodes = ClusterNodes.of(clusterNodes);
+ }
+
+ public void setClusterName(String clusterName) {
+ this.clusterName = clusterName;
+ }
+
+ public void setClientTransportSniff(Boolean clientTransportSniff) {
+ this.clientTransportSniff = clientTransportSniff;
+ }
+
+ public String getClientNodesSamplerInterval() {
+ return clientNodesSamplerInterval;
+ }
+
+ public void setClientNodesSamplerInterval(String clientNodesSamplerInterval) {
+ this.clientNodesSamplerInterval = clientNodesSamplerInterval;
+ }
+
+ public String getClientPingTimeout() {
+ return clientPingTimeout;
+ }
+
+ public void setClientPingTimeout(String clientPingTimeout) {
+ this.clientPingTimeout = clientPingTimeout;
+ }
+
+ public Boolean getClientIgnoreClusterName() {
+ return clientIgnoreClusterName;
+ }
+
+ public void setClientIgnoreClusterName(Boolean clientIgnoreClusterName) {
+ this.clientIgnoreClusterName = clientIgnoreClusterName;
+ }
+
+ public void setProperties(Properties properties) {
+ this.properties = properties;
+ }
+}
diff --git a/lab-40/lab-40-elasticsearch/src/main/resources/application.yml b/lab-40/lab-40-elasticsearch/src/main/resources/application.yml
new file mode 100644
index 000000000..b4b5c397e
--- /dev/null
+++ b/lab-40/lab-40-elasticsearch/src/main/resources/application.yml
@@ -0,0 +1,9 @@
+spring:
+ application:
+ name: demo-application-elasticsearch
+
+ data:
+ # Elasticsearch 配置项
+ elasticsearch:
+ cluster-name: elasticsearch # 集群名
+ cluster-nodes: 127.0.0.1:9300 # 集群节点
diff --git a/lab-40/lab-40-kafka/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java b/lab-40/lab-40-kafka/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java
index 5acef128f..ee3efff41 100644
--- a/lab-40/lab-40-kafka/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java
+++ b/lab-40/lab-40-kafka/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java
@@ -89,12 +89,13 @@ public Filter tracingFilter(HttpTracing httpTracing) { // 拦截请求,记录
@Bean
public KafkaTracing kafkaTracing(Tracing tracing) {
return KafkaTracing.newBuilder(tracing)
- .remoteServiceName("demo-mq-kafka")
+ .remoteServiceName("demo-mq-kafka") // 远程 Kafka 服务名,可自定义
.build();
}
@Bean
public ProducerFactory, ?> kafkaProducerFactory(KafkaProperties properties, KafkaTracing kafkaTracing) {
+ // 创建 DefaultKafkaProducerFactory 对象
DefaultKafkaProducerFactory, ?> factory = new DefaultKafkaProducerFactory(properties.buildProducerProperties()) {
@Override
@@ -107,6 +108,7 @@ public Producer createProducer() {
};
+ // 设置事务前缀
String transactionIdPrefix = properties.getProducer().getTransactionIdPrefix();
if (transactionIdPrefix != null) {
factory.setTransactionIdPrefix(transactionIdPrefix);
@@ -117,6 +119,7 @@ public Producer createProducer() {
@Bean
public ConsumerFactory, ?> kafkaConsumerFactory(KafkaProperties properties, KafkaTracing kafkaTracing) {
+ // 创建 DefaultKafkaConsumerFactory 对象
return new DefaultKafkaConsumerFactory(properties.buildConsumerProperties()) {
@Override
diff --git a/lab-40/lab-40-mongodb/pom.xml b/lab-40/lab-40-mongodb/pom.xml
new file mode 100644
index 000000000..606109ebc
--- /dev/null
+++ b/lab-40/lab-40-mongodb/pom.xml
@@ -0,0 +1,74 @@
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.2.2.RELEASE
+
+
+ 4.0.0
+
+ lab-40-mongodb
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-mongodb
+
+
+
+
+
+ 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-mongo-driver
+ 0.1.5
+
+
+
+
+
+
+
+ io.zipkin.brave
+ brave-bom
+ 5.9.1
+ pom
+ import
+
+
+
+
+
diff --git a/lab-40/lab-40-mongodb/src/main/java/cn/iocoder/springboot/lab40/zipkin/MongoDBApplication.java b/lab-40/lab-40-mongodb/src/main/java/cn/iocoder/springboot/lab40/zipkin/MongoDBApplication.java
new file mode 100644
index 000000000..42f1b0fbd
--- /dev/null
+++ b/lab-40/lab-40-mongodb/src/main/java/cn/iocoder/springboot/lab40/zipkin/MongoDBApplication.java
@@ -0,0 +1,13 @@
+package cn.iocoder.springboot.lab40.zipkin;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class MongoDBApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(MongoDBApplication.class, args);
+ }
+
+}
diff --git a/lab-40/lab-40-mongodb/src/main/java/cn/iocoder/springboot/lab40/zipkin/config/SpringMvcConfiguration.java b/lab-40/lab-40-mongodb/src/main/java/cn/iocoder/springboot/lab40/zipkin/config/SpringMvcConfiguration.java
new file mode 100644
index 000000000..b9df30026
--- /dev/null
+++ b/lab-40/lab-40-mongodb/src/main/java/cn/iocoder/springboot/lab40/zipkin/config/SpringMvcConfiguration.java
@@ -0,0 +1,25 @@
+package cn.iocoder.springboot.lab40.zipkin.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-mongodb/src/main/java/cn/iocoder/springboot/lab40/zipkin/config/ZipkinConfiguration.java b/lab-40/lab-40-mongodb/src/main/java/cn/iocoder/springboot/lab40/zipkin/config/ZipkinConfiguration.java
new file mode 100644
index 000000000..86cdf1c1c
--- /dev/null
+++ b/lab-40/lab-40-mongodb/src/main/java/cn/iocoder/springboot/lab40/zipkin/config/ZipkinConfiguration.java
@@ -0,0 +1,97 @@
+package cn.iocoder.springboot.lab40.zipkin.config;
+
+import brave.CurrentSpanCustomizer;
+import brave.SpanCustomizer;
+import brave.Tracing;
+import brave.http.HttpTracing;
+import brave.opentracing.BraveTracer;
+import brave.servlet.TracingFilter;
+import com.mongodb.MongoClientOptions;
+import io.opentracing.Tracer;
+import io.opentracing.contrib.mongo.common.TracingCommandListener;
+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();
+ }
+
+ @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)
+
+ // ==================== MongoDB 相关 ====================
+
+ @Bean
+ public MongoClientOptions mongoClientOptions(Tracer tracer) {
+ // 创建 TracingCommandListener 对象
+ TracingCommandListener listener = new TracingCommandListener.Builder(tracer).build();
+ // 创建 MongoClientOptions 对象,并设置监听器
+ return MongoClientOptions.builder().addCommandListener(listener).build();
+ }
+
+}
diff --git a/lab-40/lab-40-mongodb/src/main/java/cn/iocoder/springboot/lab40/zipkin/controller/DemoController.java b/lab-40/lab-40-mongodb/src/main/java/cn/iocoder/springboot/lab40/zipkin/controller/DemoController.java
new file mode 100644
index 000000000..98155a7b6
--- /dev/null
+++ b/lab-40/lab-40-mongodb/src/main/java/cn/iocoder/springboot/lab40/zipkin/controller/DemoController.java
@@ -0,0 +1,29 @@
+package cn.iocoder.springboot.lab40.zipkin.controller;
+
+import cn.iocoder.springboot.lab40.zipkin.dataobject.UserDO;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
+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 MongoTemplate mongoTemplate;
+
+ @GetMapping("/mongodb")
+ public String mysql() {
+ this.findById(1);
+ return "mongodb";
+ }
+
+ public UserDO findById(Integer id) {
+ return mongoTemplate.findOne(new Query(Criteria.where("_id").is(id)), UserDO.class);
+ }
+
+}
diff --git a/lab-40/lab-40-mongodb/src/main/java/cn/iocoder/springboot/lab40/zipkin/dataobject/UserDO.java b/lab-40/lab-40-mongodb/src/main/java/cn/iocoder/springboot/lab40/zipkin/dataobject/UserDO.java
new file mode 100644
index 000000000..5166f0188
--- /dev/null
+++ b/lab-40/lab-40-mongodb/src/main/java/cn/iocoder/springboot/lab40/zipkin/dataobject/UserDO.java
@@ -0,0 +1,39 @@
+package cn.iocoder.springboot.lab40.zipkin.dataobject;
+
+import org.springframework.data.annotation.Id;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+import java.util.Date;
+
+/**
+ * 用户 DO
+ */
+@Document(collection = "User")
+public class UserDO {
+
+ @Id
+ private Integer id;
+ /**
+ * 账号
+ */
+ private String username;
+ /**
+ * 密码
+ */
+ private String password;
+ /**
+ * 创建时间
+ */
+ private Date createTime;
+
+ @Override
+ public String toString() {
+ return "UserDO{" +
+ "id=" + id +
+ ", username='" + username + '\'' +
+ ", password='" + password + '\'' +
+ ", createTime=" + createTime +
+ '}';
+ }
+
+}
diff --git a/lab-40/lab-40-mongodb/src/main/resources/application.yml b/lab-40/lab-40-mongodb/src/main/resources/application.yml
new file mode 100644
index 000000000..7ea58cb9b
--- /dev/null
+++ b/lab-40/lab-40-mongodb/src/main/resources/application.yml
@@ -0,0 +1,13 @@
+spring:
+ application:
+ name: dmeo-application-mongodb
+
+ data:
+ # MongoDB 配置项,对应 MongoProperties 类
+ mongodb:
+ host: 127.0.0.1
+ port: 27017
+ database: yourdatabase
+ username: test01
+ password: password01
+ # 上述属性,也可以只配置 uri
diff --git a/lab-40/lab-40-opentracing/pom.xml b/lab-40/lab-40-opentracing/pom.xml
new file mode 100644
index 000000000..ac11945b4
--- /dev/null
+++ b/lab-40/lab-40-opentracing/pom.xml
@@ -0,0 +1,67 @@
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.2.2.RELEASE
+
+
+ 4.0.0
+
+ lab-40-opentracing
+
+
+
+
+ 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.opentracing.brave
+ brave-opentracing
+ 0.35.0
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+
+
+
+ io.zipkin.brave
+ brave-bom
+ 5.9.1
+ pom
+ import
+
+
+
+
+
diff --git a/lab-40/lab-40-opentracing/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/OpentracingApplication.java b/lab-40/lab-40-opentracing/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/OpentracingApplication.java
new file mode 100644
index 000000000..9dd339019
--- /dev/null
+++ b/lab-40/lab-40-opentracing/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/OpentracingApplication.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 OpentracingApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(OpentracingApplication.class, args);
+ }
+
+}
diff --git a/lab-40/lab-40-opentracing/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/SpringMvcConfiguration.java b/lab-40/lab-40-opentracing/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-opentracing/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-opentracing/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java b/lab-40/lab-40-opentracing/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java
new file mode 100644
index 000000000..39c97bbbd
--- /dev/null
+++ b/lab-40/lab-40-opentracing/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java
@@ -0,0 +1,85 @@
+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 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();
+ }
+
+ @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)
+
+}
diff --git a/lab-40/lab-40-opentracing/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/controller/DemoController.java b/lab-40/lab-40-opentracing/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/controller/DemoController.java
new file mode 100644
index 000000000..3523819fa
--- /dev/null
+++ b/lab-40/lab-40-opentracing/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/controller/DemoController.java
@@ -0,0 +1,25 @@
+package cn.iocoder.springboot.lab40.zipkindemo.controller;
+
+import io.opentracing.Tracer;
+import org.springframework.beans.factory.annotation.Autowired;
+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 Tracer tracer;
+
+ @GetMapping("/opentracing")
+ public String echo() {
+ // 创建一个 Span
+ tracer.buildSpan("custom_operation").withTag("mp", "芋道源码").start().finish();
+
+ // 返回
+ return "opentracing";
+ }
+
+}
diff --git a/lab-40/lab-40-opentracing/src/main/resources/application.yml b/lab-40/lab-40-opentracing/src/main/resources/application.yml
new file mode 100644
index 000000000..d3e3997a6
--- /dev/null
+++ b/lab-40/lab-40-opentracing/src/main/resources/application.yml
@@ -0,0 +1,3 @@
+spring:
+ application:
+ name: demo-application-opentracing
diff --git a/lab-40/lab-40-rabbitmq/pom.xml b/lab-40/lab-40-rabbitmq/pom.xml
new file mode 100644
index 000000000..0744a693a
--- /dev/null
+++ b/lab-40/lab-40-rabbitmq/pom.xml
@@ -0,0 +1,66 @@
+
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.2.1.RELEASE
+
+
+ 4.0.0
+
+ lab-40-rabbitmq
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-amqp
+
+
+
+
+ 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-instrumentation-spring-rabbit
+
+
+
+
+
+
+
+
+ io.zipkin.brave
+ brave-bom
+ 5.9.1
+ pom
+ import
+
+
+
+
+
diff --git a/lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/RabbitMQApplication.java b/lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/RabbitMQApplication.java
new file mode 100644
index 000000000..76735d4c2
--- /dev/null
+++ b/lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/RabbitMQApplication.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 RabbitMQApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(RabbitMQApplication.class, args);
+ }
+
+}
diff --git a/lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/RabbitConfig.java b/lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/RabbitConfig.java
new file mode 100644
index 000000000..bf4f731ca
--- /dev/null
+++ b/lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/RabbitConfig.java
@@ -0,0 +1,40 @@
+package cn.iocoder.springboot.lab40.zipkindemo.config;
+
+import cn.iocoder.springboot.lab40.zipkindemo.message.DemoMessage;
+import org.springframework.amqp.core.Binding;
+import org.springframework.amqp.core.BindingBuilder;
+import org.springframework.amqp.core.DirectExchange;
+import org.springframework.amqp.core.Queue;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class RabbitConfig {
+
+ // 创建 Queue
+ @Bean
+ public Queue demoQueue() {
+ return new Queue(DemoMessage.QUEUE, // Queue 名字
+ true, // durable: 是否持久化
+ false, // exclusive: 是否排它
+ false); // autoDelete: 是否自动删除
+ }
+
+ // 创建 Direct Exchange
+ @Bean
+ public DirectExchange demoExchange() {
+ return new DirectExchange(DemoMessage.EXCHANGE,
+ true, // durable: 是否持久化
+ false); // exclusive: 是否排它
+ }
+
+ // 创建 Binding
+ // Exchange:DemoMessage.EXCHANGE
+ // Routing key:DemoMessage.ROUTING_KEY
+ // Queue:DemoMessage.QUEUE
+ @Bean
+ public Binding demoBinding() {
+ return BindingBuilder.bind(demoQueue()).to(demoExchange()).with(DemoMessage.ROUTING_KEY);
+ }
+
+}
diff --git a/lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/SpringMvcConfiguration.java b/lab-40/lab-40-rabbitmq/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-rabbitmq/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-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java b/lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java
new file mode 100644
index 000000000..2ab56c995
--- /dev/null
+++ b/lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/config/ZipkinConfiguration.java
@@ -0,0 +1,117 @@
+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 brave.spring.rabbit.SpringRabbitTracing;
+import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+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 构造方法
+
+ // ==================== RabbitMQ 相关 ====================
+
+ @Bean
+ public SpringRabbitTracing springRabbitTracing(Tracing tracing) {
+ return SpringRabbitTracing.newBuilder(tracing)
+ .remoteServiceName("demo-mq-rabbit") // 远程 RabbitMQ 服务名,可自定义
+ .build();
+ }
+
+ @Bean
+ public BeanPostProcessor rabbitmqBeanPostProcessor(SpringRabbitTracing springRabbitTracing) {
+ return new BeanPostProcessor() {
+
+ @Override
+ public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
+ return bean;
+ }
+
+ @Override
+ public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
+ // 如果是 RabbitTemplate ,针对 RabbitMQ Producer
+ if (bean instanceof RabbitTemplate) {
+ return springRabbitTracing.decorateRabbitTemplate((RabbitTemplate) bean);
+ }
+ // 如果是 SimpleRabbitListenerContainerFactory ,针对 RabbitMQ Consumer
+ if (bean instanceof SimpleRabbitListenerContainerFactory) {
+ return springRabbitTracing.decorateSimpleRabbitListenerContainerFactory((SimpleRabbitListenerContainerFactory) bean);
+ }
+ return bean;
+ }
+
+ };
+ }
+
+}
diff --git a/lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/consumer/DemoConsumer.java b/lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/consumer/DemoConsumer.java
new file mode 100644
index 000000000..94f69a48d
--- /dev/null
+++ b/lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/consumer/DemoConsumer.java
@@ -0,0 +1,21 @@
+package cn.iocoder.springboot.lab40.zipkindemo.consumer;
+
+import cn.iocoder.springboot.lab40.zipkindemo.message.DemoMessage;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.amqp.rabbit.annotation.RabbitHandler;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.stereotype.Component;
+
+@Component
+@RabbitListener(queues = DemoMessage.QUEUE)
+public class DemoConsumer {
+
+ private Logger logger = LoggerFactory.getLogger(getClass());
+
+ @RabbitHandler
+ public void onMessage(DemoMessage message) {
+ logger.info("[onMessage][线程编号:{} 消息内容:{}]", Thread.currentThread().getId(), message);
+ }
+
+}
diff --git a/lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/controller/DemoController.java b/lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/controller/DemoController.java
new file mode 100644
index 000000000..a52b568e6
--- /dev/null
+++ b/lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/controller/DemoController.java
@@ -0,0 +1,26 @@
+package cn.iocoder.springboot.lab40.zipkindemo.controller;
+
+import cn.iocoder.springboot.lab40.zipkindemo.producer.DemoProducer;
+import org.springframework.beans.factory.annotation.Autowired;
+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 DemoProducer producer;
+
+ @GetMapping("/rabbitmq")
+ public String echo() {
+ this.sendMessage(1);
+ return "rabbitmq";
+ }
+
+ public void sendMessage(Integer id) {
+ producer.syncSend(id);
+ }
+
+}
diff --git a/lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/message/DemoMessage.java b/lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/message/DemoMessage.java
new file mode 100644
index 000000000..e4e85b4f7
--- /dev/null
+++ b/lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/message/DemoMessage.java
@@ -0,0 +1,34 @@
+package cn.iocoder.springboot.lab40.zipkindemo.message;
+
+import java.io.Serializable;
+
+public class DemoMessage implements Serializable {
+
+ public static final String QUEUE = "QUEUE_DEMO_";
+
+ public static final String EXCHANGE = "EXCHANGE_DEMO_";
+
+ public static final String ROUTING_KEY = "ROUTING_KEY_";
+
+ /**
+ * 编号
+ */
+ private Integer id;
+
+ public DemoMessage setId(Integer id) {
+ this.id = id;
+ return this;
+ }
+
+ public Integer getId() {
+ return id;
+ }
+
+ @Override
+ public String toString() {
+ return "DemoMessage{" +
+ "id=" + id +
+ '}';
+ }
+
+}
diff --git a/lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/producer/DemoProducer.java b/lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/producer/DemoProducer.java
new file mode 100644
index 000000000..6c1e52891
--- /dev/null
+++ b/lab-40/lab-40-rabbitmq/src/main/java/cn/iocoder/springboot/lab40/zipkindemo/producer/DemoProducer.java
@@ -0,0 +1,22 @@
+package cn.iocoder.springboot.lab40.zipkindemo.producer;
+
+import cn.iocoder.springboot.lab40.zipkindemo.message.DemoMessage;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class DemoProducer {
+
+ @Autowired
+ private RabbitTemplate rabbitTemplate;
+
+ public void syncSend(Integer id) {
+ // 创建 DemoMessage 消息
+ DemoMessage message = new DemoMessage();
+ message.setId(id);
+ // 同步发送消息
+ rabbitTemplate.convertAndSend(DemoMessage.EXCHANGE, DemoMessage.ROUTING_KEY, message);
+ }
+
+}
diff --git a/lab-40/lab-40-rabbitmq/src/main/resources/application.yaml b/lab-40/lab-40-rabbitmq/src/main/resources/application.yaml
new file mode 100644
index 000000000..e7a92f1bf
--- /dev/null
+++ b/lab-40/lab-40-rabbitmq/src/main/resources/application.yaml
@@ -0,0 +1,10 @@
+spring:
+ application:
+ name: demo-application-rabbitmq
+
+ # RabbitMQ 配置项,对应 RabbitProperties 配置类
+ rabbitmq:
+ host: 127.0.0.1 # RabbitMQ 服务的地址
+ port: 5672 # RabbitMQ 服务的端口
+ username: guest # RabbitMQ 服务的账号
+ password: guest # RabbitMQ 服务的密码
diff --git a/lab-40/pom.xml b/lab-40/pom.xml
index 1c22cd344..66f0a911d 100644
--- a/lab-40/pom.xml
+++ b/lab-40/pom.xml
@@ -16,9 +16,14 @@
lab-40-springmvc
lab-40-mysql
lab-40-redis
+ lab-40-mongodb
+ lab-40-elasticsearch
lab-40-kafka
+ lab-40-rabbitmq
+ lab-40-activemq
lab-40-logback
+ lab-40-opentracing