最近在做一个内部应用的时候,应用到了ActiveMQ作为服务之间消息传递,解耦服务之间的关联,但是在应用的过程中遇到了连接断线无法重连的问题,下面基于这个问题,深入了解一下ActiveMQ的一些相关原理和知识。
一、前置知识
1.1 基础概念
ActiveMQ中有3个重要的角色:Broker、Producer、Consumer。
Broker为消息代理,它是ActiveMQ服务端角色,接收客户端的链接并提供消息通信的核心服务。
Producer是消息生产者,客户端角色
Consumer是消息消费者,客户端角色。
要保证Producer和Consumer正常通信,主要是通过Broker来实现的,Broker既代理了Producer同时也代理了Consumer,这样Broker才能知道哪些是生产者,哪些是消费者,不至于不同的消息被本不属于它的消费者给消费了。Broker内部的机制我们下一节学习。
那么生产者和消费者如何实现通信的呢?ActiveMQ定义的连接器(connector)就是用来约定ActiveMQ的节点之间如何通信的。
1.2 连接器
ActiveMQ通过网络连接器这种连接机制来实现客户端与服务端之间的通信。ActiveMQ提供了两种连接器:
- 传输连接器(transport connector):用于客户端和服务端之间( client-to-broker)的通信。
- 网络连接器(network connector):用户集群中多个服务端之间(broker-to-broker)的通信。
1.3 传输连接器包括的协议
- tcp,默认使用的协议,符合大多数的使用场景。
- udp,客户端使用udp协议和服务端通信,当客户端和服务端之间存在防火墙可以考虑使用udp协议。
- vm,当客户端和服务端在同一个JVM中可以考虑使用。直接使用虚拟机本地方法调用,从而避免网络通信的开销。
- nio,本质上还是tcp,只是使用了java NIO包,某些场景下可能性能更好。
- ssl,基于tcp提供安全的通信。
- http/https,允许客户端使用REST或Ajax的方式进行连接,可以通过JS给ActiveMQ发送消息。
- multicast,客户端使用组播的方式连接到服务端。
- websocket,可以通过HTML5中的websocket技术连接服务端。
- amqp,高级消息队列协议,很多消息中间件都支持该协议。ActiveMQ5.8版本开始支持。
- mqtt,MQTT是一个基于客户端-服务器的消息发布/订阅传输协议,主要应用在loT(物联网)。
- stomp,STOMP是在WebSocket之上提供了一个基于帧的线路格式(frame-based wire format)层,用来定义消息的语义,就像HTTP在TCP套接字之上添加了请求-响应模型层一样。ActiveMQ5.6版本开始支持
二、ActiveMQ断线发生的场景
ActiveMQ的客户端与ActiveMQ的Broker(消息代理)之间的网络连接发生断开,如果未采用高可用的配置,那么Producer无法向MQ中生产对象,同理Customer也无法消费MQ中的消息,整个业务就会出现暂停。
默认的情况下如果ActiveMQ服务正常,那么所有Client服务启动,都会自动在Broker中进行注册,这样就能实现消息生产和消费。但是如果Client服务正常,ActiveMQ服务宕机了进行重启或当网络不稳定或出现故障导致连接断开时,ActiveMQ是不会主动实现Client与Broker进行重连的,此时所有服务都正常,由于连接未建立,所以整个业务也无法实现消息的生产和消费。
三、ActiveMQ断线重连的实现原理
ActiveMQ的断线重连机制的实现原理主要是基于网络通信和消息重试机制。当ActiveMQ的客户端与Broker之间的连接断开时,客户端会检测到这个事件,并尝试重新建立连接。,ActiveMQ的客户端会检测到连接中断事件,然后触发一个重连机制。客户端会尝试重新连接到一个或多个Broker的URL。在默认情况下,如果连接断开,客户端会新起一个线程,不断的从url参数中获取一个url来重试连接。这种重试机制通常会进行一定的次数限制,以避免无限制的重试导致资源浪费或其他问题。
另外,在重连过程中,ActiveMQ的客户端还会尝试恢复之前未发送成功的消息。这个过程主要是通过持久化消息存储来实现的。在连接断开时,客户端会将未发送成功的消息存储到持久化存储中,如数据库或文件系统等。当客户端成功连接到Broker后,会从持久化存储中恢复这些消息,并进行重新发送。
四、ActiveMQ断线重连的配置
ActiveMQ提供了客户端和服务器端通信高可用的配置,
failover,为客户端提供重连服务端的逻辑,允许配置多个上面介绍的不同协议的连接配置,并随机的从其中选择一个进行连接,如果失败则继续选择其他服务重试。failover的配置格式:failover:(tcp://ip1:61616,tcp://ip2:61616)?initialReconnectDelay=100。
fanout,采用复制的方式将消息发送给多个服务端,配置格式为:fanout:(tcp://localhost:61629,udp://localhost:61639,tcp://localhost:61649)
4.1 failover
failover是一种ActiveMQ提供的失效转移(也叫故障转移)的策略。其原理是如果服务先连接到tcp://ip1:61616这个消息队列,如果因为网络抖动或其他意外情况导致ip1无法连接,failover会自动切换到ip2:61616这个消息队列,实现了消息高可用,如果ip1的网路正常了,failover又会尝试连接回来。但是这与断线重连有什么关系呢?
经过我的验证,如果只配置了一个ActiveMQ,如:failover:(tcp://ip1:61616)?initialReconnectDelay=100 当ip1上的ActiveMQ出现了问题,此时failover无法进行故障转移,他就会在initialReconnectDelay定义的100毫秒后进行ip1的重连,从而导致Client与ip1的Broker重新建立链接,实现了断线重连的功能。
4.2 fanout
采用复制的方式将消息发送给多个服务端,这里面虽然没有断线重连,但是实现了消息发送的高可用,这里面需要注意一点,如果Customer在没有很好的处理消息的情况下,有可能Productor生产了一个消息,发送给多个消息队列,Customer消费了多次消息,导致数据重复,所以需要注意Customer消息消费逻辑的幂等性。

本文详细介绍了ActiveMQ在服务间消息传递中遇到的连接断线问题,涉及其工作原理、连接器类型、断线场景、重连机制、配置选项(如failover和fanout),以及优化策略,帮助读者理解和解决实际应用中的问题。
最低0.47元/天 解锁文章
5万+

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



