SpringCloud Stream 整合RocketMQ

1.Cloud Stream

概念:

屏蔽底层消息中间件的差异,降低切换版本,统一消息的编程模型

通过定义绑定器Binder作为中间件,实现了应用程序与消息中间件细节之间的隔离

通过向应用程序暴露统一的Channel通道,使得应用程序不需要再考虑各种不同消息中间件实现

遵循发布-订阅模式,通过主题进行广播

一句话就是编码过程中看不到特定的某一个消息中间件代码的身影

标准化MQ:

1.Message 生产者/消费者之间靠消息媒介传递消息内容

2.MessageChannel 消息必须走特定的通道

3.MessageChannel的子接口SubscribableChannel,由MessageHandler消息处理器订阅(消息通道的消息如何被消费,谁负责收发处理)

流程:

Binder:很方便的连接中间件,屏蔽差异

Channel:是队列的一种抽象,在消息通讯系统中就是实现存储和转发的媒介,通过对Channel对队列进行配置

Source和Sink:相当于Stream自身,从Stream发布消息就是输出,接收消息就是输入

2.RocketMQ环境配置

1.下载RocketMQ压缩包

下载地址:

https://dlcdn.apache.org/rocketmq/4.9.4/rocketmq-all-4.9.4-bin-release.zip

这里的下载地址是最新的,我自己用的rocketmq-4.9.2

解压后给rocketmq操作权限

chmod -R 777 rocketmq-4.9.2

启动服务之前要配置一些东西 默认给程序分配的内存太大 跑不起来 要手动分配的小一点

修改bin目录下的runserver.sh和runbroker.sh

runserver.sh中的

71 JAVA_OPT="${JAVA_OPT} -server -Xms256m -Xmx256m -Xmn128m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=128m"

runbroker.sh中的

67 JAVA_OPT="${JAVA_OPT} -server -Xms256m -Xmx256m"

修改conf目录下broker.conf

23 brokerIP1 = xxx.xxx.xxx.xxx(服务器公网地址) //声明broker1 IP地址
24 autoCreateTopicEnable = true //自动创建主题

后台启动rocketmq

所有命令都是先cd进rocketmq后再输的

在这里插入图片描述

还有就是如果是云服务器的话要开放安全组端口为rocketmq服务9876、10911、10909、10912四个

先启动namesrv

nohup sh ./bin/mqnamesrv -n 服务器公网地址:9876 & //后台启动namesrv

可以查看日志,查看日志信息是否启动成功

tail -f /root/logs/rocketmqlogs/namesrv.log

再启动mqbroker

nohup sh ./bin/mqbroker -n 服务器公网地址:9876 -c ./conf/broker.conf & //把broker注册给namesrv 指定配置文件位置
tail -f /root/logs/rocketmqlogs/broker.log

创建主题topic

sh ./bin/mqadmin updateTopic -n 服务器公网地址:9876 -c DefaultCluster -t Test1 //不能重复创建主题

注:以上步骤操作失误,可以杀掉rocketmq重新启动

# 1.关闭NameServer
sh ./bin/mqshutdown namesrv
# 2.关闭Broker
sh ./bin/mqshutdown broker

rocketmq环境配置好之后进入编码环节:

3.整合案例过程

本次使用服务注册中心为nacos

1.创建父工程project

父工程pom

<!--  父工程统一jar包管理 -->
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <junit.version>4.12</junit.version>
    <lombok.version>1.18.10</lombok.version>
    <log4j.version>1.2.17</log4j.version>
    
  </properties>

<!--  子模块继承之后提供作用,锁定版本 + 子module不用写groupId和version-->
  <dependencyManagement>
    
    <dependencies>
      
      <!--spring boot 2.2.2-->
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>2.2.2.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
      
      <!--spring cloud Hoxton.SR1-->
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>Hoxton.SR1</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>

      <!--spring cloud alibaba -->
      <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-alibaba-dependencies</artifactId>
        <version>2.1.0.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>

      <!--junit-->
      <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>${junit.version}</version>
      </dependency>

      <!--log4j-->
      <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>${log4j.version}</version>
      </dependency>
      <!-- lombok -->
      <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>${lombok.version}</version>
      </dependency>
      
    </dependencies>
  </dependencyManagement>
  
  <build>
    <finalName>cloud2020</finalName>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
          <fork>true</fork>
          <addResources>true</addResources>
        </configuration>
      </plugin>
    </plugins>
  </build>

2.创建三个子模块

在这里插入图片描述

分别是消息生产者8801、消息消费者8802、8803

生产者:

建module:cloud-stream-rocketmq-provider8801

改pom

<dependencies>

        <!--   spring-cloud-starter-stream-rocketmq     -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rocketmq</artifactId>
        </dependency>
        
<!--        nacos-discovery -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

yml:

server:
  port: 8801
#rocketmq
spring:
  application:
    name: cloud-stream-provider
  cloud:
    stream:
      bindings:
        output: #生产消息
          destination: Test1
      rocketmq:
        binder:
          name-server: 服务器公网地址:9876
#nacos
    nacos:
      discovery:
        server-addr: localhost:8848 #配置nacos地址

management:
  endpoints:
    web:
      xposure:
        include: '*'

主启动类:

@EnableDiscoveryClient
@SpringBootApplication
public class StreamMQMain8801 {

    public static void main(String[] args) {

        SpringApplication.run(StreamMQMain8801.class,args);
    }
}

业务类:

​ 1.发送消息接口

package com.hz.springcloud.service;

public interface IMessageProvider {
    
    public String send();
}

​ 2.接口实现类

package com.hz.springcloud.service.impl;

import cn.hutool.core.lang.UUID;
import com.hz.springcloud.service.IMessageProvider;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.message.MessageConst;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.messaging.Source;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.support.MessageBuilder;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

@EnableBinding(Source.class)
@Slf4j
public class MessageProviderImpl implements IMessageProvider {

    @Resource
    private MessageChannel output;

    @Override
    public String send() {
        String serial = UUID.randomUUID().toString();
        Map<String,Object> headers = new HashMap<>();
        headers.put(MessageConst.PROPERTY_TAGS,"testTag");
        MessageHeaders messageHeaders = new MessageHeaders(headers);
        Message<String> message = MessageBuilder.createMessage(serial, messageHeaders);
        boolean b = output.send(message);
        if (b){
            log.info(" ----- 消息发送成功: " + serial);
        }else{
            log.info(" ----- 消息发送失败: ");
        }
        return "200 OK";
    }
}

​ 3.controller

package com.hz.springcloud.contrroller;

import com.hz.springcloud.service.IMessageProvider;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;

@RestController
public class SendMessageController {
    
    @Resource
    private IMessageProvider messageProvider;
    
    @GetMapping(value = "/sendMessage")
    public String sendMessage(){
        return messageProvider.send();
    }
}

测试:

1.启动8801项目确认服务已经注册进nacos注册中心

2.访问 http://localhost:8801/sendMessage

3.查看控制台

在这里插入图片描述

消费者:

建module:cloud-stream-rocketmq-consumer8802

改pom

<dependencies>

        <!--   spring-cloud-starter-stream-rocketmq     -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rocketmq</artifactId>
        </dependency>

        <!--        nacos-discovery -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

yml:

server:
  port: 8802
#rocketmq
spring:
  application:
    name: cloud-stream-consumer
  cloud:
    stream:
      bindings:
        input: #消费消息
          destination: Test1
          group: TestGroup
      rocketmq:
        binder:
          name-server: 服务器公网地址:9876
#nacos
    nacos:
      discovery:
        server-addr: localhost:8848 #配置nacos地址

service-url:
  nacos-user-service: http://cloud-stream-provider

主启动类:

@EnableDiscoveryClient
@SpringBootApplication
public class StreamMQMain8802 {

    public static void main(String[] args) {
        SpringApplication.run(StreamMQMain8802.class,args);
    }
}

由于是消费者,所以没有业务类

测试:

1.启动8801,8802项目

2.访问 http://localhost:8801/sendMessage

3.8802接收消息

在这里插入图片描述

再创建消费者子模块

cloud-stream-rocketmq-consumer8803

用来测试消息重复消费以及消息持久化的问题

由于和8802一样,只有yml不同,故只展示yml

server:
  port: 8803
#rocketmq
spring:
  application:
    name: cloud-stream-consumer
  cloud:
    stream:
      bindings:
        input: #消费者
          destination: Test1
          group: TestGroup1 #这里和8802不同 为了展示不同组消息重复消费
      rocketmq:
        binder:
          name-server: 服务器公网地址:9876
#nacos
    nacos:
      discovery:
        server-addr: localhost:8848 #配置nacos地址

service-url:
  nacos-user-service: http://cloud-stream-provider

测试:

发了五条消息8802,8803服务都消费了

在这里插入图片描述

重复消费问题:

如何避免重复消费?

微服务应用放置于同一个group中,就能够保证消息只会被其中一个应用消费一次。(轮询)同一个组内会发生竞争关系,只有其中一个可以消费。避免了重复消费

8802、8803两个服务的group组名都声明成一样的

发了五条消息,8802消费了4条、8803消费了1条,成功避免重复消费消息

持久化:

消息只会在有分组属性的服务上被消费,而没有声明分组的服务不会消费发送的消息

测试:

1.停掉8802、8803两个服务

2.去掉8802服务的group属性,8803group属性还在

3.8801先发送五条消息

4.先启动8802服务,无分组属性配置,后台无打印消费信息,并报错

在这里插入图片描述

5.再启动8803服务,有分组属性配置,后台有打印消息,消息被8803消费(消息持久化)

在这里插入图片描述

总结:

此次整合仅仅是一个小demo,真正的实际开发中这样是远远不够的,还需要结合具体业务操作。还有广播消费、顺序消费、延时消息、过滤消息、事务消息等等…

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Cloud StreamSpring Cloud 生态系统中的一部分,它提供了一种简单且可扩展的方式来构建消息驱动的微服务应用程序。而 RocketMQ 是一款开源的分布式消息中间件,它具有高可靠、高吞吐量、高可扩展性等特点。在 Spring Cloud Stream 中,我们可以通过集成 RocketMQ 来实现消息驱动的微服务应用程序。 下面是 Spring Cloud Stream 集成 RocketMQ 的详细文档: 1. 添加依赖 首先,我们需要添加 Spring Cloud StreamRocketMQ 的相关依赖。在 pom.xml 文件中添加以下依赖: ``` <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-stream</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-stream-binder-rocketmq</artifactId> </dependency> <dependency> <groupId>org.apache.rocketmq</groupId> <artifactId>rocketmq-spring-boot-starter</artifactId> <version>2.2.0</version> </dependency> ``` 2. 配置 RocketMQ 在 application.properties 文件中添加 RocketMQ 的相关配置,例如: ``` spring.cloud.stream.rocketmq.binder.namesrv-addr=127.0.0.1:9876 spring.cloud.stream.rocketmq.binder.group=rocketmq-group rocketmq.name-server=127.0.0.1:9876 rocketmq.producer.group=rocketmq-producer-group rocketmq.consumer.group=rocketmq-consumer-group ``` 3. 定义消息通道 在 Spring Cloud Stream 中,消息是通过消息通道来传递的。我们需要定义输入通道和输出通道,例如: ``` public interface MyChannel { String INPUT = "my_input"; String OUTPUT = "my_output"; @Input(INPUT) SubscribableChannel input(); @Output(OUTPUT) MessageChannel output(); } ``` 4. 发送消息 我们可以通过注入 MessageChannel 来发送消息,例如: ``` @Autowired @Qualifier(MyChannel.OUTPUT) private MessageChannel myOutput; public void sendMessage(String message) { myOutput.send(MessageBuilder.withPayload(message).build()); } ``` 5. 接收消息 我们可以通过注入 SubscribableChannel 来接收消息,例如: ``` @StreamListener(MyChannel.INPUT) public void handleMessage(Message<String> message) { log.info("Received message: {}", message.getPayload()); } ``` 6. 集成 RocketMQ 消费者 我们也可以通过集成 RocketMQ 的消费者来接收消息,例如: ``` @Slf4j @Component @RocketMQMessageListener(consumerGroup = "${rocketmq.consumer.group}", topic = MyChannel.INPUT) public class MyRocketMQConsumer implements RocketMQListener<String> { @Override public void onMessage(String message) { log.info("Received message: {}", message); } } ``` 7. 集成 RocketMQ 生产者 我们也可以通过集成 RocketMQ 的生产者来发送消息,例如: ``` @Slf4j @Component public class MyRocketMQProducer { @Autowired private RocketMQTemplate rocketMQTemplate; public void sendMessage(String message) { rocketMQTemplate.convertAndSend(MyChannel.OUTPUT, message); } } ``` 以上就是 Spring Cloud Stream 集成 RocketMQ 的详细文档。通过这种方式,我们可以快速构建消息驱动的微服务应用程序,并且具有高可靠、高吞吐量、高可扩展性等特点。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值