当前位置: 首页 > news >正文

Spring 与 ActiveMQ 的深度集成实践(三)

五、实战案例分析

5.1 案例背景与需求

假设我们正在开发一个电商系统,其中订单模块和库存模块是两个独立的子系统 。当用户下单后,订单模块需要通知库存模块进行库存扣减操作 。在传统的同步调用方式下,订单模块需要等待库存模块完成扣减操作后才能返回响应给用户,这不仅会导致订单处理的响应时间变长,而且当库存模块出现故障时,订单模块也会受到影响,导致整个系统的可用性降低 。

为了解决这些问题,我们决定使用 Spring 与 ActiveMQ 的集成来实现订单模块和库存模块之间的异步通信 。具体需求如下:

  • 订单模块在用户下单成功后,将订单信息发送到 ActiveMQ 的消息队列中 。
  • 库存模块从消息队列中接收订单信息,并进行库存扣减操作 。
  • 确保消息的可靠传输,避免消息丢失 。
  • 实现消息的事务处理,保证订单信息的发送和库存扣减操作要么全部成功,要么全部失败 。

5.2 实现过程与代码展示

  1. 配置文件:在application.properties文件中添加 ActiveMQ 的连接配置:
 

spring.activemq.broker-url=tcp://localhost:61616

spring.activemq.user=admin

spring.activemq.password=admin

spring.activemq.in-memory=false

spring.activemq.pool.enabled=false

  1. 自定义配置类:创建ActiveMQConfig.java配置类,配置连接工厂、JmsTemplate和消息监听器容器工厂:
 

import org.apache.activemq.ActiveMQConnectionFactory;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.jms.annotation.EnableJms;

import org.springframework.jms.config.DefaultJmsListenerContainerFactory;

import org.springframework.jms.core.JmsTemplate;

import javax.jms.ConnectionFactory;

@Configuration

@EnableJms

public class ActiveMQConfig {

@Bean

public ConnectionFactory connectionFactory() {

ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory();

connectionFactory.setBrokerURL("tcp://localhost:61616");

connectionFactory.setUserName("admin");

connectionFactory.setPassword("admin");

return connectionFactory;

}

@Bean

public JmsTemplate jmsTemplate(ConnectionFactory connectionFactory) {

JmsTemplate jmsTemplate = new JmsTemplate();

jmsTemplate.setConnectionFactory(connectionFactory);

jmsTemplate.setDeliveryPersistent(true);

return jmsTemplate;

}

@Bean

public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(ConnectionFactory connectionFactory) {

DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();

factory.setConnectionFactory(connectionFactory);

factory.setConcurrency("1-10");

factory.setSessionAcknowledgeMode(1);

return factory;

}

}

  1. 订单模块(消息生产者):创建OrderService.java类,模拟订单下单操作,并发送订单消息:
 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.jms.core.JmsTemplate;

import org.springframework.stereotype.Service;

import javax.jms.Queue;

@Service

public class OrderService {

@Autowired

private JmsTemplate jmsTemplate;

@Autowired

private Queue orderQueue;

public void placeOrder(String orderInfo) {

// 模拟订单下单的其他业务逻辑

System.out.println("订单下单成功,订单信息: " + orderInfo);

// 发送订单消息到ActiveMQ队列

jmsTemplate.convertAndSend(orderQueue, orderInfo);

System.out.println("订单消息已发送: " + orderInfo);

}

}

  1. 库存模块(消息消费者):创建StockService.java类,监听订单消息队列,并进行库存扣减操作:
 

import org.springframework.jms.annotation.JmsListener;

import org.springframework.stereotype.Service;

@Service

public class StockService {

@JmsListener(destination = "orderQueue")

public void handleOrder(String orderInfo) {

System.out.println("接收到订单消息: " + orderInfo);

// 模拟库存扣减的业务逻辑

System.out.println("库存扣减操作完成,订单信息: " + orderInfo);

}

}

5.3 运行结果与分析

运行电商系统,当用户下单后,订单模块会输出:

 

订单下单成功,订单信息: 订单编号1001,商品ID: 2001,数量: 5

订单消息已发送: 订单编号1001,商品ID: 2001,数量: 5

库存模块会输出:

 

接收到订单消息: 订单编号1001,商品ID: 2001,数量: 5

库存扣减操作完成,订单信息: 订单编号1001,商品ID: 2001,数量: 5

从运行结果可以看出,订单模块成功将订单消息发送到 ActiveMQ 队列,库存模块也成功从队列中接收到消息并进行了相应的处理,符合我们的预期 。

可能出现的问题及解决方法:

  • 消息丢失:如果在消息发送或接收过程中出现异常,可能会导致消息丢失 。可以通过配置消息的持久化(如在jmsTemplate中设置setDeliveryPersistent(true))和事务处理(如配置JmsTransactionManager)来保证消息的可靠性 。
  • 消费者处理消息失败:如果库存扣减操作失败,可能会导致数据不一致 。可以在消费者中添加事务处理,并在处理失败时进行回滚操作,同时可以设置消息的重试机制,如在jmsListenerContainerFactory中设置setRecoveryCallback来处理消息处理失败的情况 。

六、常见问题与解决方案

6.1 集成过程中的错误排查

在 Spring 与 ActiveMQ 的集成过程中,可能会遇到各种各样的错误,以下是一些常见错误及排查解决方法:

  • 依赖冲突:在引入 Spring 和 ActiveMQ 的相关依赖时,可能会因为版本不兼容或重复引入导致依赖冲突 。例如,同时引入了不同版本的 Spring-JMS 或 ActiveMQ 的核心依赖,可能会导致类冲突,出现如ClassNotFoundException或NoSuchMethodError等异常 。排查时,可以使用 Maven 的dependency:tree命令查看依赖树,找出冲突的依赖 。解决方法是在pom.xml文件中使用<exclusions>标签排除不需要的依赖,或者调整依赖的版本,确保所有依赖之间的兼容性 。比如,如果发现spring-jms依赖的版本冲突,可以通过以下方式排除冲突的依赖:
 

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-activemq</artifactId>

<exclusions>

<exclusion>

<groupId>org.springframework</groupId>

<artifactId>spring-jms</artifactId>

</exclusion>

</exclusions>

</dependency>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-jms</artifactId>

<version>5.3.10</version>

</dependency>

  • 配置错误:配置文件中的错误是导致集成失败的常见原因 。例如,在application.properties或application.yml文件中,ActiveMQ 的连接配置错误,如spring.activemq.broker-url填写错误,可能会导致无法连接到 ActiveMQ 服务器,出现JMSException: Could not connect to broker URL: tcp://wrongUrl:61616这样的异常 。排查时,仔细检查配置文件中的各项配置,确保 ActiveMQ 的连接地址、用户名、密码等信息准确无误 。还可以通过在配置文件中添加spring.activemq.show - config=true来打印详细的配置信息,以便进行对比和排查 。如果发现配置错误,及时修改配置文件并重启应用程序 。
  • 消息监听器未正确注册:在使用@JmsListener注解创建消息消费者时,如果消息监听器未正确注册,可能会导致无法接收到消息 。这可能是因为配置类中JmsListenerContainerFactory的配置有误,或者@EnableJms注解未正确添加 。排查时,检查配置类中JmsListenerContainerFactory的配置是否正确,如连接工厂、并发消费者数量、消息确认模式等设置是否符合需求 。确保在主应用类或配置类上添加了@EnableJms注解,以启用 JMS 功能 。例如,如果发现消息监听器未正确注册,可以检查ActiveMQConfig.java配置类中的jmsListenerContainerFactory方法,确保其配置正确:
 

@Bean

public DefaultJmsListenerContainerFactory jmsListenerContainerFactory(ConnectionFactory connectionFactory) {

DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();

factory.setConnectionFactory(connectionFactory);

factory.setConcurrency("1-10");

factory.setSessionAcknowledgeMode(1);

return factory;

}

6.2 性能优化建议

为了提高 Spring 与 ActiveMQ 集成的性能,可以从以下几个方面进行优化:

  • 连接池配置:合理配置 ActiveMQ 的连接池可以显著提高系统的性能和资源利用率 。在 Spring Boot 中,可以通过在application.properties或application.yml文件中配置连接池相关参数来启用连接池 。例如:
 

spring.activemq.pool.enabled=true

spring.activemq.pool.max - connections=10

spring.activemq.pool.idle - timeout=30000

spring.activemq.pool.enabled设置为true表示启用连接池;spring.activemq.pool.max - connections设置连接池的最大连接数为 10,根据系统的并发需求合理调整该值,避免连接过多导致资源浪费或连接不足导致性能瓶颈 ;spring.activemq.pool.idle - timeout设置空闲连接的过期时间为 30000 毫秒,即如果一个连接在 30 秒内处于空闲状态,将会被关闭,以释放资源 。还可以根据实际情况配置其他连接池参数,如spring.activemq.pool.blockIfFull(连接池满时是否阻塞)、spring.activemq.pool.blockIfFullTimeout(阻塞等待的超时时间)等 。

  • 消息持久化策略:消息持久化可以保证在 ActiveMQ 服务器重启或故障时消息不丢失,但同时也会对性能产生一定的影响 。在生产环境中,需要根据业务需求合理选择消息持久化策略 。如果对消息的可靠性要求极高,如金融交易系统中的订单消息,应选择持久化策略,将消息存储到磁盘上 。可以在JmsTemplate中设置setDeliveryPersistent(true)来实现消息的持久化 。但如果对消息的实时性要求较高,且允许在服务器故障时丢失少量消息,如一些实时监控数据的消息,可以选择非持久化策略,将消息存储在内存中,以提高消息的发送和接收速度 。在选择持久化策略时,还可以考虑使用数据库作为持久化存储,如 MySQL、Oracle 等,通过配置jdbcPersistenceAdapter来实现 。
  • 网络优化:网络延迟和带宽限制可能会影响消息的传输速度和系统的性能 。可以通过优化网络配置来提高性能 。确保 ActiveMQ 服务器和应用程序所在的服务器之间的网络连接稳定,减少网络延迟 。可以使用高速网络设备,如千兆网卡、高性能交换机等,提高网络带宽 。合理设置消息的发送和接收超时时间,避免因网络问题导致消息发送或接收失败 。在JmsTemplate中,可以通过setReceiveTimeout和setSendTimeout方法设置接收和发送消息的超时时间,例如:
 

jmsTemplate.setReceiveTimeout(5000);

jmsTemplate.setSendTimeout(3000);

这里将接收超时时间设置为 5000 毫秒,发送超时时间设置为 3000 毫秒,根据实际的网络情况和业务需求进行调整 。

http://www.xdnf.cn/news/185491.html

相关文章:

  • ARP协议(地址解析协议)
  • Unreal Niagara制作Scratch随模型发射粒子特效
  • Make学习二:makefile组成要素
  • 基于STM32、HAL库的ADS1115模数转换器ADC驱动程序设计
  • 驱动开发硬核特训 · Day 22(上篇): 电源管理体系完整梳理:I2C、Regulator、PMIC与Power-Domain框架
  • ByeCode,AI无代码开发平台,拖拽式操作构建应用
  • OpenFeign 自定义拦截器
  • 基于javaweb的SpringBoot在线电子书小说阅读系统设计与实现(源码+文档+部署讲解)
  • Java详解LeetCode 热题 100(02):LeetCode 49. 字母异位词分组(Group Anagrams)详解
  • 一、接口测试01
  • 基于Python Flask的深度学习电影评论情感分析可视化系统(2.0升级版,附源码)
  • 简单的 shell 程序
  • 德州仪器(TI)—TDA4VM芯片详解—目录
  • 十七、系统可靠性分析与设计
  • Vue3 + OpenLayers 开发教程 (六)WebGL渲染优化
  • 【Nova UI】十二、打造组件库之按钮组件(上):迈向功能构建的关键一步
  • Linux系统类型及常用操作命令总结
  • Linux一个系统程序——进度条
  • QT中的事件及其属性
  • 大学之大:伦敦政治经济学院2025.4.27
  • onnexruntime u2net sharp 实现开源图片处理软件
  • vue 打包设置
  • DFPatternFunctor遍历计算图
  • 【博客系统】博客系统第一弹:博客系统项目配置、MyBatis-Plus 实现 Mapper 接口、处理项目公共模块:统一返回结果、统一异常处理
  • 关于华为高斯数据库出现Invalid or unsupported by client SCRAM mechanisms定位解决的过程
  • -信息革命-
  • OpenManus云端部署及经典案例应用
  • 心磁图技术突破传统局限!心血管疾病早筛迈入“三零“新时代
  • TV launcher官方下载-tv launcher汉化版-tv桌面启动器极简下载
  • c++17 对于临时对象作为右值的优化