mirror of
https://github.com/puma/puma.git
synced 2022-11-09 13:48:40 -05:00
Allow backlog parameter to be set with ssl_bind DSL (#2780)
Hint about backlog upper limit due to net.core.somaxconn Guard against invalid backlog value
This commit is contained in:
parent
2b6968f9d4
commit
4ac14482f1
6 changed files with 46 additions and 10 deletions
|
@ -31,10 +31,10 @@ _workers_, and we sometimes call the threads created by Puma's
|
|||
![https://bit.ly/2zwzhEK](images/puma-connection-flow.png)
|
||||
|
||||
* Upon startup, Puma listens on a TCP or UNIX socket.
|
||||
* The backlog of this socket is configured (with a default of 1024). The
|
||||
backlog determines the size of the queue for unaccepted connections.
|
||||
Generally, you'll never hit the backlog cap in production. If the backlog is
|
||||
full, the operating system refuses new connections.
|
||||
* The backlog of this socket is configured with a default of 1024, but the
|
||||
actual backlog value is capped by the `net.core.somaxconn` sysctl value.
|
||||
The backlog determines the size of the queue for unaccepted connections. If
|
||||
the backlog is full, the operating system is not accepting new connections.
|
||||
* This socket backlog is distinct from the `backlog` of work as reported by
|
||||
`Puma.stats` or the control server. The backlog that `Puma.stats` refers to
|
||||
represents the number of connections in the process' `todo` set waiting for
|
||||
|
|
|
@ -168,9 +168,9 @@ module Puma
|
|||
params = Util.parse_query uri.query
|
||||
|
||||
opt = params.key?('low_latency') && params['low_latency'] != 'false'
|
||||
bak = params.fetch('backlog', 1024).to_i
|
||||
backlog = params.fetch('backlog', 1024).to_i
|
||||
|
||||
io = add_tcp_listener uri.host, uri.port, opt, bak
|
||||
io = add_tcp_listener uri.host, uri.port, opt, backlog
|
||||
|
||||
@ios[ios_len..-1].each do |i|
|
||||
addr = loc_addr_str i
|
||||
|
@ -255,7 +255,8 @@ module Puma
|
|||
logger.log "* Activated #{str}"
|
||||
else
|
||||
ios_len = @ios.length
|
||||
io = add_ssl_listener uri.host, uri.port, ctx
|
||||
backlog = params.fetch('backlog', 1024).to_i
|
||||
io = add_ssl_listener uri.host, uri.port, ctx, optimize_for_latency = true, backlog
|
||||
|
||||
@ios[ios_len..-1].each do |i|
|
||||
addr = loc_addr_str i
|
||||
|
|
|
@ -48,6 +48,8 @@ module Puma
|
|||
|
||||
ca_additions = "&ca=#{opts[:ca]}" if ['peer', 'force_peer'].include?(verify)
|
||||
|
||||
backlog_str = opts[:backlog] ? "&backlog=#{Integer(opts[:backlog])}" : ''
|
||||
|
||||
if defined?(JRUBY_VERSION)
|
||||
ssl_cipher_list = opts[:ssl_cipher_list] ?
|
||||
"&ssl_cipher_list=#{opts[:ssl_cipher_list]}" : nil
|
||||
|
@ -55,7 +57,7 @@ module Puma
|
|||
keystore_additions = "keystore=#{opts[:keystore]}&keystore-pass=#{opts[:keystore_pass]}"
|
||||
|
||||
"ssl://#{host}:#{port}?#{keystore_additions}#{ssl_cipher_list}" \
|
||||
"&verify_mode=#{verify}#{tls_str}#{ca_additions}"
|
||||
"&verify_mode=#{verify}#{tls_str}#{ca_additions}#{backlog_str}"
|
||||
else
|
||||
ssl_cipher_filter = opts[:ssl_cipher_filter] ?
|
||||
"&ssl_cipher_filter=#{opts[:ssl_cipher_filter]}" : nil
|
||||
|
@ -64,7 +66,7 @@ module Puma
|
|||
"&verification_flags=#{Array(ary).join ','}" : nil
|
||||
|
||||
"ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}" \
|
||||
"#{ssl_cipher_filter}&verify_mode=#{verify}#{tls_str}#{ca_additions}#{v_flags}"
|
||||
"#{ssl_cipher_filter}&verify_mode=#{verify}#{tls_str}#{ca_additions}#{v_flags}#{backlog_str}"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -275,6 +275,24 @@ class TestBinder < TestBinderBase
|
|||
assert_equal @events.stderr, env_hash["rack.errors"]
|
||||
end
|
||||
|
||||
def test_ssl_binder_sets_backlog
|
||||
skip_unless :ssl
|
||||
|
||||
host = '127.0.0.1'
|
||||
port = UniquePort.call
|
||||
tcp_server = TCPServer.new(host, port)
|
||||
tcp_server.define_singleton_method(:listen) do |backlog|
|
||||
Thread.current[:backlog] = backlog
|
||||
super(backlog)
|
||||
end
|
||||
|
||||
TCPServer.stub(:new, tcp_server) do
|
||||
@binder.parse ["ssl://#{host}:#{port}?#{ssl_query}&backlog=2048"], @events
|
||||
end
|
||||
|
||||
assert_equal 2048, Thread.current[:backlog]
|
||||
end
|
||||
|
||||
def test_close_calls_close_on_ios
|
||||
@mocked_ios = [Minitest::Mock.new, Minitest::Mock.new]
|
||||
@mocked_ios.each { |m| m.expect(:close, true) }
|
||||
|
|
|
@ -98,6 +98,21 @@ class TestConfigFile < TestConfigFileBase
|
|||
assert_equal [ssl_binding], conf.options[:binds]
|
||||
end
|
||||
|
||||
def test_ssl_bind_with_backlog
|
||||
skip_unless :ssl
|
||||
|
||||
conf = Puma::Configuration.new do |c|
|
||||
c.ssl_bind "0.0.0.0", "9292", {
|
||||
backlog: "2048",
|
||||
}
|
||||
end
|
||||
|
||||
conf.load
|
||||
|
||||
ssl_binding = conf.options[:binds].first
|
||||
assert ssl_binding.include?('&backlog=2048')
|
||||
end
|
||||
|
||||
def test_ssl_bind_jruby
|
||||
skip_unless :jruby
|
||||
skip_unless :ssl
|
||||
|
|
|
@ -5,7 +5,7 @@ require "puma/thread_pool"
|
|||
class TestThreadPool < Minitest::Test
|
||||
|
||||
def teardown
|
||||
@pool.shutdown(1) if @pool
|
||||
@pool.shutdown(1) if defined?(@pool)
|
||||
end
|
||||
|
||||
def new_pool(min, max, &block)
|
||||
|
|
Loading…
Reference in a new issue