僵尸连接检测
本节将讨论连接生存时间(TTL)并解释Artemis如何处理客户端崩溃和已经退出但是未完全关闭资源的客户端。没有队列的TTL(即当队列多长时间后没有被使用,如没有消费者,则队列会被删除,Artemis的TTL只有消息和连接的TTL概念)。default-purge-on-no-consumers定义也只是这个队列没有消费者后立即清除队列,无法定义队列没有消费者保留多长时间后才进行删除。
1.清理服务端资源
当客户端程序代码漏洞或者客户端崩溃时,会导致服务端资源无法清理。如果发生这种境况,可以将服务器端资源(如会话)挂在服务器上。如果没有删除它们会导致服务器资源泄漏,并且长时间之后导致服务器内存或者其他资源耗尽。
我们需要平衡清理僵尸客户端与客户端和服务端之间网络失败导致重连的实际情况。Artemis支持客户端重连,因此不希望过早的清理僵尸资源,否则会造成客户端无法重新在服务器上找到其旧的会话。Atemis通过连接TTL实现这些功能。TTL确定在服务端没有接受到客户端的任何数据时连接允许保存的多长时间。正常的客户端将定期发送ping数据包以防止服务器关闭它。
连接TTL在URI上使用connectionTtl进行配置。在“不可靠”连接(例如,使用tcp URL方案的Netty连接)上的TTL默认值为60000ms。在“可靠”(例如,使用vm URL方案的in-vm)连接上的TTL的默认值是-1,表示服务器上连接永远不会超时。
如果不希望客户端自己定义自己的connectionTtl,可以通过在服务器端配置connection-ttl-override属性作为全局值使用。默认值为-1表示不覆盖(即客户端使用自己值)。
服务器会定期检查违规的TTL,默认情况下每2000ms检查一次,可以设置connection-ttl-check-interval的值来修改检查间隔。
2.客户端检测失败
我们讨论了客户端如何将ping发送到服务器以及服务器如何清除“死”连接资源。 ping还有另一个原因,那就是客户端能够检测到服务器或网络出现故障。只要客户端从服务器接收数据,它就会认为连接仍然存在。
如果客户端在可配置的毫秒数内没有收到任何数据包,那么它将认为连接失败并将启动故障转移,或者调用任何FailureListener实例(如果使用JMS,则调用ExceptionListener实例),具体取决于它的配置方式。
这可以通过在客户端用于连接的URI上设置clientFailureCheckPeriod参数来控制其检测周期,例如
tcp://localhost:61616?clientFailureCheckPeriod=30000。
“不可靠”连接(例如,Netty连接)上的客户端故障检查周期的默认值是30000ms,即30秒。 “可靠”连接(例如,in-vm连接)上的客户端故障检查周期的默认值为-1。值-1表示即使没有从服务器接收数据,客户端将永远不会连接失败。通常,此值比连接TTL低得多,以允许客户端在发生暂时故障时重新连接。
3.配置异步连接执行
服务器端接收的大多数数据包都在远程处理线程上执行。 这些短时间运行的数据包,出于性能原因总是在远程执行线程上执行。
但是,默认情况下,某些类型的数据包是使用线程池中的线程执行的,因此远程处理线程不会被绑定太长时间。 请注意,在另一个线程上异步处理操作会增加一些延迟。 这些数据包为:
- org.apache.activemq.artemis.core.protocol.core.impl.wireformat.RollbackMessage
- org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionCloseMessage
- org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionCommitMessage
- org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionXACommitMessage
- org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionXAPrepareMessage
- org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionXARollbackMessage
要禁用异步连接执行,在broker.xml中的async-connection-execution-enabled配置设置为false(默认值为true)。
检测慢消费者
拥有服务端队列的慢消费者(如,JMS topic订阅者)可能对代理性能造成严重影响。如果消息在消费者的服务端队列中积累,内存将会被填满并且代理能进入分页模式,会对性能产生负面影响。可以通过设置条件,可以将不能足够快的确认消息的消费者与代理的连接断开,在非持久化JMS订阅者情况下运行代理删除订阅和其所有消息来释放宝贵的服务器资源。
默认情况下服务器不会检测慢消费者,用于确定消费者是否为慢消费者的估算仅检测消费者已经确认的消息数量。它不考虑是否已在消费者上启用了流量控制,消费者是否正在流式传输大型消息,在配置慢消费检测时需要注意。
Artemis使用调度线程池执行慢消费者检测,并且启用了慢消费者检测的代理上每个队列都会在java.util.concurrent.ScheduledThreadPoolExecutor实例内部产生新的检测条目。如果存在大量的队列并且slow-consumer-check-period值较低,则执行某些检查可能会有延迟。但是,这不会影响检测算法使用的计算的准确性。
代理异常检测
在生产环境中可能会出现一些问题,bug无论多少次的验证它还是经常出现。我们总是试图修护,但是在软件开发过程中它总是一值在。
IO异常,可能会导致磁盘和硬件损坏;内存问题,可能导致另一个进程的CPU使用率超级疯狂。
为了防止类似情况发生,我们为代理加了一项保护措施,以便在坏事发生的时候自行关闭进程。会在如下地方进行定期测量其响应:
- 队列投递(添加消息到队列中)
- 日志存储
- 分页操作
如果响应时间超出配置的超时时间,代理会被视为不稳定,将执行关闭代理或者暂停VM。
可以通过使用在broker.xml中的如下配置来进行监督分析:
- critical-analyzer 启用或禁用鉴定分析,默认为true。
- critical-analyzer-timeout 鉴定分析的超时时间,默认值为120000ms。
- critical-analyzer-check-period 鉴定分析的时间间隔,默认值为critical-analyzer-timeout的一半。
- critical-analyzer-policy 服务器在故障时日志记录、暂停或者关闭,默认为LOG(关闭)。
critical-analyzer-policy默认值为LOG,当生成的broker.xml被设置成HALT。因为如果将Artemis嵌入到应用程序服务器或多租户环境中,我们无法暂停VM。如果以其它任何方式处理,默认值为LOG。
如果配置为HALT,则服务器将暂停。
如果使用SHUTDOWN,系统将停止。 注意:如果系统运行不良,则无法保证停止工作。
注:此系列文章为Apache Artemis V2.6.2官方使用文档的简要翻译文档(非完全按照官方文档排版进行翻译,有删减),个人能力有限如有错误请谅解。源文档地址:http://activemq.apache.org/artemis/docs/latest/index.html