rocketmq的stream绑定器整合和使用

861 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第9天,点击查看活动详情

写在前面

很多时候,我们在开发的过程中,可能会用到很多消息中间件!!!

例如:kafkarabbitmqrocketmq等等

这样,就导致我们不得不去学习对应中间件的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说明

那我们来看一下官方文档

1654157367.png

SpringCloud的官方文档,我们可以看到Stream目前支持了rabbitmqkafka

rocketmqstream支持,是阿里自己实现的。

从源码中我们可以获取到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,大大方便了开发人员的开发工作!!!

那,这么好用的东西,赶紧用起来吧!!!

好了,今天就先到这里了,溜了溜了溜了!!!^_^

觉得有收获的,帮忙点赞、评论、收藏一下呗!!!

image.png