【发布时间】:2016-12-08 21:20:00
【问题描述】:
我们在项目中广泛使用 Spring Batch 和分区作业。有时,我们会看到分区作业因丢失消息而“挂起”的问题。远程分区全部完成,但父步骤仍处于已启动状态。我们的配置使用 1 个连接工厂从队列(入站网关)读取消息,并使用不同的集群连接发送分区消息(出站网关)。原因是 JBoss 消息传递不会在集群周围统一分发消息,而客户端连接工厂提供了该功能。
Redhat 进来,坦率地向 Spring 和配置扔了泥巴。以下是他们报告的摘录
Spring JMSTemplate 代码采用了几种反模式,例如创建新连接、会话、生产者只是为了发送消息,然后关闭连接。此外,当接收到消息时,它每次都可以创建一个消费者, 接收消息,然后关闭消费者。这可能会导致负载下的性能不佳。使用反模式不仅会导致性能下降,还会耗尽操作系统资源,例如 线程和文件句柄,因为一些连接资源是异步释放的。此外,对于非持久主题订阅者,您最终可能会丢失消息,因为在关闭之间收到的任何消息 最后一个和下一个消费者的打开将丢失。在使用 JCA 托管连接工厂(通常位于“java:/JmsXA”)的应用程序服务器中,有一个地方可以接受使用 Spring JMSTemplate,并且仅在您发送消息时才有效。 JCA 管理的连接工厂缓存连接,因此它们实际上不会每次都被创建。但是,使用 JCA 托管连接工厂并不能解决消费者的问题,因为它们没有被缓存。 总之,Spring JMSTemplate 使用起来并不安全,除了在应用程序服务器内部使用 JCA 托管连接工厂 (java:/JmsXA) 并仅在这种情况下发送消息的非常具体的用例 (不要用它来消费消息)。 从应用程序服务器外部的 JMS 客户端应用程序使用它永远不会安全,并且将它与标准连接工厂(例如“ConnectionFactory”、“ClusteredConnectionFactory”、“jms/RemoteConnectionFactory”等)一起使用是安全的 永远不安全;也用它来接收消息是不安全的。为了使用 Spring 安全地接收消息,请考虑将 MessageListenerContainers [7] 与 MessageDriven Pojos [8] 一起使用。 最后,请注意遇到的问题基于 JMS 反模式,因此不是 JBoss EAP 特有的问题。例如,参见关于 ActiveMQ [9] 的类似讨论。 Red Hat 不支持将 Spring JMSTemplate 与 JBoss Messaging 一起使用,除了一种可接受的通过 JCA 托管连接工厂发送消息的用例。
建议
● 对于 Spring JMS,通常使用 JBoss EAP 中配置的 JCA 托管连接工厂。不要使用 Spring 配置的连接工厂。使用 JNDI 模板将连接工厂从 JBoss 拉入 Spring。这将摆脱大部分 Spring JMS 问题。 ● 批处理作业使用标准JMS 而不是Spring JMS。 Spring 是非标准的(并且可能是 JMS 的次标准实现)。标准 JMS 使用由几个发送者组成的池来发送消息并在发送消息后关闭会话。在侦听器方面,标准 JMS 使用一个工作池来侦听分布式队列或主题。每个 Web 服务器都将 JMS 侦听器部署为单例,并使用标准 Java 观察器 通知任何期待回电的呼叫者。
JMS 连接工厂在 JBoss 中配置并通过 JNDI 加载。
您能否就他们的评估提供反馈?
【问题讨论】:
标签: spring-integration spring-batch-admin