pythontimeoutstompactivemq-artemisdurable-subscription

Connection timeout error for ActiveMQ Python STOMP client


I am using the stomp.py 8.1.0 Python client to listen to Red Hat AMQ 7.4.1 (based on ActiveMQ Artemis), and I frequently get this error:

received an error {cmd=ERROR,headers=[{'message': 'AMQ229014: Did not receive data from /xx.xxx.xx.xx:57182 within the 60,000ms connection TTL. The connection will now be closed.'}],body=}

My client is:

import sys
import os
import stomp

user = "a_user"
password = "a_password"
host = "a_host"
port = 61616
destination = "a_topic"

class MyListener(stomp.ConnectionListener):
  
  def __init__(self, conn):
    self.conn = conn
    self.count = 0
    self.errors = 0
    self.start = time.time()
    self.stop = False
  
  def on_error(self, message):
    print('received an error %s' % message)
    self.stop = True
    
  def on_message(self, message):
    if message == "SHUTDOWN":
    
      diff = time.time() - self.start
      print("Received %s in %f seconds" % (self.count, diff))
      conn.disconnect()
      sys.exit(0)
      
    else:
      if self.count==0:
        self.start = time.time()
        
      self.count += 1
      
      print("Received %s messages." % self.count)
      
      if self.count > 10:
          self.stop = True

  def will_stop(self):
    return self.stop
    
conn = stomp.Connection(host_and_ports = [(host, port)])
listener = MyListener(conn)
conn.set_listener('', listener)
conn.connect(login=user,passcode=password, wait=True, headers = {'client-id': 'testname'})
conn.subscribe(destination=destination, id=30999, ack='auto', persistent=True, headers = {"activemq.subscriptionName":"testsub"})
print("Waiting for messages...")
while listener.count < 100 and not listener.will_stop(): 
  time.sleep(10) 

Anyone knows whether my client is done correctly as a durable one, and should I revise my timeout setup, and how? A third-party system is publishing messages sparsely, this means my listener/subscriber will have to wait a long while to get a new message.


Solution

  • The broker is closing the connection because it is completely inactive and the time-to-live (i.e. TTL) is elapsing.

    You need to configure heart-beating as described in the STOMP specification. As noted in the spec:

    Heart-beating can optionally be used to test the healthiness of the underlying TCP connection and to make sure that the remote end is alive and kicking.

    To do this with stomp.py you can follow the example in the documentation, e.g.:

    conn = stomp.Connection([(host, port)], heartbeats=(4000, 4000))
    

    If the network connection between the client and the broker is not very reliably you could try increasing the heartbeats (e.g. 10000, 10000) or you could try setting heart_beat_receive_scale=2.0 when creating the connection or both.