0
| WARN  | Transport Connection to: tcp://ip:port failed: org.apache.activemq.transport.InactivityIOException: Channel was inactive for too long | org.apache.activemq.broker.TransportConnection.Transport | AmqpInactivityMonitor Async Task: java.util.concurrent.ThreadPoolExecutor$Worker@7e641927[State = -1, empty queue]

I am trying to send a message from java[publisher] to active mq, which is getting enqueued in active mq. subscriber code is written in python[using this library python-qpid-proton 0.31.0]. the subscribers stays active when no request is sent to active mq. But when a request is sent to active mq , client in "Active Durable Topic Subscribers" goes in to "Offline Durable Topic Subscribers" after sometime while the request is being processed.when the same code run in pycharm will work fine but on exe can see this issue python receiver code looks like this:-

P1 = Receiver(url, subscriptionname)
        from proton.reactor import Container
        Container(P1).run()


class Receiver(MessagingHandler):
super(Receiver, self).__init__()
    def __init__(self, url, subscriptionname):
        self.url = Url(url)
        self.stopping = False
        self.messages_actually_received = 0
        self.subscriptionName = subscriptionname

    def on_start(self, event):
        durable = DurableSubscription()
        event.container.container_id = "client"
        connection = event.container.connect(self.url)
        event.container.create_receiver(connection , self.url.path, name=self.subscriptionName, options=durable)
        

     def on_message(self, event):
        if self.stopping:
            return
        
        self.messages_actually_received += 1
        if event.message.body == 'message':
               pass
vee
  • 1
  • 1

1 Answers1

0

Between the above, and the message you just posted on the ActiveMQ mailing list where you say your 'huge request processing' actually takes >30sec, it sounds very much like you are utilizing the client container thread to do the work for >30sec in on_message, which you shouldnt really do. It is a single threaded client and so by doing that means it wont be able to process the connection at all during the time you monopolise the thread for other things. That means it cant send heartbeat frames if needed to satisfy the brokers (default 30sec) inactivity timeout whilst no other messaging traffic is occurring to be considered as activity. Due to the client not sending any data to the broker for 30 seconds the connection will be considered dead and killed, as the log message clearly shows happened.

You should generally avoid blocking the container thread for long periods, e.g disable auto-accept on the receiver and offload long-running processing of messages to a worker thread if needed, before passing back to the container thread for acceptance. Alternatively you will need to configure a higher connection timeout for the broker so it doesnt kill your apparently-dead connection.

Note that if you do offload message processing, passing the task back to the container thread to e.g accept/other the message needs to be done safely, since again the connection is single-threaded and only meant to be used directly from the container thread, using it directly from another while the container thread may also be using it isnt safe.

I believe the EventInjector was the intended route for things like this, provoking work on the connection from outwith the container thread: http://qpid.apache.org/releases/qpid-proton-0.36.0/proton/python/docs/proton.reactor.html#proton.reactor.EventInjector

Its used in these examples: http://qpid.apache.org/releases/qpid-proton-0.36.0/proton/python/examples/db_recv.py.html http://qpid.apache.org/releases/qpid-proton-0.36.0/proton/python/examples/db_send.py.html http://qpid.apache.org/releases/qpid-proton-0.36.0/proton/python/examples/tx_recv_interactive.py.html

You can also provoke your own scheduled callbacks on the container, so a simpler alternative might just be scheduling (while still using the container thread, not your own) a task of your own to periodically run, that e.g picks up completed 'processed' messages to accept/other from a thread-safe work queue. Timer example: http://qpid.apache.org/releases/qpid-proton-0.36.0/proton/python/examples/recurring_timer.py.html