I have tried to put server.close after server.listen which don’t close and remain listening for request, how do I really shutdown the server gracefully?
server.listen
is a blocking call and waits until listen
finishes - which it does only when crashing.
spawn server.listen
is what you might need to be able to call server.close
at some point.
I’m not sure how it handles if I have run twice on the code below on the terminal/console to create 2 processes in macOS.
Tested on wrk benchmark on 127.0.0.1:8081, the first process will be stress load until kill -1 1234
the 2nd process will take over incoming request but wrk appear to show error requests which the 1st process wasn’t shutdown gracefully, I think my code need more robust solutions or any better way to manage it?
require "http"
server1 = HTTP::Server.new do |ctx|
ctx.response.status_code = 200
ctx.response.headers["Content-Type"] = "text/plain"
ctx.response.puts "Hello World! #1"
end
server1.bind_tcp host: "127.0.0.1", port: 8081, reuse_port: true
Signal::HUP.trap do
puts "Will stop in moment! ({active_requests} active requests)"
sleep 1.seconds
server1.close
end
spawn { server1.listen }
sleep
I would say reuse_port is not the best way to go about here. My first pick would be a load balancer like haproxy or nginx in front of both servers.
Having said that, the root of the issue as I see it is the word “gracefully”. server1.close
tries to do that:
# Gracefully terminates the server. It will process currently accepted
# requests, but it won't accept new connections.
def close
raise "Can't close server, it's already closed" if closed?
@closed = true
@processor.close
@sockets.each do |socket|
socket.close
rescue
# ignore exception on close
end
@listening = false
@sockets.clear
end
It doesn’t accept new connections, but it doesn’t close the sockets immediately either. You have to decide do you want the existing clients to be served before the new instance takes the port over, or do you want to close the sockets immediately, breaking all current requests. Both options are not entirely graceful.