springcloud系列学习笔记目录参见博主专栏 spring boot 2.X/spring cloud Greenwich。
由于是一系列文章,所以后面的文章可能会使用到前面文章的项目。文章所有代码都已上传GitHub:https://github.com/liubenlong/springcloudGreenwichDemo
本系列环境:Java11;springboot 2.1.1.RELEASE;springcloud Greenwich.RELEASE;MySQL 8.0.5;
上一篇文章中spring cloud Greenwich 学习笔记(十)spring cloud sleuth 服务链路追踪介绍了spring cloud sleuth与zipkin的简单使用。不过是通过http请求来访问zipkin的。这样存在一个问题:如果zipkin服务宕机了,或者网络出现问题,那么这段时间内的信息就会丢失。
这里我们引入rabbitmq,追踪信息通过rabbitmq进行中转。
注意,目前网上大多数相关文章都是老版本的springcloud与zipkin的集成,很多配置都失效了。本文采用最新的
spring cloud Greenwich
版本。
现有网上配置一般都是使用spring-cloud-sleuth-zipkin-stream
。在新版本的springcloud中已经废弃,具体请参考官方文档的介绍 https://cloud.spring.io/spring-cloud-sleuth/single/spring-cloud-sleuth.html#_sleuth_with_zipkin_over_rabbitmq_or_kafka :
上面意思就是说spring-cloud-sleuth-stream
已经废弃,如果我们想在sleuth中使用rabbitmq,需要添加spring-cloud-starter-zipkin
和spring-rabbit
的依赖。
官方文档才是最好的学习资料。
spring cloud Greenwich
版本正确配置本文我们还是使用zipkin官方提供的jar包的方式启动zipkin服务。不过需要使用RabbitMQ。在启动的时候需要指定rabbitmq的连接信息(我这里没有指定端口,会使用默认的端口5672,读者可以自行设置端口):
java -jar zipkin-server-2.10.1-exec.jar --zipkin.collector.rabbitmq.addresses=localhost --zipkin.collector.rabbitmq.username=lbl --zipkin.collector.rabbitmq.password=123456
由于我们使用了rabbitmq进行通信,那么zipkin的两个客户端springcloud-eureka-serviceprovider
和springcloud-eureka-serviceconsumer-feign
都要添加rabbitmq的依赖:
<dependency>
<groupId>org.springframework.amqpgroupId>
<artifactId>spring-rabbitartifactId>
dependency>
并且两个项目的配置文件中添加rabbitmq
的配置和zipkin信息的请发送方式。完整的配置如下:
server:
port: 8086
# 服务与服务之间相互调用一般都是根据这个name 。
spring:
application:
name: springcloud-eureka-serviceconsumer-feign
zipkin:
# base-url: http://localhost:9411 #http方式提交到zipkin
sender:
type: rabbit # 切换到rabbitmq
sleuth:
sampler:
#应采样的请求的概率。 例如。 应该对1.0 - 100%的请求进行抽样。 精度仅为整数(即不支持0.1%的迹线)。
probability: 1.0
rabbitmq:
host: localhost
port: 5672
username: lbl
password: 123456
listener: # 这里配置了重试策略
direct:
retry:
enabled: true
simple:
retry:
enabled: true
eureka:
client:
serviceUrl:
# 指定服务注册中心的地址
defaultZone: http://localhost:8080/eureka/
#上面是eureka单机注册中心。下面是eureka集群模式
# defaultZone: http://admin:123456@eureka2:8001/eureka/,http://admin:123456@eureka3:8002/eureka/,http://admin:123456@eureka2:8003/eureka/
#启用hystrix
feign:
hystrix:
enabled: true
至此,项目改造完成,前面已经将zipkin的服务启动,接下来依次启动springcloud-eureka-server
,springcloud-eureka-serviceprovider
,springcloud-eureka-serviceconsumer-feign
。
服务全部启动成功后,访问http://127.0.0.1:8086/?name=abcxz
接口。打开zipkin的管理页面http://localhost:9411/zipkin/
:
将zipkin服务关闭,然后再调用几次http://127.0.0.1:8086/?name=allpxasz
,去rabbitmq控制台可以查看到队列中有几条消息,说明确实是走的rabbitmq通道:
在项目启动过程中,可能会遇到Error creating bean with name 'rabbitListenerContainerFactory'
这个异常。完整错误如下:
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2019-02-22 20:24:16.831 ERROR [springcloud-eureka-serviceconsumer-feign,,,] 20088 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'rabbitListenerContainerFactory' defined in class path resource [org/springframework/boot/autoconfigure/amqp/RabbitAnnotationDrivenConfiguration.class]: Initialization of bean failed; nested exception is java.lang.NullPointerException
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:584) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:846) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:863) ~[spring-context-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546) ~[spring-context-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142) ~[spring-boot-2.1.1.RELEASE.jar:2.1.1.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775) ~[spring-boot-2.1.1.RELEASE.jar:2.1.1.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.1.1.RELEASE.jar:2.1.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:316) ~[spring-boot-2.1.1.RELEASE.jar:2.1.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260) ~[spring-boot-2.1.1.RELEASE.jar:2.1.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248) ~[spring-boot-2.1.1.RELEASE.jar:2.1.1.RELEASE]
at com.example.Application.main(Application.java:15) ~[classes/:na]
Caused by: java.lang.NullPointerException: null
at org.springframework.amqp.rabbit.config.AbstractRabbitListenerContainerFactory.getAdviceChain(AbstractRabbitListenerContainerFactory.java:198) ~[spring-rabbit-2.1.2.RELEASE.jar:2.1.2.RELEASE]
at brave.spring.rabbit.SpringRabbitTracing.decorateSimpleRabbitListenerContainerFactory(SpringRabbitTracing.java:170) ~[brave-instrumentation-spring-rabbit-5.6.1.jar:na]
at org.springframework.cloud.sleuth.instrument.messaging.SleuthRabbitBeanPostProcessor.postProcessBeforeInitialization(TraceMessagingAutoConfiguration.java:180) ~[spring-cloud-sleuth-core-2.1.0.RELEASE.jar:2.1.0.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:419) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1737) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:576) ~[spring-beans-5.1.3.RELEASE.jar:5.1.3.RELEASE]
... 15 common frames omitted
解决方案
上述问题的解决办法参考自:https://stackoverflow.com/questions/53765439/error-creating-bean-with-name-rabbitlistenercontainerfactory
意思也就是说,spring amqp 中存在一个BUG,将在2.1.3版本中解决。而我们目前使用的是2.1.2.RELEASE
版本的spring amqp。
临时解决方案是采用重试策略:
spring.rabbitmq.listener.direct.retry.enabled=true
spring.rabbitmq.listener.simple.retry.enabled=true
具体BUG描述请见官网jira: https://jira.spring.io/browse/AMQP-846
不知道是不是网略的问题,我没有打开这个地址。
使用kafka与使用rabbitmq基本类似,只是需要修改一下配置即可spring.zipkin.sender.type: kafka
。
TODO
springcloud系列学习笔记目录参见博主专栏 spring boot 2.X/spring cloud Greenwich。
由于是一系列文章,所以后面的文章可能会使用到前面文章的项目。文章所有代码都已上传GitHub:https://github.com/liubenlong/springcloudGreenwichDemo
本系列环境:Java11;springboot 2.1.1.RELEASE;springcloud Greenwich.RELEASE;MySQL 8.0.5;