Springboot整合ActiveMQ流程

ActiveMQ

​ Apache ActiveMQ是Apache软件基金会所研发的开放源代码消息中间件;
由于ActiveMQ是一个纯Java程序,因此只需要操作系统支持Java虚拟机,ActiveMQ便可执行。

优点

​ ActiveMQ 采用消息推送方式,所以最适合的场景是默认消息都可在短时间内被消费。

​ 数据量越大,查找和消费消息就越慢,消息积压程度与消息速度成反比。

缺点

​ 1.吞吐量低。由于ActiveMQ需要建立索引,导致吞吐量下降。这是无法克服的缺点,只要使用完全符合JMS规范的消息中间件,就要接受这个级别的TPS。

​ 2.无分片功能。这是一个功能缺失,JMS并没有规定消息中间件的集群、分片机制。而由于ActiveMQ是为企业级开发设计的消息中间件,初衷并不是为了处理海量消息和高并发请求。如果一台服务器不能承受更多消息,则需要横向拆分。ActiveMQ官方不提供分片机制,需要自己实现

准备工作

首先我们要下载activemq的压缩包,下载地址:http://activemq.apache.org/download.html
直接解压,到bin文件夹中,选择适合自己系统的就好。
在这里插入图片描述
我的是64位,所以我选择win64,双击activemq.bat运行。
在这里插入图片描述
如何查看是否运行成功?
这个日志就告诉你了访问地址。
在这里插入图片描述
浏览器直接访问,输入账号密码admin/admin就好(默认密码),看到这个就代表成功了在这里插入图片描述

接下来看代码

1、我们现在在做点对点模式,稍后会讲到发布订阅模式
创建springboot项目,直接点击next就好。
在这里插入图片描述
2、创建项目名之后,点击next
在这里插入图片描述
3、选择你需要的依赖,这里我们只选activeme 5 就好,然后一直点击next、finsh。
在这里插入图片描述
4、这时候我们已经创建好项目了,然后我们鼠标右键点击项目名,选择new/module,一样的流程创建生产者和消费者a、消费者b,最后我们项目结构是这样的:
在这里插入图片描述
5、我们先写producer消息生产者的代码,先来看下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 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.4.1</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.chenan</groupId>
	<artifactId>producer</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>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-activemq</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-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

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

</project>

6、编写配置文件

// 项目端口号
server.port=8888
// 访问路径
server.servlet.context-path=/pro

// mq服务器的地址
spring.activemq.broker-url=tcp://192.168.15.183:61616
// 账号和密码
spring.activemq.user=admin
spring.activemq.password=admin

// 队列名称
queueName=publish.queue
topicName=publish.topic

7、编写我们自己的配置文件

package com.chenan.producer.configs;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;

import javax.jms.Queue;
import javax.jms.Topic;

@Configuration
public class ActiveMQConfig {

    @Value("${queueName}")
    private String queueName;

    @Value("${topicName}")
    private String topicName;

    @Value("${spring.activemq.user}")
    private String usrName;

    @Value("${spring.activemq.password}")
    private  String password;

    @Value("${spring.activemq.broker-url}")
    private  String brokerUrl;

    //创建消息队列
    @Bean
    public Queue queue(){
        return new ActiveMQQueue(queueName);
    }

    //创建主题
    @Bean
    public Topic topic(){
        return new ActiveMQTopic(topicName);
    }

    // 创建连接
    @Bean
    public ActiveMQConnectionFactory connectionFactory(){
        return new ActiveMQConnectionFactory(usrName, password, brokerUrl);
    }

    //创建消费者监听器
    @Bean
    public JmsListenerContainerFactory<?> jmsListenerContainerQueue(ActiveMQConnectionFactory connectionFactory){
        DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
        bean.setConnectionFactory(connectionFactory);
        return bean;
    }

    //创建订阅者监听器
    @Bean
    public JmsListenerContainerFactory<?> jmsListenerContainerTopic(ActiveMQConnectionFactory connectionFactory){
        DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
        //设置为发布订阅方式, 默认情况下使用的生产消费者方式
        bean.setPubSubDomain(true);
        bean.setConnectionFactory(connectionFactory);
        return bean;
    }
}


8、现在我们来发送信息

package com.chenan.producer.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.jms.Topic;
import java.util.Date;
import java.util.Queue;

@RestController
@RequestMapping("/producer")
public class ProducerController {

    @Autowired
    private JmsMessagingTemplate jms;

    @Autowired
    private Queue queue;

    @Autowired
    private Topic topic;

    /**
     * 发送queue消息
     * @return
     */
    @RequestMapping("/send")
    public String queue(){
        for (int i = 0; i < 10 ; i++){
            // 参数为  :发送信息的队列名称,发送的信息
            jms.convertAndSend("publish.queue", "queue"+i);
        }
        return "queue 发送成功";
    }

    /**
     * queue发送的消息被消费后会发送回执信息
     * @param msg
     */
    @JmsListener(destination = "out.queue")
    public void consumerMsg(String msg){
        System.err.println(msg);
    }

    /**
     * 发布topic
     * @return
     */
    @RequestMapping("/topic")
    public String topic(){

        for (int i = 0; i < 10 ; i++){
            jms.convertAndSend(topic, "topic"+i);
        }
        return "topic 发送成功";
    }
}

9、到这里就生产者就搞定了,有木有很简单?现在的项目结构是什么样子的呢?
在这里插入图片描述

现在我们来运行下试试,访问http://localhost:8888/pro/producer/send 回车
在这里插入图片描述
发送成功了,我们看下activemq服务器是什么样子
在这里插入图片描述
注意标红这一条,我们刚刚发送的队列名称叫做publish.queue,看名称就是这一条,然后看第二列,代表未被消费的信息数,意思是说我们刚刚的消息被推送到服务器上了,成功了。

10、那我们再来看下消费者,pom文件、配置文件、我们自己的配置文件都是一样的,我们就pass了,直接看代码。
创建QueueListener类,这个类主要用来监听一对一模式的消息

package com.chenan.customer_a.listener;

import org.springframework.jms.annotation.JmsListener;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.stereotype.Component;

@Component
public class QueueListener {

    // 监听消息
    @JmsListener(destination = "publish.queue" ,containerFactory = "jmsListenerContainerQueue")
    // 给另外一个队列发送此信息
    @SendTo("out.queue") 
    public String receive(String message){
        System.out.println("QueueListener:consumer-a 收到一条信息:"+message);
        return "consumer-a:"+message;
    }

}

创建TopicListener类,这个类主要用来监听发布订阅模式的消息

package com.chenan.customer_a.listener;

import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

import javax.jms.Destination;

@Component
public class TopicListener {

    @JmsListener(destination = "publish.topic",containerFactory = "jmsListenerContainerTopic")
    public void recive(String text){
        System.out.println("TopicListener: consumer-b 收到一条信息:"+text);
    }

}

代码部分搞定了,我们现在一起来看下消费者a目前的结构:
在这里插入图片描述
我们先访问http://localhost:8888/pro/producer/send,然后看下队列服务器
在这里插入图片描述
我们发现队列中有20条未被消费的消息,那我们现在运行下消费者a:
在这里插入图片描述
可以看到,消费者a服务一旦运行,立刻接收到了20条消息,那现在队列服务器是什么样子呢?
在这里插入图片描述
可以看到,待消费消息变成0了,移除消息变为20了,消息被成功消费了,这时候,一对一模式也就搞定了,那什么是发布订阅呢?

11、我们比对着消费者a服务,再次创建一个消费者b服务,记得,端口号一定要改下,要不然会报错呦。直接运行即可,我们在上边的代码中其实已经实现了发布订阅模式了,浏览器直接访问http://localhost:8888/pro/producer/topic ,我们去查看两个消费者服务控制台
在这里插入图片描述
在这里插入图片描述
两个消费者服务都接收到了消息,大功告成。

总结:

一对一模式消息不被消费会一直存在于队列中,直到被消费为止,但发布订阅模式恰恰相反,消费者不能消费之前未消费到的信息,也就是说我们要运行消费者(订阅者)服务成功之后,生产者服务再产生消息,消费者(订阅者)才能成功消费消息。
好了,今天分享到此结束,本人新手小菜鸟,欢迎各路大神多多指导。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值