I have a websocket server based on Jetty v9.3.9
The server sends text messages to clients from different Threads.
A single client can receive multiple simultaneous messages from 2 different threads.
For example:
Thread 1: "message A"
Thread 2: "message B"
Sometimes, not all the times, but around 4-5% of the time, the client doesn't receive all the messages. It receive either message A or B. The client is based on the browser.
I tested in both Firefox and Chrome, and I looked in web console to see if the message is received and is not.
The code I'm using for sending the message is
getSession().getRemote().sendString(this.message);
from http://download.eclipse.org/jetty/9.3.9.v20160517/apidocs/org/eclipse/jetty/websocket/api/RemoteEndpoint.html#sendString-java.lang.String-org.eclipse.jetty.websocket.api.WriteCallback-
Is this the right way to do this? Should I use sendStringByFuture(String text) ? Am I missing something.
On the server I have around 800-1k connected clients, that sends and receives multiple messages from different threads.
NOTE: I used websockets with Jetty since version 8 and I can't remember having this problems until I updated to 9, however I can't go back.
Thank you
Related
I'm working on making an iOS app that does a few things, some of which would benefit from real-time data streams (like chat)
For right now I have a few handlers on my server, one of them gets all the threads a user has access to, another can get messages (offset, all, time-ranged, etc.) for a thread. When a user sends a message to a thread, I get all the listeners for the thread and send them a push notification. This works, but I was reading through the APNS docs and it says "dont do more than 3/hr" and I'm definitely doing more than 3/hr.
So I'm thinking I move to websockets. I know how to synchronize pub/subs across machines via redis so I'm not worried about that, I'm more stuck on the following:
If I start to bring websockets into the project, should I just pump all the information App <-> Server through the websocket? Create a thread -> Don't POST, just send a message along the socket. Get a message -> Don't poll or send notification, just send a message along the socket. Literally anything -> Don't make a request, just send a message along the socket.
Right now I'm leaning towards loading initial state and bulk data via normal HTTP URLs (eg: Create a thread, load the last 20 messages for thread XYZ), but for data that needs to be pushed and received in real time (eg: Chat Message send/recv) do that via a websocket.
I have an application in which clients use websockets to connect to a server which is running Spring Boot Tomcat.
My question is if there is a way for the server to detect a client disconnect due to a network loss.
Thanks.
if you are using stomp , check SessionDisconnectEvent.
For raw Websocket connections, you can use :
WebSocketHandler-->afterConnectionClosed
I have searched before for this and the solution I was able to find was to implement a ping-pong mechanism between the server and the clients.
For example, each few seconds send a dummy message to the client on a specific topic and receive back another dummy reply, if you didn't get a reply for a configured period you can consider the client disconnected.
As mentioned here,
STOMP and Spring also allow us to set up topics, where every
subscriber will receive the same message. This is going to be very
useful for tracking active users. In the UI, each user subscribes to a
topic that reports back which users are active, and in our example
that topic will produce a message every 2 seconds. The client will
reply to every message containing a list of users with its own
heartbeat, which then updates the message being sent to other clients.
If a client hasn't checked in for more than 5 seconds (i.e. missed two
heartbeats), we consider them offline. This gives us near real time
resolution of users being available to chat. Users will appear in a
box on the left hand side of the screen, clicking on a name will pull
up a chat window for them, and names with an envelope next to them
have new messages.
I'm trying to get a "communication line" between a server app that uses MQTT for messaging and a web page where I want to see the messages in real time and send back messages to the server-side app.
I use mosquitto, Bottle and gevent on the server and I want to keep it as simple as possible. Using gevent I managed to receive the MQTT messages in a greenlet, put them in a queue and send the messages to the webpage in the websocket procedure which looks like this:
while True:
mqt = queue.get(True)
ws.send(mqt)
I can also send messages from the web page back to the server and MQTT like this (also through a queue):
while True:
msg = ws.receive()
queue2.put(msg)
However I want these two loops to work at the same time on the same websocket. Is there any way to combine them? For example does receive have a timeout? I guess I could use two separate websockets, but that would be a waste if I can do it with only one.
Why not just have messages delivered directly to the page using MQTT over Websockets? There are a number of brokers that support Websockets and the paho JavaScript client allows both subscribing and publishing of messages
I built a small server (golang) to grab messages from a RabbitMQ and deliver them to connected browsers via a Websocket.
It works quite well, though has one caveat: the messages are acknowledged when delivered to the browser via the websocket. For most messages that is ok but some messages might be very important. If the user's browser received those but the user didn't SEE the message, it would be lost if the browser was closed or reloaded.
Is there a way to ack a message at a later time based on its message id (from the Delivery struct)?
The use case would be that some messages are acked when the user acknowledges them explicitly and at that point the message id is sent back to the tool to be acknowledged with RabbitMQ.
Even if you can do this, it's bad design.
What happens to the message if the user doesn't see it? Does your web server infinitely hang on to it? Does it "nack" the message back to the queue?
Neither of these options are good.
Hang on to every message, and RabbitMQ will start having issues with thousands of unacknowledged messages from a lot of users. Nack the message back to the queue and you'll thrash the message round in circles, spiking CPU resources on the web server and the RMQ server, as well as network traffic between the two.
The better solution to this problem is to store the message in a database, after pulling it out of RabbitMQ. When it gets sent to / viewed by the browser, update the database to reflect that.
From a yet-unpublished article I've written:
Store the message in a database.
Add a field to the database record that says who this message belongs
to. When the user reconnects later, query the database for any
messages that this user needs to see and send them along at that time.
The full process started above, then becomes this:
User's browser connects to SignalR/Socket.io/Pusher/websockets on web
server
Web server checks a queue for updates that happen during a long
running process
When a message for a logged in user comes in
If the
user is logged in, broadcast the message through the websocket to the
user
If the user is not logged in, store the message in a database
When the user logs in again, query the database and send all waiting
messages
It's what you would have done before the idea of a message
queue came in to play, right? It should be what you would do now that
you have a message queue, as well.
I want to send data to a server from a client. Only the last message is important to the server. If the server comes up after a failure I only want the server to get the last message from the client.
While the server is down I want the client to keep processing and send messages or atlest put them in a queue(with the length of one message).
I try to use NetMQ/ZeroMQ for this. How can it be done?
Thanks!
First use PubSub where the client is the publisher, with PubSub you will only get messages while you online, if the subscriber (server in your case) was down it missed all the messages (like a radio)
ZeroMQ also has a feature called Conflate (NetMQ doesn't have it yet, you might want to port it), take a look at the following question:
ZeroMQ: I want Publish–Subscribe to drop older messages in favor of newer ones
Also description of conflate from ZeroMQ documentation:
ZMQ_CONFLATE: Keep only last message If set, a socket shall keep only one message in its inbound/outbound queue, this message being the last message received/the last message to be sent. Ignores 'ZMQ_RCVHWM' and 'ZMQ_SNDHWM' options. Does not support multi-part messages, in particular, only one part of it is kept in the socket internal queue.