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
|
||||||

|

|
||||||
|
|
||||||
* Upon startup, Puma listens on a TCP or UNIX socket.
|
* Upon startup, Puma listens on a TCP or UNIX socket.
|
||||||
* The backlog of this socket is configured (with a default of 1024). The
|
* The backlog of this socket is configured with a default of 1024, but the
|
||||||
backlog determines the size of the queue for unaccepted connections.
|
actual backlog value is capped by the `net.core.somaxconn` sysctl value.
|
||||||
Generally, you'll never hit the backlog cap in production. If the backlog is
|
The backlog determines the size of the queue for unaccepted connections. If
|
||||||
full, the operating system refuses new connections.
|
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
|
* 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
|
`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
|
represents the number of connections in the process' `todo` set waiting for
|
||||||
|
|
|
@ -168,9 +168,9 @@ module Puma
|
||||||
params = Util.parse_query uri.query
|
params = Util.parse_query uri.query
|
||||||
|
|
||||||
opt = params.key?('low_latency') && params['low_latency'] != 'false'
|
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|
|
@ios[ios_len..-1].each do |i|
|
||||||
addr = loc_addr_str i
|
addr = loc_addr_str i
|
||||||
|
@ -255,7 +255,8 @@ module Puma
|
||||||
logger.log "* Activated #{str}"
|
logger.log "* Activated #{str}"
|
||||||
else
|
else
|
||||||
ios_len = @ios.length
|
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|
|
@ios[ios_len..-1].each do |i|
|
||||||
addr = loc_addr_str i
|
addr = loc_addr_str i
|
||||||
|
|
|
@ -48,6 +48,8 @@ module Puma
|
||||||
|
|
||||||
ca_additions = "&ca=#{opts[:ca]}" if ['peer', 'force_peer'].include?(verify)
|
ca_additions = "&ca=#{opts[:ca]}" if ['peer', 'force_peer'].include?(verify)
|
||||||
|
|
||||||
|
backlog_str = opts[:backlog] ? "&backlog=#{Integer(opts[:backlog])}" : ''
|
||||||
|
|
||||||
if defined?(JRUBY_VERSION)
|
if defined?(JRUBY_VERSION)
|
||||||
ssl_cipher_list = opts[:ssl_cipher_list] ?
|
ssl_cipher_list = opts[:ssl_cipher_list] ?
|
||||||
"&ssl_cipher_list=#{opts[:ssl_cipher_list]}" : nil
|
"&ssl_cipher_list=#{opts[:ssl_cipher_list]}" : nil
|
||||||
|
@ -55,7 +57,7 @@ module Puma
|
||||||
keystore_additions = "keystore=#{opts[:keystore]}&keystore-pass=#{opts[:keystore_pass]}"
|
keystore_additions = "keystore=#{opts[:keystore]}&keystore-pass=#{opts[:keystore_pass]}"
|
||||||
|
|
||||||
"ssl://#{host}:#{port}?#{keystore_additions}#{ssl_cipher_list}" \
|
"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
|
else
|
||||||
ssl_cipher_filter = opts[:ssl_cipher_filter] ?
|
ssl_cipher_filter = opts[:ssl_cipher_filter] ?
|
||||||
"&ssl_cipher_filter=#{opts[:ssl_cipher_filter]}" : nil
|
"&ssl_cipher_filter=#{opts[:ssl_cipher_filter]}" : nil
|
||||||
|
@ -64,7 +66,7 @@ module Puma
|
||||||
"&verification_flags=#{Array(ary).join ','}" : nil
|
"&verification_flags=#{Array(ary).join ','}" : nil
|
||||||
|
|
||||||
"ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}" \
|
"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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -275,6 +275,24 @@ class TestBinder < TestBinderBase
|
||||||
assert_equal @events.stderr, env_hash["rack.errors"]
|
assert_equal @events.stderr, env_hash["rack.errors"]
|
||||||
end
|
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
|
def test_close_calls_close_on_ios
|
||||||
@mocked_ios = [Minitest::Mock.new, Minitest::Mock.new]
|
@mocked_ios = [Minitest::Mock.new, Minitest::Mock.new]
|
||||||
@mocked_ios.each { |m| m.expect(:close, true) }
|
@mocked_ios.each { |m| m.expect(:close, true) }
|
||||||
|
|
|
@ -98,6 +98,21 @@ class TestConfigFile < TestConfigFileBase
|
||||||
assert_equal [ssl_binding], conf.options[:binds]
|
assert_equal [ssl_binding], conf.options[:binds]
|
||||||
end
|
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
|
def test_ssl_bind_jruby
|
||||||
skip_unless :jruby
|
skip_unless :jruby
|
||||||
skip_unless :ssl
|
skip_unless :ssl
|
||||||
|
|
|
@ -5,7 +5,7 @@ require "puma/thread_pool"
|
||||||
class TestThreadPool < Minitest::Test
|
class TestThreadPool < Minitest::Test
|
||||||
|
|
||||||
def teardown
|
def teardown
|
||||||
@pool.shutdown(1) if @pool
|
@pool.shutdown(1) if defined?(@pool)
|
||||||
end
|
end
|
||||||
|
|
||||||
def new_pool(min, max, &block)
|
def new_pool(min, max, &block)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue