springboot整合ActiveMQ

本文探讨了在微服务架构中ActiveMQ的应用,通过实例展示了如何整合Spring Boot,实现消息的点对点与发布订阅模式,阐述了ActiveMQ在解耦、异步处理和流量削峰中的关键作用。

        目前随着微服务以及分布式的发展,消息中间件的作用越来越大了。消息中间件可以起到系统之间解耦的作用,比如用户进行购买商品,有加入购物车操作,还有下单操作以及支付操作等。在微服务的情况下,这些将是不同的服务,有可能部署在不同的容器中,因此,这个购买操作存在各个系统之间的调用关系。其中支付之后会有支付信息,以及物流等信息反馈给用户。但是如果在一个串行调用的系统中则是非常不合理的。对于用户来说支付信息和物流信息等延迟几秒基本是无感的。因此,这里会使用消息中间件,这里支付系统会生产一个支付结果的消息,然后结果反馈(短信、应用程序通知)系统和物流系统则会订阅这个消息。支付系统支付完成之后则会处理下一个订单,不在关心该订单的后续情况,结果反馈系统和物流系统则会监听到这个支付结果,并进行该订单的后续处理。从上可以看出,消息中间件解耦了支付系统和结果反馈系统以及物流系统。常见的消息中间件有:kafka、ActiveMQ、RabbitMQ。消息中间件主要有以下特点:

(1).异步处理

(2).应用解耦

(3).流量削峰

         本文通过介绍Springboot整合ActiveMQ的项目示例来介绍消息中间件的作用,以及ActiveMQ的特性。

1.介绍ActiveMQ

         ActiveMQ中消息的两种角色:消息生产者和消息消费者。简而言之,消息生产者负责发送消息,而消息消费者则会处理消息。 

        ActiveMQ具有两种模式:点对点模式(Queue)和发布订阅模式(Topic)。其中点对点模式是指某一条产生的消息只能被一个消息消费者消费,即消息与消费者是一对一的关系。而发布订阅模式则有一个Topic,可以被所有监听它的消费者消费。

2.两种模式的示例

2.1点对点模式

        1.pom文件

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.carson</groupId>
    <artifactId>activemq-producer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>activemq-producer</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-activemq</artifactId>
        </dependency>

        <dependency>
            <groupId>org.messaginghub</groupId>
            <artifactId>pooled-jms</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-test</artifactId>
            <version>2.2.0.RELEASE</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

springboot整合activemq的依赖如下所示(springboot版本为2.1及其以上)

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-activemq</artifactId>
        </dependency>

        <dependency>
            <groupId>org.messaginghub</groupId>
            <artifactId>pooled-jms</artifactId>
        </dependency>

2.设置一个常量类,Constant

public class Constant {

    public static final String QUEUEMESSAGE="queue";

    public static final String TOPICMESSAGE="topic";

}

3.消息生产类Producer

@RestController
public class Producer {


    @Autowired
    private JmsMessagingTemplate jmsMessageingTemplate;

    @Autowired
    private Queue queue;

    @Autowired
    private Topic topic;

    @RequestMapping("/sendMessage/{msg}")
    public void sendMessage(@PathVariable("msg") String msg){
        this.jmsMessageingTemplate.convertAndSend(queue,msg);
    }

    @RequestMapping("/sendMessage1/{msg}")
    public void sendMessage1(@PathVariable("msg") String msg){
        this.jmsMessageingTemplate.convertAndSend(topic,msg);
    }
}

其中sendMessage方法是用于验证点对点的形式,sendMessage1用于验证topic的形式。

4.消息消费者Consumer、Consumer1

@Component
public class Consumer {

    @JmsListener(destination= Constant.QUEUEMESSAGE)
    public void receiveQueue(String message) throws JMSException {
        if(null!=message){
            System.out.println("我是消费者一号,接收到的queue是:"+message);
        }else{
            System.out.print("我是消费者一号,我接收到空queue");
        }
    }

    @JmsListener(destination= Constant.TOPICMESSAGE)
    public void receiveQueue1(String message) throws JMSException {
        if(null!=message){
            System.out.println("我是消费者一号,接收到的topic是:"+message);
        }else{
            System.out.print("我是消费者一号,我接收到空topic");
        }
    }
}

@Component
public class Consumer1 {

    @JmsListener(destination= Constant.QUEUEMESSAGE)
    public void receiveQueue(String message) throws JMSException {
        if(null!=message){
            System.out.println("我是消费者二号,接收到的queue是:"+message);
        }else{
            System.out.print("我是消费者二号,我接收到空queue");
        }
    }

    @JmsListener(destination= Constant.TOPICMESSAGE)
    public void receiveQueue1(String message) throws JMSException {
        if(null!=message){
            System.out.println("我是消费者二号,接收到的topic是:"+message);
        }else{
            System.out.print("我是消费者二号,我接收到空topic");
        }
    }
}


@Component注解表示该类作为组件注入到容器中。

5.application.properties

server.port=8089
spring.activemq.broker-url=tcp://127.0.0.1:61616


# 在考虑结束之前等待的时间
#spring.activemq.close-timeout=15s
# 默认代理URL是否应该在内存中。如果指定了显式代理,则忽略此值。
spring.activemq.in-memory=true 
# 是否在回滚回滚消息之前停止消息传递。这意味着当启用此命令时,消息顺序不会被保留。
spring.activemq.non-blocking-redelivery=false
# 等待消息发送响应的时间。设置为0等待永远。
#spring.activemq.send-timeout=1
#默认情况下activemq提供的是queue模式,若要使用topic模式需要配置下面配置
#账号
spring.activemq.user=admin
# 密码
spring.activemq.password=admin

6.启动类

@SpringBootApplication
public class ActivemqApplication {

    @Bean
    public Queue queue(){
        return new ActiveMQQueue(Constant.QUEUEMESSAGE);
    }

    @Bean
    public Topic topic(){
        return new ActiveMQTopic(Constant.TOPICMESSAGE);
    }

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

}

 queue()、topic()方法分别表示注册点对点的queue和topic。

7.启动项目

结果如下:

我是消费者一号,接收到的queue是:12345

说明queue模式生产的消息只会对应一个消费者。

 

2.2发布订阅模式

server.port=8089
spring.activemq.broker-url=tcp://127.0.0.1:61616


# 在考虑结束之前等待的时间
#spring.activemq.close-timeout=15s
# 默认代理URL是否应该在内存中。如果指定了显式代理,则忽略此值。
spring.activemq.in-memory=true 
# 是否在回滚回滚消息之前停止消息传递。这意味着当启用此命令时,消息顺序不会被保留。
spring.activemq.non-blocking-redelivery=false
# 等待消息发送响应的时间。设置为0等待永远。
#spring.activemq.send-timeout=1
#默认情况下activemq提供的是queue模式,若要使用topic模式需要配置下面配置
spring.jms.pub-sub-domain=true
#账号
spring.activemq.user=admin
# 密码
spring.activemq.password=admin

发布订阅模式只需要在原有基础上将application.properties修改为如上所示,

spring.jms.pub-sub-domain=true表示开启了topic模式。

启动项目,并用postman调用http://127.0.0.1:8089/sendMessage1/123,结果如下:

我是消费者一号,接收到的topic是:123
我是消费者二号,接收到的topic是:123

运行结果说明,两个消费者都消费topic。 说明topic模式表示一个消费对应所有的消费者。

 

2.3总结

以上说明了activemq的queue和topic两种模式,其中queue模式可以适用于秒杀项目,topic可以用于多个系统监听一个消息的场景。

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值