WebSocket shuts down after X amount of time

Heya everyone,

I have a React/JS & Django Rest Framework project. A part of the project is a chat which was made using websockets through django-channels.

The application is deployed using Nginx as a reverse proxy for the WSGI part of the app and Daphne for the ASGI/channels part of the app.

Everything seems to be working fine, except that the websocket I have a “persistent” connection to closes the connection after an unspecified amount of time. Some times it’s after 15 minutes of inactivity, sometimes it’s after an hour and I haven’t been able to find the cause.

From my understanding, websocket connections should be persistent – they shouldn’t close until you explicitly close the connection, so does anyone have any idea why this might be happening or how to prevent it?

The issue could be happening in any number of places, depending upon the precise network infrastructure involved. Any router in the path or network interface could have inactive tcp connection timeouts that would drop connections after some period of time. You’d have to evaluate everything in the network between the client and the server to definitively identify a source.

We have our JavaScript client code (HTMX) issue “heartbeat” packets at 27 second intervals. HTMX also handles the reconnect process if a connection gets dropped, which can happen quite easily with mobile devices. (Thank you HTMX!)

Would I just have to issue heartbeat packets from the client side code, or does the server have to respond with something or do something in addition to it?

Also, how come you are issuing heartbeats at 27 seconds intervals, that seems like a very specific number?

In my case, it’s a “ping/pong” combination, but no, I don’t think a response from the server is technically necessary. (I don’t do anything with the response. I originally created it as part of a debugging tool and just have never bothered removing it.)

Regarding the timing, it’s actually 27 + a “fuzz factor” to reduce the possibility of a “thundering herd” situation from occurring.

Aah, I see. Thank you for the advice. I’ll implement heartbeat packets and see if that maybe solves my issue, cause I am not seeing any problems between the client and the server, the network seems completely fine. :confused:

As a side note, it’s not necessarily a “problem”. All of nginx, iptables, f5, and haproxy have idle timeout settings available. Every Cisco router I’ve worked with does as well.

Maintaining a tcp socket connection does require some resources for the devices responsible for sustaining them, and so removing idle connections is appropriate, since those devices have no way to know whether either side have completely gone away.

I always thought websockets were meant to explicitly always stay on, until explicitly closed, but I guess one of the devices could trump that at any point. Hopefully I can leave them on in that case implementing heartbeat packets, since as far as I know, idle websockets don’t use much resources and I do need them in my case to stay open even with hours of idle time on them.

Also, do you perhaps have any idea on how I would go about handling the reconnect process if it does still get dropped sometimes – in a React/DRF stack?

They are - but they’re a tcp connection just like any other tcp socket. From the perspective of the network infrastructure between them, they’re no different than a telnet, ssh, ftp, or any other tcp socket.

Individually, from the perspective of the endpoints, this is accurate.

However, from the perspective of the networking components between the endpoints, it’s just another connection needing to be maintained. Individually, not much - but consider all of the connections that could reasonably need to be maintained, and if every connection was held open in the absence of an explicit disconnect, it would exhaust what resources are available.

Sorry, I don’t use React. (DRF isn’t an issue here since it is not involved in the networking stack.)

Alright, thanks for the info Ken, I’ll take all of it into consideration working on a solution. :slight_smile: