持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第9天,点击查看活动详情
写在前面
很多时候,我们在开发的过程中,可能会用到很多消息中间件!!!
例如:kafka、rabbitmq、rocketmq等等
这样,就导致我们不得不去学习对应中间件的api方法。
例如,如何发送消息,如何消费消息,等等
而且,后期想切换消息中间件的时候,你会发现需要去改动我们的业务代码。
这样,对于我们的后期维护,也是一个大的花销。
- 例如: kafka的消息发送和消费是这样的:
@Resource private KafkaTemplate<String, Object> kafkaTemplate;
//发送消息
kafkaTemplate.send("主题topic", "发送的消息message");
//消费消息
@KafkaListener(topics = {"主题topic"})
public void onMessage1(ConsumerRecord<?, ?> consumerRecord) {
Optional<?> optional = Optional.ofNullable(consumerRecord.value());
if (optional.isPresent()) {
Object msg = optional.get();
logger.info("message:{}", msg);
}
}
- 例如:rocketmq的消息发送和消费是这样的:
@Autowired
private RabbitTemplate rabbitTemplate;
//发送消息
rabbitTemplate.convertAndSend("swl.direct","1", "发送的消息");
//消费消息
@RabbitListener(queues = "swl.queue1")
public void doSomeThing(Object object){
System.out.println("收到!"+object.toString());
}
- 例如:rocketmq的消息发送和消费是这样的:
@Autowired
private RocketMQTemplate rocketMQTemplate;
//发送消息
rocketMQTemplate.convertAndSend("主题topic", "发送的消息message");
//消息消息
@Component
@RocketMQMessageListener(topic = "主题topic",consumerGroup = "消息分组group")
public class Consumer implements RocketMQListener<String> {
@Override
public void onMessage(String message) {
System.out.println(message);
}
}
由此可见,
不同的消息中间件,那就需要用不同的api去发送和消费消息。这个springboot整合这些中间件的配置和依赖,这里就不再一 一列举。
面对这样的一些问题,我们应该要做一个整合,对这些api,进行封装,最后统一提供一样的api方式,给开发人员所使用。
开发人员无感知的使用消息中间件的问题,使得微服务开发的高度解耦,服务可以关注更多自己的业务流程!!!
这是我们的一个理想的想法,那目前这样的一个框架,存不存在呢?
这肯定的是有的,毕竟咱们能想到的问题,那些大佬们,老早就已经想到这个问题了。
这个框架,就是Spring Cloud Stream。
Stream说明
那我们来看一下官方文档
从
SpringCloud的官方文档,我们可以看到Stream目前支持了rabbitmq和kafka。
rocketmq的stream支持,是阿里自己实现的。
从源码中我们可以获取到spring cloud stream构建的应用程序与消息中间件之间是通过绑定器Binder相关联的。绑定器对应用程序而言起到了隔离作用。
所以对通信程序而言,它不知道消息中间件的通信细节。
绑定器是spring cloud stream重要的组件,在没有绑定器这个概念的情况下,spring boot 要直接与消息中间件进行信息交互的时候。
由于各消息中间件构建的初衷不同,实现细节会有较大差异,这使得我们消息交互相当笨重。
通过定义绑定器作为中间层,完美实现了解耦。
Stream使用
我们以rocketmq为例。
1.添加依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rocketmq</artifactId>
</dependency>
2.配置name-server地址
# rocketmq nameserver地址
spring.cloud.stream.rocketmq.binder.name-server=127.0.0.1:9876
# 日志输出 logOutput 分组
spring.cloud.stream.bindings.logOutput.destination=log
spring.cloud.stream.bindings.logOutput.group= logout-group
3.代码编写
- 添加LogOutput和LogInput类
/**
* 日志发送消息。
*/
public interface LogOutput {
/**
* MessageModel的消息收发。
*/
String OUTPUT = "logOutput";
@Output(OUTPUT)
MessageChannel logOutput();
}
/**
* 日志接收消息队列。
*/
public interface LogInput {
/**
* MessageModel的消息收发。
*/
String INPUT = "logInput";
@Input(INPUT)
SubscribableChannel logInput();
}
- 启动类添加注解
/**
* springboot启动类添加注解
*/
@EnableFeignInterceptor
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
@EnableBinding({LogOutput.class, LogInput.class})
public class LlsydnApplication {
public static void main(String[] args) {
SpringApplication.run(LlsydnApplication.class, args);
}
}
- 发送消息
/**
* 发送消息
*/
@Autowired
private LogOutput logInputOutput;
@Async
public void send(String msg) {
logInputOutput.logOutput().send(MessageBuilder.withPayload(msg).build());
}
- 消费消息
/**
*消费消息
*/
@StreamListener(LogInput.INPUT)
public void handLog(String msg) {
//消费消息
//处理自己的业务逻辑代码
...
}
上面就是
rocketmq的示例了!!!如果要切换到
kafka,代码层面的东西,基本上是不需要动的。可能要改,就是
Binder绑定器依赖,还有一些配置文件等等。
由上可见,stream统一了消息发送和消息消费的api,大大方便了开发人员的开发工作!!!
那,这么好用的东西,赶紧用起来吧!!!
好了,今天就先到这里了,溜了溜了溜了!!!^_^
觉得有收获的,帮忙点赞、评论、收藏一下呗!!!