使用Spring Cloud Alibaba创建springcloud项目-5.Spring Cloud Stream & RabbitMQ

Spring Cloud Stream是一个构建消息驱动微服务的框架。它支持RabbitMQ和Kafka。这里使用RabbitMQ.

官网:https://spring.io/projects/spring-cloud-stream#overview
中文网站:https://m.wang1314.com/doc/webapp/topic/20971999.html

我们要在项目中使用RabbitMQ,首先要有一个完整的RabbitMQ环境,首先搭建一些RabbitMQ环境。
RabbitMQ环境搭建: https://www.cnblogs.com/JustinLau/p/11738511.html,写的很详细。按照这篇文章一步一步配置应该是没问题的。

搭建完成后,访问http://localhost:15672/,如果能看到以下页面就表明搭建成功了。
使用Spring Cloud Alibaba创建springcloud项目-5.Spring Cloud Stream & RabbitMQ_第1张图片

接下来我们开始撸代码,创建服务rabbitMQProvider9004

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloudstudy</artifactId>
        <groupId>com.study</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>rabbitMQProvider9004</artifactId>


    <dependencies>

        <!-- Spring Cloud Stream RabbitMQ-->

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>

        <!--  SpringCloud alibaba nacos    -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--  web组件      -->
        <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.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>


</project>

创建application.yml

server:
  port: 9004
spring:
  application:
    name: stream-rabbitmq-provider   #本服务的名称
  cloud:                           #注册到nacos
    nacos:
      discovery:
        server-addr: localhost:8848
    stream:
      binders:  #需要绑定的rabbitmq的服务信息
        defaultRabbit: #定义的名称,用于binding整合
          type: rabbit #消息组件类型
          environment: #环境配置
            spring:
              rabbitmq:
                host: localhost
                port: 5672
                username: guest
                password: guest
      bindings: # 服务的整合处理
        output: # 名字是一个通道的名称
          destination: studyExchange # 表示要使用的Exchange名称定义
          content-type: application/json # 设置消息类型,本次为json
          binder: defaultRabbit #设置要绑定的消息服务的具体设置

management:
  endpoints:
    web:
      exposure:
        include: "*"

创建启动类RabbitMQProviderMain9004

@SpringBootApplication
@EnableDiscoveryClient
public class RabbitMQProviderMain9004 {
     
    public static void main(String[] args) {
     
        SpringApplication.run(RabbitMQProviderMain9004.class,args);
    }
}

创建一个service包创建ProviderMessage接口

public interface ProviderMessage {
     

    public void send();
}

在service包下创建impl包创建ProviderMessageImpl类实现ProviderMessage接口

@EnableBinding(Source.class)  //定义消息的推送广告
public class ProviderMessageImpl implements ProviderMessage {
     

    @Resource
    private MessageChannel output; //消息发送管道

    @Override
    public void send() {
     
        String uuid = UUID.randomUUID().toString();
        output.send(MessageBuilder.withPayload(uuid).build());
        System.out.println("9004发送消息: " +uuid);
    }
}

创建controller包MessageController类

@RestController
public class MessageController {
     

    @Resource
    ProviderMessage providerMessage;

    @GetMapping(value = "/message/send")
    public String send(){
     
        providerMessage.send();
        return "发送成功!";
    }
}

现在创建消息消费服务rabbitMQConsumer9005

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloudstudy</artifactId>
        <groupId>com.study</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>rabbitMQConsumer9005</artifactId>

    <dependencies>

        <!-- Spring Cloud Stream RabbitMQ-->

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>

        <!--  SpringCloud alibaba nacos    -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--  web组件      -->
        <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.hmy.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>


</project>

application.yml(和9004有不同,注意一下)

server:
  port: 9005
spring:
  application:
    name: stream-rabbitmq-consumer   #本服务的名称
  cloud:                           #注册到nacos
    nacos:
      discovery:
        server-addr: localhost:8848
    stream:
      binders:  #需要绑定的rabbitmq的服务信息
        defaultRabbit: #定义的名称,用于binding整合
          type: rabbit #消息组件类型
          environment: #环境配置
            spring:
              rabbitmq:
                host: localhost
                port: 5672
                username: guest
                password: guest
      bindings: # 服务的整合处理
        input: # 名字是一个通道的名称   注意这里和生产消息不同
          destination: studyExchange # 表示要使用的Exchange名称定义
          content-type: application/json # 设置消息类型,本次为json
          binder: defaultRabbit #设置要绑定的消息服务的具体设置

management:
  endpoints:
    web:
      exposure:
        include: "*"

主启动类RabbitConsumer9005

@SpringBootApplication
@EnableDiscoveryClient
public class RabbitConsumer9005 {
     

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

创建ConsumerController

@Component
@EnableBinding(Sink.class)
public class ConsumerController {
     

    @Value("${server.port}")
    private String serverPort;

    @StreamListener(Sink.INPUT)
    public void input(Message<String> message){
     
        System.out.println("9005收到消息:"+message.getPayload()+"\t port:"+serverPort);
    }
}

依次启动9004,9005,访问localhost:9004/message/send,打开idea控制台

使用Spring Cloud Alibaba创建springcloud项目-5.Spring Cloud Stream & RabbitMQ_第2张图片
使用Spring Cloud Alibaba创建springcloud项目-5.Spring Cloud Stream & RabbitMQ_第3张图片

消息重复消费和持久化

我们思考两个问题,1、我们在做集群服务的时候,如果接收消息的服务有两个,此时消息服务器发了一个消息,会被两个服务都消费。例如,订单服务发送了一条消息,两个库存服务都消费了这个消息,都对库存进行-1操作,这就出了问题。2、消息服务发了消息,但是消费服务由于一些原因停止了服务,当它再次启动的时候,无法接收到消息了。

对于以上两个问题解决办法很简单,分组就完事了。

创建服务rabbitMQConsumer9006,除了把端口号改成9006,其他与9005一样。启动9004,9005,9006

访问localhost:9004/message/send
打开控制台,查看9004,9005,9006的控制台输出

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

两个服务都收到了消息,现在我们来解决这个问题,修改9005和9006的application.yml文件

使用Spring Cloud Alibaba创建springcloud项目-5.Spring Cloud Stream & RabbitMQ_第4张图片

两个服务添加一样的分组名。启动服务,发送消息,会发现9005和9006会轮询接收消息,这样就可以避免消息重复消费。

现在关闭9005和9006,关闭服务后,9004发送消息,把9006的分组属性去掉,再次启动9005和9006
在这里插入图片描述
在这里插入图片描述

此时会发现,9005启动后收到了消息,9006没有收到。

使用Spring Cloud Alibaba创建springcloud项目-6.Sentinel

你可能感兴趣的:(java,spring,rabbitmq,spring,boot)