activeMQ常见面试题(面试总结)

什么是activeMQ

详细介绍一下MQ

MQ简称消息队列,他是一个不同项目之间进行通讯时,对消息进行管理的组件。有了MQ,可以使项目之间交互由同步转换成异步,解耦了消息的处理过程。把消息统一管理起来,按照顺序,根据客户端的处理能力一个一个的进行操作,MQ具有送达保证、排序保证、峰值处理、异步通信几大特性。在高并发时,对于减轻数据库压力非常有效。MQ一般有点对点和发布订阅两种方式,点对点就是一个消息只允许接收一次,发布订阅模式,一个消息可以被多次接收。目前主流的产品有RabbitMQ、ActiveMQ和Kafka;ActiveMq是Java语言开发的,RabbitMQ是Erlang语言开发的,理论上,RabbitMQ的性能比ActiveMq更强,是非Java系统的首选,ActiveMq是Java的,整套系统如果本来就是Java的,配合的默契更佳。Kafka相当于一个分布式的MQ,传统的MQ,消息被消化掉后会被mq删除,而kafka中消息被消化后不会被删除,而是到配置的expire时间后,才删除,他把写入压力均摊到各个节点。可以通过增加节点降低压力;

activeMQ介绍

ActiveMQ是当前非常流行,能力非常强劲的消息中间件。可以在分布式系统的不同服务之间进行消息的发送和接收;它是Apache的开源产品,支持跨平台跨语言。完美的实现了 JMS java消息规范,我们在项目可以直接使用jms的api来进行开发。

遵循了JMS消息协议,支持多种消息格式(字符串、Map、Object、字节数组、数据流)
包含两个角色(Producer生产者 Consumer消费者), (broker)
包含两种消费模式 队列模式(queue)点对点 主题模式(topic)

[必会]为什么要用activeMQ

可以让系统解耦。异步处理,应对高并发。比如,使用消息中间件,某一个服务,可能依赖了其他好几个服务。比如我们电商项目中,商品的增加和删除都依赖其他项目,如:在我们上架一款商品时 需要依赖搜索引擎更新索引库,同时还需要页面静态化服务生成html页面,如果不用MQ我们代码就会和这两个服务耦合,使用MQ就可以直接通知MQ不和其他服务联系。

[必会]如何使用activeMQ

在项目中,我们使用的是SpringJMS操作activeMQ,已maven操作为例,首先先引用SpringJMS的依赖 及 activeMQ的依赖,然后在spring的配置中,
如果要配置消息的生产者的话,需要配置springjms的连接工厂,通过连接工厂配置 jmsTemplate实例,我们可以使用jmsTemplate进行消息的相关操作,另外我们也需要配置消息的目的地,也是在spring的配置文件中配置配置队列 或者 主题。
消息的消费者和生产者配置差不多,不同的是需要配置一个消息的监听器,监听器里面实现onMessage方法,在这个方法里面处理消息

[必会]activeMQ的消息确认机制

客户端消费消息的风格有两种: 同步和异步 同步是在消费者端调用receive()方法,异步是使用messageListener. 在同一个消费者中只能使用一种风格。

AUTO_ACKNOWLEDGE=1 自动确认(
自动确认的消息 同步方法中receive方法一调用消息就会被确认消费。在异步方法中 是调用完onMessage方法后消息被确认,如果方法抛出异常消息会重发,重发有一定次数,次数过多会进入死信队列。我们通常会使用try catch避免抛出异常)
CLIENT_ACKNOWLEDGE=2 客户端手动确认(客户端手动确认 需要我们在代码中使用acknowledge方法进行确认。)
DUPS_OK_ACKNOWLEDGE=3 自动批量确认
SESSION_TRANSACTED=0 事务提交并确认 (如果session是事务类型,则消息确认机制必须是这个,如果session是非事务的,则不可以是这个消息确认机制) session.commit();
INDIVIDUAL_ACKNOWLEDGE=4 单条消息确认

[熟悉]activeMQ服务器宕机怎么办

这得从ActiveMQ的储存机制说起。在通常的情况下,非持久化消息是存储在内存中的,持久化消息是存储在文件中的,它们的最大限制在配置文件的节点中配置。但是,在非持久化消息堆积到一定程度,内存告急的时候,ActiveMQ会将内存中的非持久化消息写入临时文件中,以腾出内存。虽然都保存到了文件里,但它和持久化消息的区别是,重启后持久化消息会从文件中恢复,非持久化的临时文件会直接删除。
那如果文件增大到达了配置中的最大限制的时候会发生什么?我做了以下实验:消息的监听器会实现一个onMessage方法,在有新消息的是否会被触发。
设置2G左右的持久化文件限制,大量生产持久化消息直到文件达到最大限制,此时生产者阻塞,但消费者可正常连接并消费消息,等消息消费掉一部分,文件删除又腾出空间之后,生产者又可继续发送消息,服务自动恢复正常。
设置2G左右的临时文件限制,大量生产非持久化消息并写入临时文件,在达到最大限制时,生产者阻塞,消费者可正常连接但不能消费消息,或者原本慢速消费的消费者,消费突然停止。整个系统可连接,但是无法提供服务,就这样挂了。
具体原因不详,解决方案:尽量不要用非持久化消息,非要用的话,将临时文件限制尽可能的调大。

[熟悉]activeMQ丢消息怎么办

这得从java的java.net.SocketException异常说起。简单点说就是当网络发送方发送一堆数据,然后调用close关闭连接之后。这些发送的数据都在接收者的缓存里,接收者如果调用read方法仍旧能从缓存中读取这些数据,尽管对方已经关闭了连接。但是当接收者尝试发送数据时,由于此时连接已关闭,所以会发生异常,这个很好理解。不过需要注意的是,当发生SocketException后,原本缓存区中数据也作废了,此时接收者再次调用read方法去读取缓存中的数据,就会报Software caused connection abort: recv failed错误。

通过抓包得知,ActiveMQ会每隔10秒发送一个心跳包,这个心跳包是服务器发送给客户端的,用来判断客户端死没死。如果你看过上面第一条,就会知道非持久化消息堆积到一定程度会写到文件里,这个写的过程会阻塞所有动作,而且会持续20到30秒,并且随着内存的增大而增大。当客户端发完消息调用connection.close()时,会期待服务器对于关闭连接的回答,如果超过15秒没回答就直接调用socket层的close关闭tcp连接了。这时客户端发出的消息其实还在服务器的缓存里等待处理,不过由于服务器心跳包的设置,导致发生了java.net.SocketException异常,把缓存里的数据作废了,没处理的消息全部丢失。

解决方案:用持久化消息,或者非持久化消息及时处理不要堆积,或者启动事务,启动事务后,commit()方法会负责任的等待服务器的返回,也就不会关闭连接导致消息丢失了。

[必会]如何持久化信息

默认的情况下,非持久化的消息是异步发送的,持久化的消息是同步发送的,遇到慢一点的硬盘,发送消息的速度是无法忍受的。但是在开启事务的情况下,消息都是异步发送的,效率会有2个数量级的提升。所以在发送持久化消息时,请务必开启事务模式。其实发送非持久化消息时也建议开启事务,因为根本不会影响性能。
相关录音

[熟悉]持久化消息非常慢如何解决

[熟悉]消息的不均匀消费

有时在发送一些消息之后,开启2个消费者去处理消息。会发现一个消费者处理了所有的消息,另一个消费者根本没收到消息。原因在于ActiveMQ的prefetch机制。当消费者去获取消息时,不会一条一条去获取,而是一次性获取一批,默认是1000条。这些预获取的消息,在还没确认消费之前,在管理控制台还是可以看见这些消息的,但是不会再分配给其他消费者,此时这些消息的状态应该算作“已分配未消费”,如果消息最后被消费,则会在服务器端被删除,如果消费者崩溃,则这些消息会被重新分配给新的消费者。但是如果消费者既不消费确认,又不崩溃,那这些消息就永远躺在消费者的缓存区里无法处理。更通常的情况是,消费这些消息非常耗时,你开了10个消费者去处理,结果发现只有一台机器吭哧吭哧处理,另外9台啥事不干。

解决方案:将prefetch设为1,每次处理1条消息,处理完再去取,这样也慢不了多少。

[熟悉]activeMQ中死信队列

如果你想在消息处理失败后,不被服务器删除,还能被其他消费者处理或重试,可以关闭AUTO_ACKNOWLEDGE,将ack交由程序自己处理。那如果使用了AUTO_ACKNOWLEDGE,消息是什么时候被确认的,还有没有阻止消息确认的方法?有!

消费消息有2种方法,一种是调用consumer.receive()方法,该方法将阻塞直到获得并返回一条消息。这种情况下,消息返回给方法调用者之后就自动被确认了。另一种方法是采用listener回调函数,在有消息到达时,会调用listener接口的onMessage方法。在这种情况下,在onMessage方法执行完毕后,消息才会被确认,此时只要在方法中抛出异常,该消息就不会被确认。那么问题来了,如果一条消息不能被处理,会被退回服务器重新分配,如果只有一个消费者,该消息又会重新被获取,重新抛异常。就算有多个消费者,往往在一个服务器上不能处理的消息,在另外的服务器上依然不能被处理。难道就这么退回–获取–报错死循环了吗?

在重试6次后,ActiveMQ认为这条消息是“有毒”的,将会把消息丢到死信队列里。如果你的消息不见了,去ActiveMQ.DLQ里找找,说不定就躺在那里。

[熟悉]修改重发间隔和重发次数

ActiveMQ:是Apache出品,最流行的,能力强劲的开源消息总线。是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现。JMS(Java消息服务):是一个Java平台中关于面向消息中间件(MOM)的API,用于在两个应用程序之间,或分布式系统中发送消息,进行异步通信。
首先,我们得大概了解下,在哪些情况下,ActiveMQ服务器会将消息重发给消费者,这里为简单起见,假定采用的消息发送模式为队列(即消息发送者和消息接收者)。
① 如果消息接收者在处理完一条消息的处理过程后没有对MOM进行应答,则该消息将由MOM重发.
② 如果我们队某个队列设置了预读参数(consumer.prefetchSize),如果消息接收者在处理第一条消息时(没向MOM发送消息接收确认)就宕机了,则预读数量的所有消息都将被重发!
③ 如果Session是事务的,则只要消息接收者有一条消息没有确认,或发送消息期间MOM或客户端某一方突然宕机了,则该事务范围中的所有消息MOM都将重发。
④ 说到这里,大家可能会有疑问,ActiveMQ消息服务器怎么知道消费者客户端到底是消息正在处理中还没来得急对消息进行应答还是已经处理完成了没有应答或是宕机了根本没机会应答呢?其实在所有的客户端机器上,内存中都运行着一套客户端的ActiveMQ环境,该环境负责缓存发来的消息,负责维持着和ActiveMQ服务器的消息通讯,负责失效转移(fail-over)等,所有的判断和处理都是由这套客户端环境来完成的。
我们可以来对ActiveMQ的重发策略(Redelivery Policy)来进行自定义配置,其中的配置参数主要有以下几个:
可用的属性
属性 默认值 说明
l collisionAvoidanceFactor 默认值0.15 , 设置防止冲突范围的正负百分比,只有启用useCollisionAvoidance参数时才生效。
l maximumRedeliveries 默认值6 , 最大重传次数,达到最大重连次数后抛出异常。为-1时不限制次数,为0时表示不进行重传。
l maximumRedeliveryDelay 默认值-1, 最大传送延迟,只在useExponentialBackOff为true时有效(V5.5),假设首次重连间隔为10ms,倍数为2,那么第二次重连时间间隔为 20ms,第三次重连时间间隔为40ms,当重连时间间隔大的最大重连时间间隔时,以后每次重连时间间隔都为最大重连时间间隔。
l initialRedeliveryDelay 默认值1000L, 初始重发延迟时间
l redeliveryDelay 默认值1000L, 重发延迟时间,当initialRedeliveryDelay=0时生效(v5.4)
l useCollisionAvoidance 默认值false, 启用防止冲突功能,因为消息接收时是可以使用多线程并发处理的,应该是为了重发的安全性,避开所有并发线程都在同一个时间点进行消息接收处理。所有线程在同一个时间点处理时会发生什么问题呢?应该没有问题,只是为了平衡broker处理性能,不会有时很忙,有时很空闲。
l useExponentialBackOff 默认值false, 启用指数倍数递增的方式增加延迟时间。
l backOffMultiplier 默认值5, 重连时间间隔递增倍数,只有值大于1和启用useExponentialBackOff参数时才生效。

[熟悉]在项目中的使用

以前我们做电商项目的时候由于用户的并发量不是太高,而且用dubbo对服务进行监控和管理,没有发现什么问题。后来并发量上来了以后就有反馈回来,说用户在下单后的响应提示有点慢,开始的时候对系统检查没发现什么问题。后来考虑到可能是由于并发量变高导致的模块间的响应变慢了。
所以在最近的一个电商项目中就用到了ActiveMQ,比如购物车模块,购物车有个特点就是,用户在购物车选择相应的商品进行提交订单后,就需要将生成订单的商品从购物车删除,由于我们的系统是分布式的,用户提交订单成功后,我们的购物车系统是不知道的。所以这时候订单系统就要通知我们购物车系统,其实有多种方式可以实现:一种是我们这边开发dubbo一个服务接口,订单提交成功后,订单直接调用我们的服务接口,完成下单后的购物车的删除功能。但是最后发现和订单交互的系统越来越多,比如:下单后还要通知,优惠券,优惠码,积分,库存,完成相应的扣除功能。这样给订单系统去通知的时候就比较麻烦了,增加了系统的压力,而且也需要维护很多地址,最后我们就修改成mq提高了系统的可维护性和可用性,从而提高下单的效率。在扫单系统中过期的订单需要系统取消,取消的时候需要调用优惠券,积分,库存系统进行还资源的过程,可以使用发布订阅。

[熟悉]遇到的问题

消息发送一致性如何保证(分布式事务解决方案)
发送正向流程:

添加商品保存到数据库成功,但是发送消息的时候失败(数据不一致);
解决方案:(本地事务解决)先执行数据库持久的逻辑,然后再执行发送消息,而且将两个步骤放到一个事务中;
正向流程中的异常:
2.(可靠消息解决)咋消息发送完成,但是在要进行投递的过程中,mq挂掉了,因为mq的主题模式默认消息是不会持久的,所以消息就丢失了(数据不一致);
投递正向流程:
出现消息的消费宕机,因为ActiveMQ,发布订阅模式默认消息是不会持久化的,所以消息投递失败就丢失了(数据不一致)
解决方案:对mq的消息进行持久化
投递的异常流程:
当消息的消费者接收到了消息,但是在执行的过程中,出错了(消息被消费,但是在执行中遇到异常)(数据不一致)
解决方案:消息的确认机制(ack)默认消息是自动确认的,只要消息发送出去,就认为会成功消费,在保存的时候我们也会发送一个短信给开发者,便于问题的解决。
分布式事务问题解决方案:不是强一致性,而是最终一致性,从而提高系统的吞吐量。
分布式事物解决的方法:抛出异常
Try{
}cath{
New runtimeException();
}
在try块中捕获到的异常都会抛出到dispatchServlet然后进行回滚

[熟悉]ActiveMQ消息存储持久化

1.AMQ消息存储-基于文件的存储方式,是以前的默认消息存储
2.KahaDB消息存储-提供了容量的提升和恢复能力,是现在的默认存储方式
3.JDBC消息存储-消息基于JDBC存储的
4.Memory消息存储-基于内存的消息存储

[了解]activemq 信息优先级

JMS标准中约定priority可以为0~9的数值,值越大表示权重越高,默认值为4。不过activeMQ中各个存储器对priority的支持并非完全一样。比如JDBC存储器可以支持0-9,因为JDBC存储器可以基于priority对消息进行排序和索引化;但是对于kahadb/levelDB等这种基于日志文件的存储器而言,priority支持相对较弱,只能识别三种优先级(LOW: < 4,NORMAL: =4,HIGH: > 4)。在broker端,默认是不支持priority排序的,我们需要手动开启:

  • 1
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
以下是一些ActiveMQ常见面试题: 1. 什么是ActiveMQ?它的作用是什么? 答:ActiveMQ是一个开源的消息中间件,它的作用是实现异步通信和消息传递,可以用于解耦、异步处理、流量削峰等场景。 2. ActiveMQ的消息模型有哪些?它们的区别是什么? 答:ActiveMQ的消息模型包括点对点(P2P)模型和发布/订阅(Pub/Sub)模型,P2P模型中每个消息只有一个消费者可以消费,而Pub/Sub模型中每个消息可以被多个消费者消费。 3. ActiveMQ的消息传递方式有哪些?它们的区别是什么? 答:ActiveMQ的消息传递方式包括同步传递和异步传递,同步传递是指生产者发送消息后需要等待消费者返回确认消息之后才能继续发送下一个消息,而异步传递则是生产者发送消息后不需要等待消费者的确认消息,可以立即发送下一个消息。 4. ActiveMQ的消息持久化方式有哪些?它们的区别是什么? 答:ActiveMQ的消息持久化方式包括文件(File)持久化和数据库(Database)持久化,文件持久化是将消息保存在本地的文件系统中,而数据库持久化则是将消息保存在数据库中。 5. ActiveMQ的消息监听方式有哪些?它们的区别是什么? 答:ActiveMQ的消息监听方式包括消息驱动(Message-Driven)和轮询(Polling)两种,消息驱动是指在消息到达时立即通知消费者进行处理,而轮询则是在一定时间间隔内不断地检查是否有消息到达。 6. ActiveMQ和RabbitMQ的区别和联系是什么? 答:ActiveMQ和RabbitMQ都是开源的消息中间件,用于解耦、异步处理、流量削峰等场景,但是ActiveMQ相对于RabbitMQ更加灵活和易于使用,支持更多的协议和消息模型,而RabbitMQ则更加成熟和稳定,支持更多的消息传递方式和持久化方式。两者可以根据实际业务需求进行选择和使用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序猫A建仔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值