Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there a graceful way to drain a keep-alive connection server side? #1652

Open
eseres opened this issue May 31, 2024 · 1 comment
Open

Comments

@eseres
Copy link

eseres commented May 31, 2024

The use case is one of selective connection draining initiated server side. The server must continue to be able to receive new connections, processing new HTTP requests on those connections. We just need to be able to selectively drain a chosen connection without discarding HTTP requests on that connection while doing so. Suspending and subsequently stopping the ranch listener as described here is not a solution for us.

The obvious answer would be to add the Connection: close header to the response of a currently running HTTP 1.1 request. But what is the solution if there is no currently running HTTP 1.1 request and the connection is being kept alive by the client?

A naive solution would be to monitor the HTTP request processes and:

  • if one is running, signal it to include the Connection: close header,
  • if one is not running, send the connection process the {Closed, Socket} message.

However, this can create race conditions:

  • A running HTTP request process might already have sent the response by the time it was signaled to include the Connection: close header. In this case, the connection will not be closed as intended.
  • A connection not currently running any HTTP requests might receive one right after we have sent the connection process the {Close, Socket} message. In this case, the connection will close and discard the just received HTTP request.

Is there a clean and robust way built into Cowboy to handle the above scenarios? Perhaps half closing the connection so that inbound requests are blocked while outgoing responses can still be sent, then letting any current request run to completion and finally closing the connection by sending it the {Close, Socket} message? Or some other way?

Thank you.

@essen
Copy link
Member

essen commented May 31, 2024

You must have the pid of the connection process(es) you want to shut down, and call sys:terminate/2 using it. Cowboy will initiate a graceful connection closure. This works for all protocols (Connection: close is HTTP/1.1 only).

If there's no request ongoing, the connection gets closed immediately. Otherwise, the ongoing request(s) will be the last one(s). Note that for HTTP/1.1, pipelined requests that haven't started being processed will not be handled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants