目前随着微服务以及分布式的发展,消息中间件的作用越来越大了。消息中间件可以起到系统之间解耦的作用,比如用户进行购买商品,有加入购物车操作,还有下单操作以及支付操作等。在微服务的情况下,这些将是不同的服务,有可能部署在不同的容器中,因此,这个购买操作存在各个系统之间的调用关系。其中支付之后会有支付信息,以及物流等信息反馈给用户。但是如果在一个串行调用的系统中则是非常不合理的。对于用户来说支付信息和物流信息等延迟几秒基本是无感的。因此,这里会使用消息中间件,这里支付系统会生产一个支付结果的消息,然后结果反馈(短信、应用程序通知)系统和物流系统则会订阅这个消息。支付系统支付完成之后则会处理下一个订单,不在关心该订单的后续情况,结果反馈系统和物流系统则会监听到这个支付结果,并进行该订单的后续处理。从上可以看出,消息中间件解耦了支付系统和结果反馈系统以及物流系统。常见的消息中间件有: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可以用于多个系统监听一个消息的场景。
本文探讨了在微服务架构中ActiveMQ的应用,通过实例展示了如何整合Spring Boot,实现消息的点对点与发布订阅模式,阐述了ActiveMQ在解耦、异步处理和流量削峰中的关键作用。
4004

被折叠的 条评论
为什么被折叠?



