Implementing heartbeat in stomp.py - python

I am seeing behavior in our stomp.py 7.0 client (listener only) where after some idle time of not receiving messages the ActiveMQ 5.15.9 broker seems to drop the client (i.e. looking at the ActiveMQ management console shows zero consumers). The odd thing is the on_disconnected handler of the client never gets called and we have a health check on the client service that checks the connection is_connected(), however it still returns true.
Based on my understanding/research (please correct if any of this is false) this is due to the broker trying to clean-up resources it perceives as inactive. Also based on my research "heartbeating" can be used to avoid this perception on the broker.
I know how to send the heartbeat header from the client and how to check the response from the server/broker (as far as what it expects) in on_connected but my question is how do I send the actual heartbeat from the client to the server/broker? Do I need to send a message on the queue I am listening to? If so how do I send a "heartbeat message" and not have to adjust message handling code in my listeners? Do I send it without a body? Also does the broker need to be configured to accept heartbeats? and If it is not configured would declaring and sending them from the client still result in the broker disconnecting the client?

Heart-beating is part of STOMP 1.2 so as long as your client supports STOMP 1.2 you should be able to configure heart-beating when the connection is established. Also, if your broker supports STOMP 1.2 it should accept the heart-beat header and adjust its behavior accordingly. You shouldn't have to send your own heart-beats. In the absence of any "normal" STOMP frames the client itself should send an EOL as described in the specification.
If your client doesn't support STOMP 1.2 then you should upgrade to a client that does. The STOMP 1.2 spec was released in October 2012, almost a decade ago now so there's been plenty of time to implement support.

Related

How to not lose any MQTT messages

I am new to using MQTT. I have set up an Arduino publishing MQTT messages to ActiveMQ. I also have a Python script subscribed to the same topic (using paho) which gets the data from the broker and inserts it into a database.
The problem is if this Python script is down or loses connection for any reason I lose all messages being published while its down. How can I ensure all the data is inserted into the database? I see ActiveMQ has some sort of storage is it possible to retrieve historic data from it?
If you want to ensure that your subscription persists and receives messages even if the subscriber gets disconnected then you need to set CleanSession=false on your MQTT client (assuming you're using MQTT 3.x) and use the same client ID when you reconnect.
Also, if you want messages to survive a broker restart or crash you need to send them with QoS 1.
I think the PubSubClient Arduino library only publishes with fire and forget (QoS 0). I've instead used the stomp.py library to create a durable consumer subscribed to the same topic. If there's no connection on Arduino It's saved to the SD card and if there is connection but no client at the time the messages are stored by ActiveMQ until the client is active.
This solved my problem but I'm still testing the durability

Allowing message dropping in websockets

Is there a simple method or library to allow a websocket to drop certain messages if bandwidth doesn't allow? Or any one of the following?
to measure the queue size of outgoing messages that haven't yet reached a particular client
to measure the approximate bitrate that a client has been receiving recent messages at
to measure the time that a particular write_message finished being transmitted to the client
I'm using Tornado on the server side (tornado.websocket.WebSocketHandler) and vanilla JS on the client side. In my use case it's really only important that the server realize that a client is slow and throttle its messages (or use lossier compression) when it realizes that condition.
You can implement this on top of what you have by having the client confirm every message it gets and then use that information on the server to adapt the sending of messages to each client.
This is the only way you will know which outgoing messages haven't yet reached the client, be able to approximate bitrate or figure out the time it took for the message to reach the client. You must consider that the message back to the server will also take time and that if you use timestamps on the client, they will likely not match your servers as clients have their time set incorrectly more often than not.

Can pyzmq pub/sub sockets be used bidirectionally?

I'm using a pyzmq pub/sub socket for a server to advertise notifications to client subscribers. It works nicely but I have a question:
Is there any way to use the same socket to send information back to the server? Or do I need a separate socket for that?
Use case: I just want to allow the server to see who's actively subscribing to notifications, so I was hoping I could allow clients to send back periodic "heartbeat" messages. I have a use case where if no clients are listening, I want the server to spawn one. (This is a multiprocess system that uses localhost only.)
You need a separate socket. From the ZMQ guide (http://zguide.zeromq.org/page:all#Pros-and-Cons-of-Pub-Sub):
Killing back-chatter is essential to real scalability. With pub-sub, it's how the pattern can map cleanly to the PGM multicast protocol, which is handled by the network switch. In other words, subscribers don't connect to the publisher at all, they connect to a multicast group on the switch, to which the publisher sends its messages.
In order for this to work, the PUB socket will not send back data to the subscribers (at least not in a way visible to the user. The heartbeating problem was discussed in-depth in the guide: http://zguide.zeromq.org/page:all#The-Asynchronous-Client-Server-Pattern
Also, check out the 7/MDP and 18/MDP protocols (http://rfc.zeromq.org/spec:7 -- this is also discussed in the guide) if you want to keep track of clients.

python uwsgi 2.0 websocket implementation

I am working on a websocket implementation based on uwsgi 2.0 in python. I am a little confused about how messages are sent from the websocket server to the client. Would appreciate if someone would clarify the following for me.
When uwsgi.websocket_send(msg) is used, is the message sent to all connected clients or the one for which the handshake is established?
Is it possible to use websocket to send messages to a group of clients (channels) if yes, are there any examples out there for this?
the whole api is peer 2 peer, uwsgi.websocket_send send to the currently connected peer. You need an additional layer (generally redis) to have room/channels support.
This is an example (gevent + redis) https://github.com/unbit/uwsgi/blob/master/tests/websockets_chat.py

WebSocket messages get queued when client disconnected

We have a server, written using tornado, which sends asynchronous messages to a client over websockets. In this case, a javascript app running in Chrome on a Mac. When the client is forcibly disconnected, in this case by putting the client to sleep, the server still thinks it is sending messages to the client. Additionally, when the client awakens from sleep, the messages are delivered in a burst.
What is the mechanism by which these messages are queued/buffered? Who is responsible? Why are they still delivered? Who is reconnecting the socket? My intuition is that even though websockets are not request/response like HTTP, they should still require ACK packets since they are built on TCP. Is this being done on purpose to make the protocol more robust to temporary drops in the mobile age?
Browsers may handle websocket client messages in a separate thread, which is not blocked by sleep.
Even if a thread of your custom application is not active, when you force it to sleep (like sleep(100)), TCP connection is not closed in this case. The socket handle is still managed by OS kernel and the TCP server still sends the messages until it reaches the TCP client's receive window overflow. And even after this an application on server side can still submit new messages successfully, which are buffered on TCP level on server side until TCP outgoing buffer is overflown. When outgoing buffer is full, an application should get error code on send request, like "no more space". I have not tried myself, but it should behave like this.
Try to close the client (terminate the process), you will see totally different picture - the server will notice disconnect.
Both cases, disconnect and overflow, are difficult to handle on server side for highly reliable scenarios. Disconnect case can be converted to overflow case (websocket server can buffer messages up to some limit on user space while client is being reconnected). However, there is no easy way to handle reliably overflow of transmit buffer limit. I see only one solution - propagate overflow error back to originator of the event, which raised the message, which has been discarded due to overflow.

Categories

Resources