websockets icon indicating copy to clipboard operation
websockets copied to clipboard

Stop listening for new connections for graceful stopping of server

Open davidavdav opened this issue 3 years ago • 3 comments

Hello,

We're busy moving from tornado to websockets, and it looks like we can do almost everything, but much simpler. Great!

There is one thing I can't seem to get going: make the server stop listening for new connections, but keep current connections open until the last client exists, then finally exit altogether. I can keep track of current clients, but I can't seem to be able to prevent new clients from connecting.

So my idea for super graceful shutdown is:

  • stop accepting new connections
  • keep handling existing connections from clients, until they exit
  • if there are no more clients, shutdown and exit

I've experimented with the server's close(), which seems to disconnect existing clients, and await wait_closed(), which, in my case does nothing, but I suppose it is meant to be used after a normal server close(). I can't find anything like tornado's stop().

Any ideas how I could accomplish this?

Thanks!

davidavdav avatar May 11 '22 17:05 davidavdav

You don't have a public API for this right now.

You'd need a way to pause here: https://github.com/aaugustin/websockets/blob/c4a4b6f45af607431c5707d56420bbaf471bbb6e/src/websockets/legacy/server.py#L766, which doesn't exist right now.

You can do it with a private API as follows:

server.server.close()

where server is the object returned by serve().

I think the behavior you're requesting could be added as an option to server.close().

aaugustin avatar May 11 '22 20:05 aaugustin

Thanks!

This seems to work for me. I use an event shutdown_event to consecutively signal

  • stop accepting new connections
  • all connections are closed

For future reference, the code excerpt is

shutdown_event = asyncio.Event()
server = await websockets.serve(handler, "", port)
logger.info("HTTP websocket server started")
await shutdown_event.wait()  # run until shutdown
shutdown_event.clear()
logger.info("Shutdown event happened")
server.server.close()
logger.info("Stopped accepting")
await shutdown_event.wait()
logger.info("All connections closed")
server.close()
await server.wait_closed()
logger.info("Server closed")

davidavdav avatar May 12 '22 09:05 davidavdav

I will keep this issue open in order to implement a public API for this.

aaugustin avatar May 12 '22 11:05 aaugustin

Hello @davidavdav - sorry for not following up earlier. If you're able to confirm that #1241 does what you want, that would be amazing.

aaugustin avatar Oct 09 '22 16:10 aaugustin

Oops - forgot to merge this before releasing 10.4 :-( I'm going to merge it now.

aaugustin avatar Oct 25 '22 20:10 aaugustin