springboot整合ActiveMQ

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

(1).异步处理

(2).应用解耦

(3).流量削峰

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

1.介绍ActiveMQ

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

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

2.两种模式的示例

2.1点对点模式

        1.pom文件



    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        2.1.6.RELEASE
         
    
    com.carson
    activemq-producer
    0.0.1-SNAPSHOT
    activemq-producer
    Demo project for Spring Boot

    
        1.8
    

    
        
            org.springframework.boot
            spring-boot-starter-web
        

        
            org.springframework.boot
            spring-boot-starter
        

        
            org.springframework.boot
            spring-boot-starter-activemq
        

        
            org.messaginghub
            pooled-jms
        

        
            org.springframework.boot
            spring-boot-starter-test
            test
            
                
                    org.junit.vintage
                    junit-vintage-engine
                
            
        
        
            org.springframework
            spring-web
            5.2.0.RELEASE
        
        
            org.springframework.boot
            spring-boot-test
            2.2.0.RELEASE
            test
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

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


            org.springframework.boot
            spring-boot-starter-activemq
        

        
            org.messaginghub
            pooled-jms
        

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可以用于多个系统监听一个消息的场景。

 

你可能感兴趣的:(中间件)