I maintain an application which uses MQTT.js in the browser to communicate with remote devices.
Some customers attempt to use the application behind firewalls that disable websockets, causing thousands of reconnect errors. Our error monitoring tool will often throttle error reporting because of the high volume of errors generated by MQTT.js (some users will leave the app open for hours after a connection failure).
Is there a way to set limits on reconnect attempts in MQTT.js?
Related
Accordingly blogpost from Jake Archibald, from Chrome 88 implements 3 stages of throttling
Accordingly throttling implementation from Chrome 57
There are a number of automatic exemptions from this throttling:
Applications playing audio are considered foreground and aren’t throttled.
Applications with real-time connections (WebSockets and WebRTC), to avoid closing these connections by timeout. The run-timers-once-a-second rule is still applied in these cases.
Second cite imeratively says, that once application has Websocket connection, application exempt from throttling.
The fact is, we use #microsoft/signalr library as top-level api for websocket connections, and this library uses internal ping (not a ping opcodes) messages, wrapped with setTimeout. After 5 minutes of background work, that timer throtlled and stops sending ping messages, thats leads to close event and websocket connection being closed.
I'm asking for more detailed explanation:
Does Chorome 88 enbles throttling for applications, that have real-time connections?
Does timers will be throttled regardless websocket connection appeareance and only websocket instances exempt from throttling?
accordingly this post same issues reported.
Quick explanation is:
As Jake wrote in blogpost about heavy throttling
the browser will check timers in this group once per minute. Similar to before, this means timers will batch together in these minute-by-minute checks.
That is! After 5 minutes tab spent in background, signalr ping algorithm will be throttled to 1 minute, BUT default values for keepAliveIntervalInMilliseconds = 15sec and serverTimeoutInMilliseconds = 30sec, thats twice smaller than heavy throttling timer delaying time and for server side it is count as ping failure that is predicate for lifetime methods invocation and stopping the connection, but first, server side trying to stop connection with disconnect handshake, and physically client is still connected, the result is - CloseEvent with code 1000 and wasClean = true. This behaviour wount produce any errors.
Front-end clients must update version of #microsoft/signalr to >= 5.0.6 to solve this problem. Changes
I'm working on a website where some events are broadcasted to the clients using SSE (EventSource API). When testing my site on the mobile version of Chrome for Android, I noticed the connection is lost when the channel is idle for about five minutes.
I used several Android devices, with different carriers and different browsers and the result is the same, no matter if the screen is on or off. Desktop Chrome seems to keep the connection alive for a longer time.
Couldn't find any info about this, and when trying to debug the issue, all I got was a TCP "FIN" packet received from the telephone IP address about 3 and a half minutes after the last event was sent.
EventSource's onerror event doesn't get fired so I can't know when the connection was dropped to initiate a new one.
Is there any way to avoid this problem or should I just send some fake message every 30 secs to prevent connection idling?
Thanks in advance
Your connection was probably taken by a "push proxy" - a feature that is designed to improve battery life in phones.
Quote from "https://html.spec.whatwg.org/multipage/server-sent-events.html":
User agents running in controlled environments, e.g. browsers on
mobile handsets tied to specific carriers, may offload the management
of the connection to a proxy on the network. In such a situation, the
user agent for the purposes of conformance is considered to include
both the handset software and the network proxy.
For example, a browser on a mobile device, after having established a
connection, might detect that it is on a supporting network and
request that a proxy server on the network take over the management of
the connection. The timeline for such a situation might be as follows:
Browser connects to a remote HTTP server and requests the resource specified by the author in the EventSource constructor.
The server sends occasional messages.
In between two messages, the browser detects that it is idle except for the network activity involved in keeping the TCP connection alive,
and decides to switch to sleep mode to save power.
The browser disconnects from the server.
The browser contacts a service on the network, and requests that the service, a "push proxy", maintain the connection instead.
The "push proxy" service contacts the remote HTTP server and requests the resource specified by the author in the EventSource
constructor (possibly including a Last-Event-ID HTTP header, etc).
The browser allows the mobile device to go to sleep.
The server sends another message.
The "push proxy" service uses a technology such as OMA push to convey the event to the mobile device, which wakes only enough to
process the event and then returns to sleep.
This can reduce the total data usage, and can therefore result in
considerable power savings.
You can set the retry field to establish the reconnection time of EventSource instance
If the field name is "retry"
If the field value consists of only ASCII digits, then interpret the field value as an integer in base ten, and set the event stream's
reconnection time to that integer. Otherwise, ignore the field.
I'm developing an application that uses SockJS to update some common data across the other applications connected to the server. The problem comes when
I try to open it in two browser tabs because just one of them achieve the connection while the other keeps waiting until the timeout comes.
¿Can anyone explain me why is this happening? ¿Is there any solution?
On the server I'm using an Spring implementation of SockJS whit the WebSocket transport disabled because the application server doesn´t support it.
To anyone who find this helpful, I ended up discovering that the HTTP/1.1 protocol recommends a connection limit of two connections per domain, so, the browsers share this two connections across any tab/window/iframe. As a result, when this two connections are consummed, every other connection/request have to wait until one of that two connections is released.
Libraries like cometd handle this by detecting when multiple clients are connected and falling back to normal poll.
I have a question about Firebase's offline capabilities for JavaScript. Specifically, I am wondering if one were to lose connection while filling out a form on a web application (powered by firebase, obviously), and then try to send that form, would it perform a write operation to the local database, and then catch up with the server when connection is re-established, or would that data be lost? If this is a yes, I am assuming that it does not matter if the user exits out of the page, as long as the form as sent.
I know that it offers tremendous disk persistence for its iOS and Android SDKs, however I am just trying to get a better handle on how this can help in JavaScript. I am aware of the onDisconnectclass, and that it should mainly be used to manage the presence of a users as well - Just has this on mind for a while!
Thanks !
Firebase supports two types of offline mode:
in case of intermittent loss of connectivity, the client will keep serving events from the local data and any writes will be queued. When the connection is restored, all writes are sent to the server and any stale data is resynchronized. We often call this "tunnel mode".
The mobile native (iOS and Android) clients can be configured through their API to store all data on the local disk. In case of prolonged loss of connectivity, these clients will then queue writes on disk too. The client will also be able to serve data from this disk cache, when the app is restarted. This one we often call "airplane mode".
Tunnel mode is available in all Firebase SDKs. Airplane mode is only available in Firebase's native mobile SDKs for Android and iOS.
So basically, if I have say a chat application using websockets, I want to be able to send the server a message saying I'm disconnecting. I've tried binding to onbeforeunload, but that seems to only be able to display a message.
Is there a better strategy to this? If not, it seems like I'd have to do some sort of ping/timeout strategy from the server side.
Thanks.
WebSockets are implemented on top of TCP, and in TCP world different connection drops - is expected scenario.
In terms of network security - your server side should never rely on "kindness" of clients, and should always be independent and expect any and more scenario of disconnects.
Taking this in account, you have to expect unexpectedly dropped connections (GPRS/EDGE/3G/4G poor connection or going under bridge/ground, wifi drops, ethernet unplug, ISP issues, server network problems, and many more). Dropped connections without "bye" in fact is most common disconnects you will get, so have to implement server side logic taking this in account.