I'm currently in the process of migrating from Puma to Falcon and was looking for a way to throttle the incoming request queue so that my upstream nginx reverse proxy doesn't overload a single thread with Fibers-per-request - someone else had this issue as well.
I'd like to prevent the actual Socket accept from happening until capacity is available:
This may or may not be the best way to go about this and this behavior should probably be customizable, but, I would abstractly like to be able to:
def accept(server, timeout: nil, linger: nil, task: Task.current, **options, &block)
loop do
task.async do
socket, address = server.accept
if linger
socket.setsockopt(SOL_SOCKET, SO_LINGER, 1)
end
if timeout
set_timeout(socket, timeout)
end
# Some sockets, notably SSL sockets, need application level negotiation before they are ready:
if socket.respond_to?(:start)
begin
socket.start
rescue
socket.close
raise
end
end
# It seems like OpenSSL doesn't return the address of the peer when using `accept`, so we need to get it from the socket:
address ||= socket.remote_address
yield socket, address
end
end
end
And then in Falcon, I can pass an Async::Semaphore to the endpoint.
This is currently working with the above monkey-patched into the class (in config/falcon.rb) - maybe there's a cleaner abstraction.
I'm currently in the process of migrating from
PumatoFalconand was looking for a way to throttle the incoming request queue so that my upstreamnginxreverse proxy doesn't overload a single thread with Fibers-per-request - someone else had this issue as well.I'd like to prevent the actual Socket
acceptfrom happening until capacity is available:This may or may not be the best way to go about this and this behavior should probably be customizable, but, I would abstractly like to be able to:
And then in Falcon, I can pass an
Async::Semaphoreto the endpoint.This is currently working with the above monkey-patched into the class (in
config/falcon.rb) - maybe there's a cleaner abstraction.