Spring Cloud Bus
Spring Cloud Bus
通常使用轻量级的消息代理来构建一个公用的消息主题,让系统中所有的微服务实例都连接上来,由于该主题中产生的消息会被所有的实例监听和消费,所以称它为消息总线;
结合RabbitMQ
RabbitMQ前置知识
使用
- 新建spring boot工程 ,命名为rabbitmq-hello
- pom引入依赖 spring-boot-starter-amqp
- 配置rabbitmq的连接信息
- 使用参考demo
原理
指定刷新范围
- 通过向服务实例请求Spring Cloud Bus的/bus/refresh接口,从而实现总线上其他服务实例的/refresh
- 如果要刷新某个具体实例的配置:/bus/refresh接口提供了一个destination参数来指定要刷新的应用程序(/bus/refresh?destination=customers:9000)
架构优化
- Config Server引入Spring Cloud Bus 将配置服务端加入到消息总线中来;
- /bus/refresh请求不再发送到具体服务实例上,而是发送给Config Server 并通过destination参数来指定要更新配置的服务或实例;
kafka实现消息总线
kafka知识
Spring Cloud Stream
使用(rabbitmq)
- 创建一个基础的Spring Boot 工程,命名为stream-hello
- 添加依赖spring-cloud-starter-stream-rabbit
- 创建用于接收来自RabbitMQ消息的消费者SinkReceiver
@EnableBinding(value = {SinkSender.class})
public class SinkReceiver {
private static Logger logger = LoggerFactory.getLogger(DemoApplication.class);
/**
* 消息通道的消费者
* @param payload
*/
@StreamListener(Sink.INPUT)
public void receive(Object payload){
logger.info("received: " + payload);
}
}
- @EnableBinding 该注解用来指定一个或多个定义了@Input或Output注解的接口,以此实现对消息通道(Channel)的绑定;
public interface Sink {
String INPUT = "input";
@Input("input")
SubscribableChannel input();
}
- @StreamListener 主要定义在方法上,作用是将被修饰的方法注册为消息中间件上数据流的事件监听器,注解中的属性值对于了监听的消息通道名;
- 配置通道的主题
spring.cloud.stream.bindings.input.destination=output
spring.cloud.stream.bindings.output.destination=input
- 如果在同一个主题上的应用需要启动多个实例的时候,我们可以通过spring.cloud.stream.bindings.input.group属性为应用指定一个组名,这样这个应用的多个实例在接收到消息的时候,只会有一个成员真正收到消息并进行处理;
- 没有为应用指定消费组的时候,Spring Cloud Stream 会为其分配一个独立的匿名消费组。如果同一主题下的所有应用都没有指定消费组的时候,当有消息发布之后,所有的应用都会对其进行消费,因为它们属于一个独立的组。所以最好为其指定一个消费组。
- 消息分区:当生产者将消息数据发送给多个消费者实例时,保证拥有共同特征的消息数据始终是由同一个消费者实例接收和处理;
- @Input和@Output定义消息通道, 注入绑定接口,如上述代码所示;
- @StreamListener与@ServiceActivator(Spring Intergation的注解)相比,第一个注解功能更加强大,后者没有转换功能,不能将JSON或XML专成对象等;
- 消息反馈 :很多时候在处理完消息之后,需要反馈一个消息给对方,这时可通过@SendTo注解来指定返回内容的输出通道;
@EnableScheduling
@EnableBinding(value = {Processor.class})
public class App1 {
private static Logger logger = LoggerFactory.getLogger(App1.class);
//@StreamListener(Processor.INPUT)
//@SendTo(Processor.OUTPUT)
@ServiceActivator(inputChannel = Processor.INPUT,outputChannel = Processor.OUTPUT)
public Object receiveFromInput(Object payLoad){
logger.info("APP1接收到消息-"+ payLoad);
return "返回-"+payLoad;
}
}
@EnableBinding(value = {Processor.class})
public class App2 {
private static final Logger logger = Logger.getLogger("Process");
@Bean
@InboundChannelAdapter(value = Processor.OUTPUT,poller = @Poller(fixedDelay = "2000"))
public MessageSource<Date> timerMessageSource(){
return ()->new GenericMessage<>(new Date());
}
@StreamListener(Processor.INPUT)
public void receiveFromOut(Object payload){
logger.info("APP2接收:"+payload);
}
}
- 响应式编程可使用RxJava,即引入spring-cloud-straeam-rxjava
- 消费组与消费分区
#消费组
spring.cloud.stream.bindings.input.group=
#消费主题
spring.cloud.stream.bindings.input.destination=output
#开启分区
spring.cloud.stream.bindings.input.consumer.partitioned=true
#指定消费者的总实例数
spring.cloud.stream.instance-count=1
#当前实例的索引号
spring.cloud.stream.instance-index=1
#生产者也可以进行一些配置等
#生产者主题
spring.cloud.stream.bindings.output.destination=input
#生产者 分区键
spring.cloud.stream.bindings.output.producer.partition-key-expression=
#指定消息分区的数量
spring.cloud.stream.bindings.output.producer.partition-count=
- 绑定器SPI :涵盖了一套可插拔的用于连接外部中间件的实现机制 ,最为关键的是Binder接口,一个典型的Binder绑定器实现
- 一个实现Binder接口的类’;
- 一个Spring配置加载类,用于创建连接消息中间件的基础结构使用的实例;
- 一个或多个能够在classpath下的META-INF/sping.binders路径下找到的绑定器定义文件,该文件一般存储了当前绑定器使用的自动化配置类的路径;
- 绑定器自动化配置
- spring-cloud-stream-binder-rabbit
- spring-cloud-stream-binder-kafka
- 多绑定器配置
Spring Cloud Sleuth
初始化
- 引入Spring-cloud-starter-sleuth组件
- 默认参数(A1,A2,A3,A4)
- A1: 应用的名称(Spring.application.name);
- A2:TreceID(用来标识一条请求链路,一条请求链路包含一个TraceID,多个SpanID);
- A3:SpanID(表示一个基本的工作单元,比如发送一个http请求);
- false , 表四是否将该信息输出到Zipkin等服务中来收集和展示;
原理
- 分布式系统的入口,服务跟踪框架为请求创建一个唯一的跟踪标识(TreceID);
- 当请求到达各个组件时,或是处理逻辑到达某个状态时,也通过唯一标识来标记它的开始,具体过程和结果(SpanID);
抽样收集
默认10% 收集 :spring.sleuth.sampler.percentage=0.1
抽样收集整合
- logstash
- zipkin
- http
- 消息中间件