简体   繁体   English

建立JMS连接时如何捕捉?

[英]How to catch when JMS connection is established?

I have message producers that are sending JMS messages about some events using ActiveMQ . 我有消息生产者正在使用ActiveMQ发送有关某些事件的JMS消息。 However, connection to ActiveMQ might not be up all the time. 但是,与ActiveMQ的连接可能并非一直都处于打开状态。 Thus, events are stored and when connection is established they are suppose to be read and sent over. 因此,将存储事件,并在建立连接时假定它们已被读取并发送。 Here is my code: 这是我的代码:

private void sendAndSave(MyEvent event) {
    boolean sent = sendMessage(event);
    event.setProcessed(sent);
    boolean saved = repository.saveEvent(event);
    if (!sent && !saved) {
        logger.error("Change event lost for Id = {}", event.getId());
    }
}

private boolean sendMessage(MyEvent event) {
    try {
        messenger.publishEvent(event);
        return true;
    } catch (JmsException ex) {
        return false;
    }
}

I'd like to create some kind of ApplicationEventListener that will be invoked when connection is established and process unsent events. 我想创建某种ApplicationEventListener ,当建立连接并处理未发送的事件时将调用它。 I went through JMS, Spring framework and ActiveMQ documentation but couldn't find any clues how to hook up my listener with ConnectionFactory. 我浏览了JMS,Spring框架和ActiveMQ文档,但找不到任何线索来连接ConnectionFactory的监听器。

If someone can help me out, I'll appreciate it greatly. 如果有人可以帮助我,我将不胜感激。

Here is what my app Spring context says about JMS: 这是我的应用程序Spring上下文对JMS的评价:

<!-- Connection factory to the ActiveMQ broker instance.              -->
<!-- The URI and credentials must match the values in activemq.xml    -->
<!-- These credentials are shared by ALL producers.                   -->
<bean id="jmsTransportListener" class="com.rhd.ams.service.common.JmsTransportListener" 
      init-method="init" destroy-method="cleanup"/>
<bean id="amqJmsConnectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
    <property name="brokerURL" value="${jms.publisher.broker.url}"/>
    <property name="userName" value="${jms.publisher.username}"/>
    <property name="password" value="${jms.publisher.password}"/>
    <property name="transportListener" ref="jmsTransportListener"/>
</bean>

<!-- JmsTemplate, by default, will create a new connection, session, producer for         -->
<!-- each message sent, then close them all down again. This is very inefficient!         -->
<!-- PooledConnectionFactory will pool the JMS resources. It can't be used with consumers.-->
<bean id="pooledAmqJmsConnectionFactory" class="org.apache.activemq.pool.PooledConnectionFactory" destroy-method="stop">
    <property name="connectionFactory" ref="amqJmsConnectionFactory" />
</bean>

<!-- Although JmsTemplate instance is unique for each message, it is  -->
<!-- thread-safe and therefore can be injected into referenced obj's. -->
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
    <constructor-arg ref="pooledAmqJmsConnectionFactory"/>
</bean>

The way you describe the issue, it sure sounds like an open-and-shut case of JMS Durable Subscriptions. 您描述问题的方式肯定听起来像是JMS持久订阅的一开即关案例。 You might want to consider a more traditional implementation before going down this road. 您可能想在走这条路之前考虑一个更传统的实现。 Caveats aside, ActiveMQ provides Advisory Messages which you can listen for and which will be sent for various events including new connections. 除了警告之外,ActiveMQ还提供咨询消息 ,您可以听取这些消息 ,并将针对各种事件(包括新连接)发送该消息

========= =========

Shoot, sorry... I did not understand what the issue was. 射击,对不起...我不明白问题所在。 I don't think Advisories are the solution at all.... after all, you need to be connected to the broker to get them, but being connected is what you know about. 我根本不认为咨询是解决方案。。。毕竟,您需要与经纪人建立联系才能获得它们,但您所了解的就是建立联系。

So if I understand it correctly (prepare for retry #2....), what you need is a client connection which, when it fails, attempts to reconnect indefinitely. 因此,如果我正确理解它(准备重试#2...。),则需要的是客户端连接,当客户端连接失败时,它将尝试无限期地重新连接。 When it does reconnect, you want to trigger an event (or more) that flushes pending messages to the broker. 当它确实重新连接时,您想触发一个事件(或更多事件),以将未决消息刷新到代理。

So detecting the lost connection is easy. 因此,检测丢失的连接很容易。 You just register a JMS ExceptionListener . 您只需注册一个JMS ExceptionListener As far as detecting a reconnect, the simplest way I can think of is to start a reconnect thread. 至于检测到重新连接,我想到的最简单的方法就是启动一个重新连接线程。 When it connects, stop the reconnect thread and notify interested parties using Observer/Observable or JMX notifications or the like. 当它连接时,停止重新连接线程,并使用Observer / Observable或JMX通知等通知相关方。 You could use the ActiveMQ Failover Transport which will do a connection retry loop for you, even if you only have one broker. 您可以使用ActiveMQ故障转移传输 ,即使您只有一个代理,它也会为您执行连接重试循环。 At least, it is supposed to , but it's not doing that much for you that would not be done by your own reconnect thread... but if you're willing to delegate some control to it, it will cache your unflushed messages (see the trackMessages option), and then send them when it reconnects, which is sort of all of what you're trying to do. 至少它应该这样做,但是它并不能为您做很多事情,您自己的重新连接线程不会做... 但是如果您愿意将某些控制权委派给它,它将缓存您未刷新的消息(请参阅( trackMessages选项),然后在重新连接时将其发送出去,这就是您要执行的所有操作。

I guess if your broker is down for a few minutes, that's not a bad way to go, but if you're talking hours, or you might accumulate 10k+ messages in the downtime, I just don't know if that cache mechanism is as reliable as you would need it to be. 我想如果您的经纪人停了几分钟,那不是一个坏方法,但是如果您正在谈论几个小时,或者您可能在停机时间内积累了超过10k的消息,我只是不知道该缓存机制是否为可靠,如您所愿。

================== ==================

Mobile app ... right. 移动应用...对。 Not really appropriate for the failover transport. 不太适合故障转移传输。 Then I would implement a timer that periodically connects (might be a good idea to use the http transport, but not relevant). 然后,我将实现一个定期连接的计时器(使用http传输可能是一个好主意,但不相关)。 When it does connect, if there's nothing to flush, then see you in x minutes. 当它确实连接时,如果没有要冲洗的东西,然后在x分钟后见。 If there is, send each message, wait for a handshake and purge the message from you mobile store. 如果存在,请发送每条消息,等待握手,然后从移动存储中清除该消息。 Then see you again in x minutes. 再过x分钟再见。

I assume this is Android ? 我认为这是Android吗? If not, stop reading here. 如果没有,请在这里停止阅读。 We actually implemented this some time ago. 我们实际上是在一段时间之前实现的。 I only did the server side, but if I remember correctly, the connection timer/poller spun every n minutes (variable frequencies, I think, because getting too aggressive was draining the battery). 我只做服务器端,但是如果我没记错的话,连接计时器/轮询器每n分钟旋转一次(我认为可变频率是因为过于激进会消耗电池电量)。 Once a successful connection was made, I believe they used an intent broadcast to nudge the message pushers to do their thing. 建立成功的连接后,我相信他们会使用意图广播来推动消息推送者完成其任务。 The thinking was that even though there was only one message pusher, we might add more. 当时的想法是,即使只有一个消息推送器,我们也可能会添加更多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM