mirror of
https://github.com/puma/puma.git
synced 2022-11-09 13:48:40 -05:00
Add worker_check_interval configuration option (#2759)
Co-authored-by: Olivier Bellone <olivier@bellone.fr>
This commit is contained in:
parent
909f51e711
commit
1008c36a4a
8 changed files with 43 additions and 8 deletions
|
@ -135,7 +135,7 @@ module Puma
|
|||
def check_workers
|
||||
return if @next_check >= Time.now
|
||||
|
||||
@next_check = Time.now + Const::WORKER_CHECK_INTERVAL
|
||||
@next_check = Time.now + @options[:worker_check_interval]
|
||||
|
||||
timeout_workers
|
||||
wait_workers
|
||||
|
|
|
@ -130,7 +130,7 @@ module Puma
|
|||
Puma::Util.purge_interrupt_queue
|
||||
break
|
||||
end
|
||||
sleep Const::WORKER_CHECK_INTERVAL
|
||||
sleep @options[:worker_check_interval]
|
||||
end
|
||||
end
|
||||
server_thread.join
|
||||
|
|
|
@ -11,6 +11,7 @@ module Puma
|
|||
|
||||
DefaultTCPHost = "0.0.0.0"
|
||||
DefaultTCPPort = 9292
|
||||
DefaultWorkerCheckInterval = 5
|
||||
DefaultWorkerTimeout = 60
|
||||
DefaultWorkerShutdownTimeout = 30
|
||||
end
|
||||
|
@ -195,6 +196,7 @@ module Puma
|
|||
:workers => Integer(ENV['WEB_CONCURRENCY'] || 0),
|
||||
:silence_single_worker_warning => false,
|
||||
:mode => :http,
|
||||
:worker_check_interval => DefaultWorkerCheckInterval,
|
||||
:worker_timeout => DefaultWorkerTimeout,
|
||||
:worker_boot_timeout => DefaultWorkerTimeout,
|
||||
:worker_shutdown_timeout => DefaultWorkerShutdownTimeout,
|
||||
|
|
|
@ -235,9 +235,6 @@ module Puma
|
|||
|
||||
EARLY_HINTS = "rack.early_hints".freeze
|
||||
|
||||
# Minimum interval to checks worker health
|
||||
WORKER_CHECK_INTERVAL = 5
|
||||
|
||||
# Illegal character in the key or value of response header
|
||||
DQUOTE = "\"".freeze
|
||||
HTTP_HEADER_DELIMITER = Regexp.escape("(),/:;<=>?@[]{}\\").freeze
|
||||
|
|
|
@ -736,6 +736,19 @@ module Puma
|
|||
@options[:tag] = string.to_s
|
||||
end
|
||||
|
||||
# Change the default interval for checking workers.
|
||||
#
|
||||
# The default value is 5 seconds.
|
||||
#
|
||||
# @note Cluster mode only.
|
||||
# @example
|
||||
# worker_check_interval 5
|
||||
# @see Puma::Cluster#check_workers
|
||||
#
|
||||
def worker_check_interval(interval)
|
||||
@options[:worker_check_interval] = Integer(interval)
|
||||
end
|
||||
|
||||
# Verifies that all workers have checked in to the master process within
|
||||
# the given timeout. If not the worker process will be restarted. This is
|
||||
# not a request timeout, it is to protect against a hung or dead process.
|
||||
|
@ -750,7 +763,7 @@ module Puma
|
|||
#
|
||||
def worker_timeout(timeout)
|
||||
timeout = Integer(timeout)
|
||||
min = Const::WORKER_CHECK_INTERVAL
|
||||
min = @options.fetch(:worker_check_interval, Puma::ConfigDefault::DefaultWorkerCheckInterval)
|
||||
|
||||
if timeout <= min
|
||||
raise "The minimum worker_timeout must be greater than the worker reporting interval (#{min})"
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require "puma/control_cli"
|
||||
require "json"
|
||||
require "open3"
|
||||
require "io/wait"
|
||||
require_relative 'tmp_path'
|
||||
|
@ -255,6 +256,11 @@ class TestIntegration < Minitest::Test
|
|||
r
|
||||
end
|
||||
|
||||
def get_stats
|
||||
read_pipe = cli_pumactl "stats"
|
||||
JSON.parse(read_pipe.readlines.last)
|
||||
end
|
||||
|
||||
def hot_restart_does_not_drop_connections(num_threads: 1, total_requests: 500)
|
||||
skipped = true
|
||||
skip_if :jruby, suffix: <<-MSG
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
require_relative "helper"
|
||||
require_relative "helpers/integration"
|
||||
|
||||
require "time"
|
||||
|
||||
class TestIntegrationCluster < TestIntegration
|
||||
parallelize_me! if ::Puma.mri?
|
||||
|
||||
|
@ -147,6 +149,21 @@ class TestIntegrationCluster < TestIntegration
|
|||
worker_respawn { |phase0_worker_pids| Process.kill :USR1, @pid }
|
||||
end
|
||||
|
||||
def test_worker_check_interval
|
||||
@control_tcp_port = UniquePort.call
|
||||
worker_check_interval = 1
|
||||
|
||||
cli_server "-w 1 -t 1:1 --control-url tcp://#{HOST}:#{@control_tcp_port} --control-token #{TOKEN} test/rackup/hello.ru", config: "worker_check_interval #{worker_check_interval}"
|
||||
|
||||
sleep worker_check_interval + 1
|
||||
last_checkin_1 = Time.parse(get_stats["worker_status"].first["last_checkin"])
|
||||
|
||||
sleep worker_check_interval + 1
|
||||
last_checkin_2 = Time.parse(get_stats["worker_status"].first["last_checkin"])
|
||||
|
||||
assert(last_checkin_2 > last_checkin_1)
|
||||
end
|
||||
|
||||
def test_worker_boot_timeout
|
||||
timeout = 1
|
||||
worker_timeout(timeout, 2, "worker failed to boot within \\\d+ seconds", "worker_boot_timeout #{timeout}; on_worker_boot { sleep #{timeout + 1} }")
|
||||
|
@ -154,7 +171,7 @@ class TestIntegrationCluster < TestIntegration
|
|||
|
||||
def test_worker_timeout
|
||||
skip 'Thread#name not available' unless Thread.current.respond_to?(:name)
|
||||
timeout = Puma::Const::WORKER_CHECK_INTERVAL + 1
|
||||
timeout = Puma::ConfigDefault::DefaultWorkerCheckInterval + 1
|
||||
worker_timeout(timeout, 1, "worker failed to check in within \\\d+ seconds", <<RUBY)
|
||||
worker_timeout #{timeout}
|
||||
on_worker_boot do
|
||||
|
|
|
@ -148,7 +148,7 @@ class TestLauncher < Minitest::Test
|
|||
end
|
||||
launcher = launcher(conf)
|
||||
Thread.new do
|
||||
sleep Puma::Const::WORKER_CHECK_INTERVAL + 1
|
||||
sleep Puma::ConfigDefault::DefaultWorkerCheckInterval + 1
|
||||
status = Puma.stats_hash[:worker_status].first[:last_status]
|
||||
Puma::Server::STAT_METHODS.each do |stat|
|
||||
assert_includes status, stat
|
||||
|
|
Loading…
Reference in a new issue