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