簡體   English   中英

Spring Integration MQTT cleanSession=false 失敗,因為客戶端取消訂閱主題

[英]Spring Integration MQTT cleanSession=false fails because client unsubscribes from topics

我正在配置 Spring Integration 以在我的一個頻道上使用 cleanSession=false。

<bean id="clientFactory" class="org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory">
        <property name="cleanSession" value="false" />
</bean>


<int-mqtt:message-driven-channel-adapter id="mqttLiveDataInbound"
    client-id="client1"
    url="${mqtt.broker.url}"
    qos="1"
    topics="liveData"
    client-factory="clientFactory"
    channel="channelLiveData"/> 

原因是我希望能夠在我的應用程序離線時接收消息。 當我的應用程序重新啟動時,我希望它接收在我不在時發布的任何 QoS>0 消息。

現在我注意到一些奇怪的事情:我的應用程序在停機后沒有獲取丟失的 QoS>0 消息。

我記錄了一個簡單的場景,其中

  • Spring集成開始
  • 向主題發送 QoS1 消息並由 Spring Integration 接收
  • Spring集成退出
  • 向主題發送 QoS1 消息
  • Spring集成開始
  • Spring Integration 不接收離線時發送的 QoS1 消息。

原因如下(從下面的日志中可以看出):

  • spring 集成退出
  • 它取消訂閱該主題
  • 它斷開客戶端

這實質上是告訴代理該客戶端不再對這些消息感興趣。 當我的應用程序關閉時,代理不再為我保留這些 QoS>0 消息。

當我的應用程序再次啟動時,它無法接收在它關閉時發布的 QoS>0 消息。

1448917620: New connection from 127.0.0.1 on port 1883.
1448917620: New client connected from 127.0.0.1 as client1 (c0, k60).
1448917620: Sending CONNACK to client1 (0, 0)
1448917620: Received SUBSCRIBE from client1
1448917620:     liveData (QoS 1)
1448917620: Sending SUBACK to client1
1448917632: New connection from ::1 on port 1883.
1448917632: New client connected from ::1 as mosqpub/25936-MacBook-P (c1, k60, u'system').
1448917632: Sending CONNACK to mosqpub/25936-MacBook-P (0, 0)
1448917632: Received PUBLISH from mosqpub/25936-MacBook-P (d0, q1, r0, m1, 'liveData', ... (68 bytes))
1448917632: Sending PUBACK to mosqpub/25936-MacBook-P (Mid: 1)
1448917632: Sending PUBLISH to client1 (d0, q1, r0, m1, 'liveData', ... (68 bytes))
1448917632: Received DISCONNECT from mosqpub/25936-MacBook-P
1448917632: Client mosqpub/25936-MacBook-P disconnected.
1448917633: Received PUBACK from client1 (Mid: 1)
1448917643: Received UNSUBSCRIBE from client1
1448917643:     liveData
1448917643: Received DISCONNECT from client1
1448917643: Client client1 disconnected.
1448917648: New connection from ::1 on port 1883.
1448917648: New client connected from ::1 as mosqpub/25945-MacBook-P (c1, k60, u'system').
1448917648: Sending CONNACK to mosqpub/25945-MacBook-P (0, 0)
1448917648: Received PUBLISH from mosqpub/25945-MacBook-P (d0, q1, r0, m1, 'liveData', ... (68 bytes))
1448917648: Sending PUBACK to mosqpub/25945-MacBook-P (Mid: 1)
1448917648: Received DISCONNECT from mosqpub/25945-MacBook-P
1448917648: Client mosqpub/25945-MacBook-P disconnected.
1448917665: New connection from 127.0.0.1 on port 1883.
1448917665: Client client1 disconnected.
1448917665: New client connected from 127.0.0.1 as client1 (c0, k60).
1448917665: Sending CONNACK to client1 (1, 0)
1448917665: Received SUBSCRIBE from client1
1448917665:     liveData (QoS 1)
1448917665: Sending SUBACK to client1

我使用 mosquitto 客戶端工具運行了這個場景,退出 mosquitto 訂閱者會斷開客戶端的連接,但不會取消訂閱該主題

1448917534: New connection from ::1 on port 1883.
1448917534: New client connected from ::1 as client1 (c0, k60).
1448917534: Sending CONNACK to client1 (0, 0)
1448917534: Received SUBSCRIBE from client1
1448917534:     liveData (QoS 1)
1448917534: Sending SUBACK to client1
1448917550: New connection from ::1 on port 1883.
1448917550: New client connected from ::1 as mosqpub/25879-MacBook-P (c1, k60, u'system').
1448917550: Sending CONNACK to mosqpub/25879-MacBook-P (0, 0)
1448917550: Received PUBLISH from mosqpub/25879-MacBook-P (d0, q1, r0, m1, 'liveData', ... (68 bytes))
1448917550: Sending PUBACK to mosqpub/25879-MacBook-P (Mid: 1)
1448917550: Sending PUBLISH to client1 (d0, q1, r0, m1, 'liveData', ... (68 bytes))
1448917550: Received DISCONNECT from mosqpub/25879-MacBook-P
1448917550: Client mosqpub/25879-MacBook-P disconnected.
1448917550: Received PUBACK from client1 (Mid: 1)
1448917553: Socket error on client client1, disconnecting.
1448917554: New connection from ::1 on port 1883.
1448917554: New client connected from ::1 as mosqpub/25884-MacBook-P (c1, k60, u'system').
1448917554: Sending CONNACK to mosqpub/25884-MacBook-P (0, 0)
1448917554: Received PUBLISH from mosqpub/25884-MacBook-P (d0, q1, r0, m1, 'liveData', ... (68 bytes))
1448917554: Sending PUBACK to mosqpub/25884-MacBook-P (Mid: 1)
1448917554: Received DISCONNECT from mosqpub/25884-MacBook-P
1448917555: Client mosqpub/25884-MacBook-P disconnected.
1448917556: New connection from ::1 on port 1883.
1448917556: Client client1 disconnected.
1448917556: New client connected from ::1 as client1 (c0, k60).
1448917556: Sending CONNACK to client1 (0, 0)
1448917556: Sending PUBLISH to client1 (d0, q1, r0, m2, 'liveData', ... (68 bytes))
1448917556: Received SUBSCRIBE from client1
1448917556:     liveData (QoS 1)
1448917556: Sending SUBACK to client1
1448917556: Received PUBACK from client1 (Mid: 2)

知道如何處理這種情況嗎?

編輯 :

在實施已接受的答案中提出的解決方法時,我收到以下錯誤。 我的 Spring 上下文是從 webapp 加載的。 我試過將 IgnoreUnsubscribePahoClientFactory 放在一個單獨的 JAR(與 spring-integration/paho 相同的級別)以及 webapp 類本身中。

2015-12-02 15:47:43,703 ERROR org.springframework.integration.handler.LoggingHandler - org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class [class org.eclipse.paho.client.mqttv3.MqttAsyncClient]: Common causes of this problem include using a final class or a non-visible class; nested exception is org.springframework.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
        at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:206)
        at org.springframework.aop.framework.ProxyFactoryBean.getProxy(ProxyFactoryBean.java:368)
        at org.springframework.aop.framework.ProxyFactoryBean.getSingletonInstance(ProxyFactoryBean.java:322)
        at org.springframework.aop.framework.ProxyFactoryBean.getObject(ProxyFactoryBean.java:246)
        at com.ecs.vdm.rest.integration.IgnoreUnsubscribePahoClientFactory.proxy(IgnoreUnsubscribePahoClientFactory.java:62)
        at com.ecs.vdm.rest.integration.IgnoreUnsubscribePahoClientFactory.getAsyncClientInstance(IgnoreUnsubscribePahoClientFactory.java:43)
        at org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter.connectAndSubscribe(MqttPahoMessageDrivenChannelAdapter.java:216)
        at org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter.access$300(MqttPahoMessageDrivenChannelAdapter.java:45)
        at org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter$1.run(MqttPahoMessageDrivenChannelAdapter.java:272)
        at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
        at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:304)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:178)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
        at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:237)
        at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:377)
        at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:317)
        at org.springframework.aop.framework.ObjenesisCglibAopProxy.createProxyClassAndInstance(ObjenesisCglibAopProxy.java:57)
        at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:202)
        ... 16 more
Caused by: java.lang.reflect.InvocationTargetException
        at sun.reflect.GeneratedMethodAccessor37.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:384)
        at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:219)
        ... 20 more
Caused by: java.lang.SecurityException: class "org.eclipse.paho.client.mqttv3.MqttAsyncClient$$EnhancerBySpringCGLIB$$d14754a9_4603"'s signer information does not match signer information of other classes in the same package
        at java.lang.ClassLoader.checkCerts(ClassLoader.java:952)
        at java.lang.ClassLoader.preDefineClass(ClassLoader.java:666)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:794)
        ... 25 more

這是一個錯誤 - 它在stop()期間無條件取消訂閱。

我沒有看到簡單的解決方法; 但我有幾個想法; 如果/當我有東西時,我會在這里發布。

同時,請打開一個JIRA 問題

編輯

要點在這里

這有點像大錘,但它應該適合你; 它有效地忽略了unsubscribe客戶端的調用。 它可以做得更復雜一點,只在 QOS > 0 時忽略,但這會涉及更多。

如果您已經在使用DefaultMqttPahoClientFactory只需將 bean 類更改為這個類。 如果您當前未使用工廠,請將其聲明為 bean 並使用client-factory屬性將其提供給適配器。

我們將在即將發布的版本中正確修復它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM