
在一个典型的jboss eap应用中,web服务通过servlet将消息发送到jms队列,随后一个mdb负责消费并处理这些消息。然而,在实际运行中,可能会出现mdb的onmessage()方法未能被调用的情况,导致消息似乎“丢失”,但服务器日志中并未报告任何错误。这种现象通常是间歇性的,例如约50%的消息未能被预期的mdb处理。
以下是涉及到的基本配置和代码片段:
JBoss JMS 队列配置:
<jms-queue name="HIFWebHookQueue" entries="HifWebHookQueue java:jboss/exported/jms/queue/HifWebHookQueue"/>
Servlet 消息生产者:
@WebServlet(name = "/")
public class MyServlet extends HttpServlet {
@Inject
private JMSContext context;
@Resource(lookup = "java:jboss/exported/jms/queue/HifWebHookQueue")
private Queue queue;
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
JMSProducer producer = context.createProducer();
producer.setDeliveryMode(DeliveryMode.PERSISTENT);
ObjectMessage msg = context.createObjectMessage(evt); // evt 是一个可序列化的 POJO
producer.send(queue, evt);
}
}MDB 消息消费者:
@MessageDriven(name = "WebhookListenerEJB", activationConfig = {
@ActivationConfigProperty(propertyName="messagingType", propertyValue="javax.jms.MessageListener"),
@ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Queue"),
@ActivationConfigProperty(propertyName="destination", propertyValue="java:/jms/queue/HIFWebHookQueue"),
@ActivationConfigProperty(propertyName="ConnectionFactoryName", propertyValue="ConnectionFactory"),
})
@TransactionManagement(value = TransactionManagementType.CONTAINER)
@TransactionAttribute(value = TransactionAttributeType.REQUIRED)
public class WebhookListenerEJB implements MessageListener {
public void onMessage(Message message) {
ObjectMessage msg = (ObjectMessage) message;
// ... 消息处理逻辑 ...
message.acknowledge(); // 如果是 CLIENT_ACKNOWLEDGE 模式,需要手动确认
}
}当遇到此类问题时,第一步是检查JMS队列的运行时状态,以确定消息是否真的滞留在队列中,或者是否已被消费。JBoss CLI提供了强大的工具来实时查看这些指标。
使用以下JBoss CLI命令查询特定JMS队列的运行时资源信息:
/subsystem=messaging-activemq/server=default/jms-queue=HIFWebHookQueue:read-resource(include-runtime=true)
示例输出分析:
{
"outcome" => "success",
"result" => {
"consumer-count" => 30,
"dead-letter-address" => "jms.queue.DLQ",
"delivering-count" => 0,
"durable" => true,
"entries" => [
"HifWebHookQueue",
"java:jboss/exported/jms/queue/HifWebHookQueue"
],
"expiry-address" => "jms.queue.ExpiryQueue",
"legacy-entries" => undefined,
"message-count" => 0L,
"messages-added" => 1L,
"paused" => false,
"queue-address" => "jms.queue.HIFWebHookQueue",
"scheduled-count" => 0L,
"selector" => undefined,
"temporary" => false
}
}关键指标解读:
诊断结论:
从上述输出可以看出,messages-added 为 1 而 message-count 为 0,这明确表明发送到队列的消息已被某个消费者成功接收并处理,而不是滞留在队列中。如果消息未被消费,message-count 应该大于 0。
问题的关键在于 consumer-count。通常,一个MDB的默认并发会话数(即消费者数量)在JBoss EAP中是有限的,例如默认可能为 15。然而,示例中 consumer-count 达到了 30,这远超单个MDB的默认并发数。这强烈暗示存在多于预期的MDB实例或重复的MDB部署正在消费同一个队列。
当 consumer-count 异常高时,最常见的原因是:
在这种情况下,消息并没有“丢失”,而是被其他(可能是不受控制的)MDB实例消费了。因此,您预期的MDB实例可能只是“碰巧”没有接收到消息,因为其他实例抢先处理了。
为了解决这个问题,您需要识别所有连接到该队列的消费者,并消除多余的部署。
步骤一:列出所有消费者
使用以下JBoss CLI命令来获取连接到特定JMS队列的所有消费者的详细信息:
/subsystem=messaging-activemq/server=default/jms-queue=HIFWebHookQueue:list-consumers-as-json
这个命令将返回一个JSON数组,其中包含每个消费者的详细信息,包括其客户端ID、连接ID以及可能关联的应用程序名称或MDB名称。通过分析这些信息,您可以确定哪些MDB实例正在消费队列。
步骤二:识别并移除多余部署
根据 list-consumers-as-json 的输出,您应该能够识别出导致 consumer-count 异常高的那些MDB实例。
例如,如果发现 WebhookListenerEJB.jar 被部署了两次,您需要卸载其中一个。
JBoss EAP中JMS MDB“消息丢失”的现象,往往并非消息真正消失,而是被预期之外的MDB实例消费。通过JBoss CLI工具,特别是 read-resource(include-runtime=true) 和 list-consumers-as-json 命令,可以有效地诊断队列的运行时状态和消费者情况。一旦确认存在多余的MDB部署,及时进行管理和清理,即可解决此类问题,确保消息被正确的MDB实例可靠地处理。
以上就是JBoss EAP 中 JMS MDB 消息丢失问题的诊断与解决的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号