puma 3.0.0.rc1 → 5.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of puma might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/{History.txt → History.md} +703 -70
- data/LICENSE +23 -20
- data/README.md +173 -163
- data/docs/architecture.md +37 -0
- data/{DEPLOYMENT.md → docs/deployment.md} +28 -6
- data/docs/fork_worker.md +31 -0
- data/docs/images/puma-connection-flow-no-reactor.png +0 -0
- data/docs/images/puma-connection-flow.png +0 -0
- data/docs/images/puma-general-arch.png +0 -0
- data/docs/jungle/README.md +13 -0
- data/docs/jungle/rc.d/README.md +74 -0
- data/docs/jungle/rc.d/puma +61 -0
- data/docs/jungle/rc.d/puma.conf +10 -0
- data/{tools → docs}/jungle/upstart/README.md +0 -0
- data/{tools → docs}/jungle/upstart/puma-manager.conf +0 -0
- data/{tools → docs}/jungle/upstart/puma.conf +1 -1
- data/docs/nginx.md +2 -2
- data/docs/plugins.md +38 -0
- data/docs/restart.md +41 -0
- data/docs/signals.md +57 -3
- data/docs/systemd.md +228 -0
- data/ext/puma_http11/PumaHttp11Service.java +2 -2
- data/ext/puma_http11/extconf.rb +16 -0
- data/ext/puma_http11/http11_parser.c +287 -468
- data/ext/puma_http11/http11_parser.h +1 -0
- data/ext/puma_http11/http11_parser.java.rl +21 -37
- data/ext/puma_http11/http11_parser.rl +10 -9
- data/ext/puma_http11/http11_parser_common.rl +4 -4
- data/ext/puma_http11/mini_ssl.c +159 -10
- data/ext/puma_http11/org/jruby/puma/Http11.java +108 -116
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +99 -132
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +30 -6
- data/ext/puma_http11/puma_http11.c +6 -38
- data/lib/puma.rb +25 -5
- data/lib/puma/accept_nonblock.rb +7 -1
- data/lib/puma/app/status.rb +53 -26
- data/lib/puma/binder.rb +150 -119
- data/lib/puma/cli.rb +56 -38
- data/lib/puma/client.rb +277 -80
- data/lib/puma/cluster.rb +326 -130
- data/lib/puma/commonlogger.rb +21 -20
- data/lib/puma/configuration.rb +160 -161
- data/lib/puma/const.rb +50 -47
- data/lib/puma/control_cli.rb +104 -63
- data/lib/puma/detect.rb +13 -1
- data/lib/puma/dsl.rb +463 -114
- data/lib/puma/events.rb +22 -13
- data/lib/puma/io_buffer.rb +9 -5
- data/lib/puma/jruby_restart.rb +2 -59
- data/lib/puma/launcher.rb +195 -105
- data/lib/puma/minissl.rb +110 -4
- data/lib/puma/minissl/context_builder.rb +76 -0
- data/lib/puma/null_io.rb +9 -14
- data/lib/puma/plugin.rb +32 -12
- data/lib/puma/plugin/tmp_restart.rb +19 -6
- data/lib/puma/rack/builder.rb +7 -5
- data/lib/puma/rack/urlmap.rb +11 -8
- data/lib/puma/rack_default.rb +2 -0
- data/lib/puma/reactor.rb +242 -32
- data/lib/puma/runner.rb +41 -30
- data/lib/puma/server.rb +265 -183
- data/lib/puma/single.rb +22 -63
- data/lib/puma/state_file.rb +9 -2
- data/lib/puma/thread_pool.rb +179 -68
- data/lib/puma/util.rb +3 -11
- data/lib/rack/handler/puma.rb +60 -11
- data/tools/Dockerfile +16 -0
- data/tools/trickletest.rb +1 -2
- metadata +35 -99
- data/COPYING +0 -55
- data/Gemfile +0 -13
- data/Manifest.txt +0 -79
- data/Rakefile +0 -158
- data/docs/config.md +0 -0
- data/ext/puma_http11/io_buffer.c +0 -155
- data/lib/puma/capistrano.rb +0 -94
- data/lib/puma/compat.rb +0 -18
- data/lib/puma/convenient.rb +0 -23
- data/lib/puma/daemon_ext.rb +0 -31
- data/lib/puma/delegation.rb +0 -11
- data/lib/puma/java_io_buffer.rb +0 -45
- data/lib/puma/rack/backports/uri/common_18.rb +0 -56
- data/lib/puma/rack/backports/uri/common_192.rb +0 -52
- data/lib/puma/rack/backports/uri/common_193.rb +0 -29
- data/lib/puma/tcp_logger.rb +0 -32
- data/puma.gemspec +0 -52
- data/tools/jungle/README.md +0 -9
- data/tools/jungle/init.d/README.md +0 -54
- data/tools/jungle/init.d/puma +0 -394
- data/tools/jungle/init.d/run-puma +0 -3
data/lib/puma/detect.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Puma
|
2
4
|
IS_JRUBY = defined?(JRUBY_VERSION)
|
3
5
|
|
@@ -5,7 +7,17 @@ module Puma
|
|
5
7
|
IS_JRUBY
|
6
8
|
end
|
7
9
|
|
10
|
+
IS_WINDOWS = RUBY_PLATFORM =~ /mswin|ming|cygwin/
|
11
|
+
|
8
12
|
def self.windows?
|
9
|
-
|
13
|
+
IS_WINDOWS
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.mri?
|
17
|
+
RUBY_ENGINE == 'ruby' || RUBY_ENGINE.nil?
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.forkable?
|
21
|
+
::Process.respond_to?(:fork)
|
10
22
|
end
|
11
23
|
end
|
data/lib/puma/dsl.rb
CHANGED
@@ -1,27 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'puma/const'
|
4
|
+
|
1
5
|
module Puma
|
2
|
-
# The methods that are available for use inside the
|
6
|
+
# The methods that are available for use inside the configuration file.
|
7
|
+
# These same methods are used in Puma cli and the rack handler
|
8
|
+
# internally.
|
9
|
+
#
|
10
|
+
# Used manually (via CLI class):
|
11
|
+
#
|
12
|
+
# config = Configuration.new({}) do |user_config|
|
13
|
+
# user_config.port 3001
|
14
|
+
# end
|
15
|
+
# config.load
|
16
|
+
#
|
17
|
+
# puts config.options[:binds]
|
18
|
+
# "tcp://127.0.0.1:3001"
|
19
|
+
#
|
20
|
+
# Used to load file:
|
21
|
+
#
|
22
|
+
# $ cat puma_config.rb
|
23
|
+
# port 3002
|
3
24
|
#
|
25
|
+
# config = Configuration.new(config_file: "puma_config.rb")
|
26
|
+
# config.load
|
27
|
+
#
|
28
|
+
# puts config.options[:binds]
|
29
|
+
# # => "tcp://127.0.0.1:3002"
|
30
|
+
#
|
31
|
+
# You can also find many examples being used by the test suite in
|
32
|
+
# +test/config+.
|
4
33
|
class DSL
|
5
34
|
include ConfigDefault
|
6
35
|
|
7
|
-
def self.load(options, cfg, path)
|
8
|
-
d = new(options, cfg)
|
9
|
-
d._load_from(path)
|
10
|
-
|
11
|
-
options
|
12
|
-
ensure
|
13
|
-
d._offer_plugins
|
14
|
-
end
|
15
|
-
|
16
36
|
def initialize(options, config)
|
17
|
-
@config
|
37
|
+
@config = config
|
18
38
|
@options = options
|
19
39
|
|
20
40
|
@plugins = []
|
21
41
|
end
|
22
42
|
|
23
43
|
def _load_from(path)
|
24
|
-
|
44
|
+
if path
|
45
|
+
@path = path
|
46
|
+
instance_eval(File.read(path), path, 1)
|
47
|
+
end
|
25
48
|
ensure
|
26
49
|
_offer_plugins
|
27
50
|
end
|
@@ -37,10 +60,12 @@ module Puma
|
|
37
60
|
@plugins.clear
|
38
61
|
end
|
39
62
|
|
40
|
-
def
|
41
|
-
|
42
|
-
|
43
|
-
|
63
|
+
def set_default_host(host)
|
64
|
+
@options[:default_host] = host
|
65
|
+
end
|
66
|
+
|
67
|
+
def default_host
|
68
|
+
@options[:default_host] || Configuration::DefaultTCPHost
|
44
69
|
end
|
45
70
|
|
46
71
|
def inject(&blk)
|
@@ -57,9 +82,22 @@ module Puma
|
|
57
82
|
@plugins << @config.load_plugin(name)
|
58
83
|
end
|
59
84
|
|
60
|
-
# Use
|
61
|
-
# be the
|
85
|
+
# Use an object or block as the rack application. This allows the
|
86
|
+
# configuration file to be the application itself.
|
62
87
|
#
|
88
|
+
# @example
|
89
|
+
# app do |env|
|
90
|
+
# body = 'Hello, World!'
|
91
|
+
#
|
92
|
+
# [
|
93
|
+
# 200,
|
94
|
+
# {
|
95
|
+
# 'Content-Type' => 'text/plain',
|
96
|
+
# 'Content-Length' => body.length.to_s
|
97
|
+
# },
|
98
|
+
# [body]
|
99
|
+
# ]
|
100
|
+
# end
|
63
101
|
def app(obj=nil, &block)
|
64
102
|
obj ||= block
|
65
103
|
|
@@ -68,9 +106,20 @@ module Puma
|
|
68
106
|
@options[:app] = obj
|
69
107
|
end
|
70
108
|
|
71
|
-
# Start the Puma control rack
|
72
|
-
# with to control the main server.
|
109
|
+
# Start the Puma control rack application on +url+. This application can
|
110
|
+
# be communicated with to control the main server. Additionally, you can
|
111
|
+
# provide an authentication token, so all requests to the control server
|
112
|
+
# will need to include that token as a query parameter. This allows for
|
113
|
+
# simple authentication.
|
114
|
+
#
|
115
|
+
# Check out {Puma::App::Status} to see what the app has available.
|
73
116
|
#
|
117
|
+
# @example
|
118
|
+
# activate_control_app 'unix:///var/run/pumactl.sock'
|
119
|
+
# @example
|
120
|
+
# activate_control_app 'unix:///var/run/pumactl.sock', { auth_token: '12345' }
|
121
|
+
# @example
|
122
|
+
# activate_control_app 'unix:///var/run/pumactl.sock', { no_token: true }
|
74
123
|
def activate_control_app(url="auto", opts={})
|
75
124
|
if url == "auto"
|
76
125
|
path = Configuration.temp_path
|
@@ -81,7 +130,12 @@ module Puma
|
|
81
130
|
end
|
82
131
|
|
83
132
|
if opts[:no_token]
|
84
|
-
|
133
|
+
# We need to use 'none' rather than :none because this value will be
|
134
|
+
# passed on to an instance of OptionParser, which doesn't support
|
135
|
+
# symbols as option values.
|
136
|
+
#
|
137
|
+
# See: https://github.com/puma/puma/issues/1193#issuecomment-305995488
|
138
|
+
auth_token = 'none'
|
85
139
|
else
|
86
140
|
auth_token = opts[:auth_token]
|
87
141
|
auth_token ||= Configuration.random_token
|
@@ -92,76 +146,153 @@ module Puma
|
|
92
146
|
end
|
93
147
|
|
94
148
|
# Load additional configuration from a file
|
149
|
+
# Files get loaded later via Configuration#load
|
95
150
|
def load(file)
|
96
|
-
|
151
|
+
@options[:config_files] ||= []
|
152
|
+
@options[:config_files] << file
|
97
153
|
end
|
98
154
|
|
99
|
-
# Bind the server to +url+. tcp:// and
|
100
|
-
# protocols.
|
155
|
+
# Bind the server to +url+. "tcp://", "unix://" and "ssl://" are the only
|
156
|
+
# accepted protocols. Multiple urls can be bound to, calling `bind` does
|
157
|
+
# not overwrite previous bindings.
|
158
|
+
#
|
159
|
+
# The default is "tcp://0.0.0.0:9292".
|
101
160
|
#
|
161
|
+
# You can use query parameters within the url to specify options:
|
162
|
+
#
|
163
|
+
# - Set the socket backlog depth with +backlog+, default is 1024.
|
164
|
+
# - Set up an SSL certificate with +key+ & +cert+.
|
165
|
+
# - Set whether to optimize for low latency instead of throughput with
|
166
|
+
# +low_latency+, default is to optimize for low latency. This is done
|
167
|
+
# via +Socket::TCP_NODELAY+.
|
168
|
+
# - Set socket permissions with +umask+.
|
169
|
+
#
|
170
|
+
# @example Backlog depth
|
171
|
+
# bind 'unix:///var/run/puma.sock?backlog=512'
|
172
|
+
# @example SSL cert
|
173
|
+
# bind 'ssl://127.0.0.1:9292?key=key.key&cert=cert.pem'
|
174
|
+
# @example Disable optimization for low latency
|
175
|
+
# bind 'tcp://0.0.0.0:9292?low_latency=false'
|
176
|
+
# @example Socket permissions
|
177
|
+
# bind 'unix:///var/run/puma.sock?umask=0111'
|
102
178
|
def bind(url)
|
103
|
-
|
179
|
+
@options[:binds] ||= []
|
180
|
+
@options[:binds] << url
|
181
|
+
end
|
182
|
+
|
183
|
+
def clear_binds!
|
184
|
+
@options[:binds] = []
|
104
185
|
end
|
105
186
|
|
106
187
|
# Define the TCP port to bind to. Use +bind+ for more advanced options.
|
107
188
|
#
|
189
|
+
# @example
|
190
|
+
# port 9292
|
108
191
|
def port(port, host=nil)
|
109
|
-
host ||=
|
192
|
+
host ||= default_host
|
110
193
|
bind "tcp://#{host}:#{port}"
|
111
194
|
end
|
112
195
|
|
196
|
+
# Define how long persistent connections can be idle before Puma closes
|
197
|
+
# them.
|
198
|
+
def persistent_timeout(seconds)
|
199
|
+
@options[:persistent_timeout] = Integer(seconds)
|
200
|
+
end
|
201
|
+
|
202
|
+
# Define how long the tcp socket stays open, if no data has been received.
|
203
|
+
def first_data_timeout(seconds)
|
204
|
+
@options[:first_data_timeout] = Integer(seconds)
|
205
|
+
end
|
206
|
+
|
113
207
|
# Work around leaky apps that leave garbage in Thread locals
|
114
|
-
# across requests
|
115
|
-
#
|
208
|
+
# across requests.
|
116
209
|
def clean_thread_locals(which=true)
|
117
210
|
@options[:clean_thread_locals] = which
|
118
211
|
end
|
119
212
|
|
120
|
-
# Daemonize the server into the background. Highly suggest that
|
121
|
-
# this be combined with +pidfile+ and +stdout_redirect+.
|
122
|
-
def daemonize(which=true)
|
123
|
-
@options[:daemon] = which
|
124
|
-
end
|
125
|
-
|
126
213
|
# When shutting down, drain the accept socket of pending
|
127
|
-
# connections and
|
214
|
+
# connections and process them. This loops over the accept
|
128
215
|
# socket until there are no more read events and then stops
|
129
216
|
# looking and waits for the requests to finish.
|
130
217
|
def drain_on_shutdown(which=true)
|
131
218
|
@options[:drain_on_shutdown] = which
|
132
219
|
end
|
133
220
|
|
134
|
-
# Set the environment in which the
|
221
|
+
# Set the environment in which the rack's app will run. The value must be
|
222
|
+
# a string.
|
223
|
+
#
|
224
|
+
# The default is "development".
|
225
|
+
#
|
226
|
+
# @example
|
227
|
+
# environment 'production'
|
135
228
|
def environment(environment)
|
136
229
|
@options[:environment] = environment
|
137
230
|
end
|
138
231
|
|
232
|
+
# How long to wait for threads to stop when shutting them
|
233
|
+
# down. Defaults to :forever. Specifying :immediately will cause
|
234
|
+
# Puma to kill the threads immediately. Otherwise the value
|
235
|
+
# is the number of seconds to wait.
|
236
|
+
#
|
237
|
+
# Puma always waits a few seconds after killing a thread for it to try
|
238
|
+
# to finish up it's work, even in :immediately mode.
|
239
|
+
def force_shutdown_after(val=:forever)
|
240
|
+
i = case val
|
241
|
+
when :forever
|
242
|
+
-1
|
243
|
+
when :immediately
|
244
|
+
0
|
245
|
+
else
|
246
|
+
Float(val)
|
247
|
+
end
|
248
|
+
|
249
|
+
@options[:force_shutdown_after] = i
|
250
|
+
end
|
251
|
+
|
139
252
|
# Code to run before doing a restart. This code should
|
140
|
-
# close
|
253
|
+
# close log files, database connections, etc.
|
141
254
|
#
|
142
255
|
# This can be called multiple times to add code each time.
|
143
256
|
#
|
257
|
+
# @example
|
258
|
+
# on_restart do
|
259
|
+
# puts 'On restart...'
|
260
|
+
# end
|
144
261
|
def on_restart(&block)
|
145
|
-
|
262
|
+
@options[:on_restart] ||= []
|
263
|
+
@options[:on_restart] << block
|
146
264
|
end
|
147
265
|
|
148
|
-
# Command to use to restart
|
149
|
-
# load
|
150
|
-
# to
|
266
|
+
# Command to use to restart Puma. This should be just how to
|
267
|
+
# load Puma itself (ie. 'ruby -Ilib bin/puma'), not the arguments
|
268
|
+
# to Puma, as those are the same as the original process.
|
151
269
|
#
|
270
|
+
# @example
|
271
|
+
# restart_command '/u/app/lolcat/bin/restart_puma'
|
152
272
|
def restart_command(cmd)
|
153
273
|
@options[:restart_cmd] = cmd.to_s
|
154
274
|
end
|
155
275
|
|
156
|
-
# Store the pid of the server in the file at
|
276
|
+
# Store the pid of the server in the file at "path".
|
277
|
+
#
|
278
|
+
# @example
|
279
|
+
# pidfile '/u/apps/lolcat/tmp/pids/puma.pid'
|
157
280
|
def pidfile(path)
|
158
281
|
@options[:pidfile] = path.to_s
|
159
282
|
end
|
160
283
|
|
161
|
-
# Disable request logging.
|
284
|
+
# Disable request logging, if this isn't used it'll be enabled by default.
|
285
|
+
#
|
286
|
+
# @example
|
287
|
+
# quiet
|
288
|
+
def quiet(which=true)
|
289
|
+
@options[:log_requests] = !which
|
290
|
+
end
|
291
|
+
|
292
|
+
# Enable request logging
|
162
293
|
#
|
163
|
-
def
|
164
|
-
@options[:
|
294
|
+
def log_requests(which=true)
|
295
|
+
@options[:log_requests] = which
|
165
296
|
end
|
166
297
|
|
167
298
|
# Show debugging info
|
@@ -172,26 +303,44 @@ module Puma
|
|
172
303
|
|
173
304
|
# Load +path+ as a rackup file.
|
174
305
|
#
|
306
|
+
# The default is "config.ru".
|
307
|
+
#
|
308
|
+
# @example
|
309
|
+
# rackup '/u/apps/lolcat/config.ru'
|
175
310
|
def rackup(path)
|
176
|
-
@options[:rackup]
|
311
|
+
@options[:rackup] ||= path.to_s
|
177
312
|
end
|
178
313
|
|
179
|
-
|
180
|
-
|
181
|
-
def tcp_mode!
|
182
|
-
@options[:mode] = :tcp
|
314
|
+
def early_hints(answer=true)
|
315
|
+
@options[:early_hints] = answer
|
183
316
|
end
|
184
317
|
|
185
|
-
# Redirect STDOUT and STDERR to files specified.
|
318
|
+
# Redirect STDOUT and STDERR to files specified. The +append+ parameter
|
319
|
+
# specifies whether the output is appended, the default is +false+.
|
320
|
+
#
|
321
|
+
# @example
|
322
|
+
# stdout_redirect '/app/lolcat/log/stdout', '/app/lolcat/log/stderr'
|
323
|
+
# @example
|
324
|
+
# stdout_redirect '/app/lolcat/log/stdout', '/app/lolcat/log/stderr', true
|
186
325
|
def stdout_redirect(stdout=nil, stderr=nil, append=false)
|
187
326
|
@options[:redirect_stdout] = stdout
|
188
327
|
@options[:redirect_stderr] = stderr
|
189
328
|
@options[:redirect_append] = append
|
190
329
|
end
|
191
330
|
|
331
|
+
def log_formatter(&block)
|
332
|
+
@options[:log_formatter] = block
|
333
|
+
end
|
334
|
+
|
192
335
|
# Configure +min+ to be the minimum number of threads to use to answer
|
193
336
|
# requests and +max+ the maximum.
|
194
337
|
#
|
338
|
+
# The default is "0, 16".
|
339
|
+
#
|
340
|
+
# @example
|
341
|
+
# threads 0, 16
|
342
|
+
# @example
|
343
|
+
# threads 5, 5
|
195
344
|
def threads(min, max)
|
196
345
|
min = Integer(min)
|
197
346
|
max = Integer(max)
|
@@ -207,107 +356,213 @@ module Puma
|
|
207
356
|
@options[:max_threads] = max
|
208
357
|
end
|
209
358
|
|
359
|
+
# Instead of "bind 'ssl://127.0.0.1:9292?key=key_path&cert=cert_path'" you
|
360
|
+
# can also use the "ssl_bind" option.
|
361
|
+
#
|
362
|
+
# @example
|
363
|
+
# ssl_bind '127.0.0.1', '9292', {
|
364
|
+
# cert: path_to_cert,
|
365
|
+
# key: path_to_key,
|
366
|
+
# ssl_cipher_filter: cipher_filter, # optional
|
367
|
+
# verify_mode: verify_mode, # default 'none'
|
368
|
+
# }
|
369
|
+
# @example For JRuby additional keys are required: keystore & keystore_pass.
|
370
|
+
# ssl_bind '127.0.0.1', '9292', {
|
371
|
+
# cert: path_to_cert,
|
372
|
+
# key: path_to_key,
|
373
|
+
# ssl_cipher_filter: cipher_filter, # optional
|
374
|
+
# verify_mode: verify_mode, # default 'none'
|
375
|
+
# keystore: path_to_keystore,
|
376
|
+
# keystore_pass: password
|
377
|
+
# }
|
210
378
|
def ssl_bind(host, port, opts)
|
379
|
+
verify = opts.fetch(:verify_mode, 'none').to_s
|
380
|
+
no_tlsv1 = opts.fetch(:no_tlsv1, 'false')
|
381
|
+
no_tlsv1_1 = opts.fetch(:no_tlsv1_1, 'false')
|
382
|
+
ca_additions = "&ca=#{opts[:ca]}" if ['peer', 'force_peer'].include?(verify)
|
383
|
+
|
211
384
|
if defined?(JRUBY_VERSION)
|
212
385
|
keystore_additions = "keystore=#{opts[:keystore]}&keystore-pass=#{opts[:keystore_pass]}"
|
213
|
-
bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}&#{keystore_additions}"
|
386
|
+
bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}&#{keystore_additions}&verify_mode=#{verify}&no_tlsv1=#{no_tlsv1}&no_tlsv1_1=#{no_tlsv1_1}#{ca_additions}"
|
214
387
|
else
|
215
|
-
|
388
|
+
ssl_cipher_filter = "&ssl_cipher_filter=#{opts[:ssl_cipher_filter]}" if opts[:ssl_cipher_filter]
|
389
|
+
bind "ssl://#{host}:#{port}?cert=#{opts[:cert]}&key=#{opts[:key]}#{ssl_cipher_filter}&verify_mode=#{verify}&no_tlsv1=#{no_tlsv1}&no_tlsv1_1=#{no_tlsv1_1}#{ca_additions}"
|
216
390
|
end
|
217
391
|
end
|
218
392
|
|
219
393
|
# Use +path+ as the file to store the server info state. This is
|
220
|
-
# used by pumactl to query and control the server.
|
394
|
+
# used by +pumactl+ to query and control the server.
|
221
395
|
#
|
396
|
+
# @example
|
397
|
+
# state_path '/u/apps/lolcat/tmp/pids/puma.state'
|
222
398
|
def state_path(path)
|
223
399
|
@options[:state] = path.to_s
|
224
400
|
end
|
225
401
|
|
226
|
-
#
|
402
|
+
# Use +permission+ to restrict permissions for the state file.
|
403
|
+
#
|
404
|
+
# @example
|
405
|
+
# state_permission 0600
|
406
|
+
def state_permission(permission)
|
407
|
+
@options[:state_permission] = permission
|
408
|
+
end
|
409
|
+
|
410
|
+
# How many worker processes to run. Typically this is set to
|
411
|
+
# the number of available cores.
|
412
|
+
#
|
413
|
+
# The default is 0.
|
227
414
|
#
|
415
|
+
# @note Cluster mode only.
|
228
416
|
def workers(count)
|
229
417
|
@options[:workers] = count.to_i
|
230
418
|
end
|
231
419
|
|
232
|
-
#
|
420
|
+
# Code to run immediately before master process
|
233
421
|
# forks workers (once on boot). These hooks can block if necessary
|
234
|
-
# to wait for background operations unknown to
|
422
|
+
# to wait for background operations unknown to Puma to finish before
|
235
423
|
# the process terminates.
|
236
|
-
# This can be used to close any connections to remote servers (database,
|
237
|
-
# that were opened when preloading the code
|
424
|
+
# This can be used to close any connections to remote servers (database,
|
425
|
+
# Redis, ...) that were opened when preloading the code.
|
238
426
|
#
|
239
|
-
# This can be called multiple times to add hooks.
|
427
|
+
# This can be called multiple times to add several hooks.
|
240
428
|
#
|
429
|
+
# @note Cluster mode only.
|
430
|
+
# @example
|
431
|
+
# before_fork do
|
432
|
+
# puts "Starting workers..."
|
433
|
+
# end
|
241
434
|
def before_fork(&block)
|
242
|
-
|
435
|
+
@options[:before_fork] ||= []
|
436
|
+
@options[:before_fork] << block
|
243
437
|
end
|
244
438
|
|
245
|
-
#
|
246
|
-
#
|
247
|
-
# can block if necessary to wait for background operations unknown
|
248
|
-
# to puma to finish before the process terminates.
|
439
|
+
# Code to run in a worker when it boots to setup
|
440
|
+
# the process before booting the app.
|
249
441
|
#
|
250
|
-
# This can be called multiple times to add hooks.
|
442
|
+
# This can be called multiple times to add several hooks.
|
251
443
|
#
|
252
|
-
|
253
|
-
|
444
|
+
# @note Cluster mode only.
|
445
|
+
# @example
|
446
|
+
# on_worker_fork do
|
447
|
+
# puts 'Before worker fork...'
|
448
|
+
# end
|
449
|
+
def on_worker_boot(&block)
|
450
|
+
@options[:before_worker_boot] ||= []
|
451
|
+
@options[:before_worker_boot] << block
|
254
452
|
end
|
255
453
|
|
256
|
-
#
|
257
|
-
#
|
454
|
+
# Code to run immediately before a worker shuts
|
455
|
+
# down (after it has finished processing HTTP requests). These hooks
|
456
|
+
# can block if necessary to wait for background operations unknown
|
457
|
+
# to Puma to finish before the process terminates.
|
258
458
|
#
|
259
|
-
# This can be called multiple times to add hooks.
|
459
|
+
# This can be called multiple times to add several hooks.
|
260
460
|
#
|
261
|
-
|
262
|
-
|
461
|
+
# @note Cluster mode only.
|
462
|
+
# @example
|
463
|
+
# on_worker_shutdown do
|
464
|
+
# puts 'On worker shutdown...'
|
465
|
+
# end
|
466
|
+
def on_worker_shutdown(&block)
|
467
|
+
@options[:before_worker_shutdown] ||= []
|
468
|
+
@options[:before_worker_shutdown] << block
|
263
469
|
end
|
264
470
|
|
265
|
-
#
|
266
|
-
#
|
471
|
+
# Code to run in the master right before a worker is started. The worker's
|
472
|
+
# index is passed as an argument.
|
267
473
|
#
|
268
|
-
# This can be called multiple times to add hooks.
|
474
|
+
# This can be called multiple times to add several hooks.
|
269
475
|
#
|
476
|
+
# @note Cluster mode only.
|
477
|
+
# @example
|
478
|
+
# on_worker_fork do
|
479
|
+
# puts 'Before worker fork...'
|
480
|
+
# end
|
270
481
|
def on_worker_fork(&block)
|
271
|
-
|
482
|
+
@options[:before_worker_fork] ||= []
|
483
|
+
@options[:before_worker_fork] << block
|
272
484
|
end
|
273
485
|
|
274
|
-
#
|
275
|
-
#
|
486
|
+
# Code to run in the master after a worker has been started. The worker's
|
487
|
+
# index is passed as an argument.
|
276
488
|
#
|
277
|
-
# This
|
489
|
+
# This is called everytime a worker is to be started.
|
278
490
|
#
|
279
|
-
|
280
|
-
|
491
|
+
# @note Cluster mode only.
|
492
|
+
# @example
|
493
|
+
# after_worker_fork do
|
494
|
+
# puts 'After worker fork...'
|
495
|
+
# end
|
496
|
+
def after_worker_fork(&block)
|
497
|
+
@options[:after_worker_fork] ||= []
|
498
|
+
@options[:after_worker_fork] = block
|
281
499
|
end
|
282
500
|
|
283
|
-
|
284
|
-
def directory(dir)
|
285
|
-
@options[:directory] = dir.to_s
|
501
|
+
alias_method :after_worker_boot, :after_worker_fork
|
286
502
|
|
287
|
-
|
503
|
+
# When `fork_worker` is enabled, code to run in Worker 0
|
504
|
+
# before all other workers are re-forked from this process,
|
505
|
+
# after the server has temporarily stopped serving requests
|
506
|
+
# (once per complete refork cycle).
|
507
|
+
#
|
508
|
+
# This can be used to trigger extra garbage-collection to maximize
|
509
|
+
# copy-on-write efficiency, or close any connections to remote servers
|
510
|
+
# (database, Redis, ...) that were opened while the server was running.
|
511
|
+
#
|
512
|
+
# This can be called multiple times to add several hooks.
|
513
|
+
#
|
514
|
+
# @note Cluster mode with `fork_worker` enabled only.
|
515
|
+
# @example
|
516
|
+
# on_refork do
|
517
|
+
# 3.times {GC.start}
|
518
|
+
# end
|
519
|
+
|
520
|
+
def on_refork(&block)
|
521
|
+
@options[:before_refork] ||= []
|
522
|
+
@options[:before_refork] << block
|
288
523
|
end
|
289
524
|
|
290
|
-
#
|
291
|
-
|
292
|
-
|
525
|
+
# Code to run out-of-band when the worker is idle.
|
526
|
+
# These hooks run immediately after a request has finished
|
527
|
+
# processing and there are no busy threads on the worker.
|
528
|
+
# The worker doesn't accept new requests until this code finishes.
|
529
|
+
#
|
530
|
+
# This hook is useful for running out-of-band garbage collection
|
531
|
+
# or scheduling asynchronous tasks to execute after a response.
|
532
|
+
#
|
533
|
+
# This can be called multiple times to add several hooks.
|
534
|
+
def out_of_band(&block)
|
535
|
+
@options[:out_of_band] ||= []
|
536
|
+
@options[:out_of_band] << block
|
293
537
|
end
|
294
538
|
|
295
|
-
#
|
296
|
-
|
297
|
-
|
539
|
+
# The directory to operate out of.
|
540
|
+
#
|
541
|
+
# The default is the current directory.
|
542
|
+
#
|
543
|
+
# @example
|
544
|
+
# directory '/u/apps/lolcat'
|
545
|
+
def directory(dir)
|
546
|
+
@options[:directory] = dir.to_s
|
298
547
|
end
|
299
548
|
|
300
|
-
#
|
301
|
-
#
|
302
|
-
# with using the phased restart feature, you can't use both.
|
549
|
+
# Preload the application before starting the workers; this conflicts with
|
550
|
+
# phased restart feature. This is off by default.
|
303
551
|
#
|
552
|
+
# @note Cluster mode only.
|
553
|
+
# @example
|
554
|
+
# preload_app!
|
304
555
|
def preload_app!(answer=true)
|
305
556
|
@options[:preload_app] = answer
|
306
557
|
end
|
307
558
|
|
308
|
-
# Use +obj+ or +block+ as the low level error handler. This allows
|
309
|
-
# change the default error on the server.
|
559
|
+
# Use +obj+ or +block+ as the low level error handler. This allows the
|
560
|
+
# configuration file to change the default error on the server.
|
310
561
|
#
|
562
|
+
# @example
|
563
|
+
# lowlevel_error_handler do |err|
|
564
|
+
# [200, {}, ["error page"]]
|
565
|
+
# end
|
311
566
|
def lowlevel_error_handler(obj=nil, &block)
|
312
567
|
obj ||= block
|
313
568
|
raise "Provide either a #call'able or a block" unless obj
|
@@ -317,40 +572,102 @@ module Puma
|
|
317
572
|
# This option is used to allow your app and its gems to be
|
318
573
|
# properly reloaded when not using preload.
|
319
574
|
#
|
320
|
-
# When set, if
|
575
|
+
# When set, if Puma detects that it's been invoked in the
|
321
576
|
# context of Bundler, it will cleanup the environment and
|
322
577
|
# re-run itself outside the Bundler environment, but directly
|
323
578
|
# using the files that Bundler has setup.
|
324
579
|
#
|
325
|
-
# This means that
|
580
|
+
# This means that Puma is now decoupled from your Bundler
|
326
581
|
# context and when each worker loads, it will be loading a
|
327
582
|
# new Bundler context and thus can float around as the release
|
328
583
|
# dictates.
|
584
|
+
#
|
585
|
+
# See also: extra_runtime_dependencies
|
586
|
+
#
|
587
|
+
# @note This is incompatible with +preload_app!+.
|
588
|
+
# @note This is only supported for RubyGems 2.2+
|
329
589
|
def prune_bundler(answer=true)
|
330
590
|
@options[:prune_bundler] = answer
|
331
591
|
end
|
332
592
|
|
333
|
-
#
|
593
|
+
# By default, Puma will raise SignalException when SIGTERM is received. In
|
594
|
+
# environments where SIGTERM is something expected, you can suppress these
|
595
|
+
# with this option.
|
596
|
+
#
|
597
|
+
# This can be useful for example in Kubernetes, where rolling restart is
|
598
|
+
# guaranteed usually on infrastructure level.
|
599
|
+
#
|
600
|
+
# @example
|
601
|
+
# raise_exception_on_sigterm false
|
602
|
+
def raise_exception_on_sigterm(answer=true)
|
603
|
+
@options[:raise_exception_on_sigterm] = answer
|
604
|
+
end
|
605
|
+
|
606
|
+
# When using prune_bundler, if extra runtime dependencies need to be loaded to
|
607
|
+
# initialize your app, then this setting can be used. This includes any Puma plugins.
|
608
|
+
#
|
609
|
+
# Before bundler is pruned, the gem names supplied will be looked up in the bundler
|
610
|
+
# context and then loaded again after bundler is pruned.
|
611
|
+
# Only applies if prune_bundler is used.
|
612
|
+
#
|
613
|
+
# @example
|
614
|
+
# extra_runtime_dependencies ['gem_name_1', 'gem_name_2']
|
615
|
+
# @example
|
616
|
+
# extra_runtime_dependencies ['puma_worker_killer', 'puma-heroku']
|
617
|
+
def extra_runtime_dependencies(answer = [])
|
618
|
+
@options[:extra_runtime_dependencies] = Array(answer)
|
619
|
+
end
|
620
|
+
|
621
|
+
# Additional text to display in process listing.
|
622
|
+
#
|
623
|
+
# If you do not specify a tag, Puma will infer it. If you do not want Puma
|
624
|
+
# to add a tag, use an empty string.
|
625
|
+
#
|
626
|
+
# @example
|
627
|
+
# tag 'app name'
|
628
|
+
# @example
|
629
|
+
# tag ''
|
334
630
|
def tag(string)
|
335
631
|
@options[:tag] = string.to_s
|
336
632
|
end
|
337
633
|
|
338
|
-
#
|
339
|
-
#
|
340
|
-
#
|
341
|
-
#
|
634
|
+
# Verifies that all workers have checked in to the master process within
|
635
|
+
# the given timeout. If not the worker process will be restarted. This is
|
636
|
+
# not a request timeout, it is to protect against a hung or dead process.
|
637
|
+
# Setting this value will not protect against slow requests.
|
638
|
+
#
|
639
|
+
# The minimum value is 6 seconds, the default value is 60 seconds.
|
640
|
+
#
|
641
|
+
# @note Cluster mode only.
|
642
|
+
# @example
|
643
|
+
# worker_timeout 60
|
342
644
|
def worker_timeout(timeout)
|
645
|
+
timeout = Integer(timeout)
|
646
|
+
min = Const::WORKER_CHECK_INTERVAL
|
647
|
+
|
648
|
+
if timeout <= min
|
649
|
+
raise "The minimum worker_timeout must be greater than the worker reporting interval (#{min})"
|
650
|
+
end
|
651
|
+
|
343
652
|
@options[:worker_timeout] = timeout
|
344
653
|
end
|
345
654
|
|
346
|
-
#
|
655
|
+
# Change the default worker timeout for booting.
|
656
|
+
#
|
657
|
+
# If unspecified, this defaults to the value of worker_timeout.
|
658
|
+
#
|
659
|
+
# @note Cluster mode only.
|
660
|
+
# @example:
|
661
|
+
# worker_boot_timeout 60
|
347
662
|
def worker_boot_timeout(timeout)
|
348
|
-
@options[:worker_boot_timeout] = timeout
|
663
|
+
@options[:worker_boot_timeout] = Integer(timeout)
|
349
664
|
end
|
350
665
|
|
351
|
-
#
|
666
|
+
# Set the timeout for worker shutdown
|
667
|
+
#
|
668
|
+
# @note Cluster mode only.
|
352
669
|
def worker_shutdown_timeout(timeout)
|
353
|
-
@options[:worker_shutdown_timeout] = timeout
|
670
|
+
@options[:worker_shutdown_timeout] = Integer(timeout)
|
354
671
|
end
|
355
672
|
|
356
673
|
# When set to true (the default), workers accept all requests
|
@@ -365,7 +682,7 @@ module Puma
|
|
365
682
|
# Note that setting this to false disables HTTP keepalive and
|
366
683
|
# slow clients will occupy a handler thread while the request
|
367
684
|
# is being sent. A reverse proxy, such as nginx, can handle
|
368
|
-
# slow clients and queue requests before they reach
|
685
|
+
# slow clients and queue requests before they reach Puma.
|
369
686
|
def queue_requests(answer=true)
|
370
687
|
@options[:queue_requests] = answer
|
371
688
|
end
|
@@ -377,6 +694,16 @@ module Puma
|
|
377
694
|
@options[:shutdown_debug] = val
|
378
695
|
end
|
379
696
|
|
697
|
+
|
698
|
+
# Attempts to route traffic to less-busy workers by causing them to delay
|
699
|
+
# listening on the socket, allowing workers which are not processing any
|
700
|
+
# requests to pick up new requests first.
|
701
|
+
#
|
702
|
+
# Only works on MRI. For all other interpreters, this setting does nothing.
|
703
|
+
def wait_for_less_busy_worker(val=0.005)
|
704
|
+
@options[:wait_for_less_busy_worker] = val.to_f
|
705
|
+
end
|
706
|
+
|
380
707
|
# Control how the remote address of the connection is set. This
|
381
708
|
# is configurable because to calculate the true socket peer address
|
382
709
|
# a kernel syscall is required which for very fast rack handlers
|
@@ -394,7 +721,7 @@ module Puma
|
|
394
721
|
# is used, allowing headers such as X-Forwarded-For
|
395
722
|
# to be used as well.
|
396
723
|
# * Any string - this allows you to hardcode remote address to any value
|
397
|
-
# you wish. Because
|
724
|
+
# you wish. Because Puma never uses this field anyway, it's
|
398
725
|
# format is entirely in your hands.
|
399
726
|
def set_remote_address(val=:socket)
|
400
727
|
case val
|
@@ -409,7 +736,7 @@ module Puma
|
|
409
736
|
when Hash
|
410
737
|
if hdr = val[:header]
|
411
738
|
@options[:remote_address] = :header
|
412
|
-
@options[:remote_address_header] = "HTTP_" + hdr.upcase.
|
739
|
+
@options[:remote_address_header] = "HTTP_" + hdr.upcase.tr("-", "_")
|
413
740
|
else
|
414
741
|
raise "Invalid value for set_remote_address - #{val.inspect}"
|
415
742
|
end
|
@@ -418,10 +745,32 @@ module Puma
|
|
418
745
|
end
|
419
746
|
end
|
420
747
|
|
421
|
-
|
748
|
+
# When enabled, workers will be forked from worker 0 instead of from the master process.
|
749
|
+
# This option is similar to `preload_app` because the app is preloaded before forking,
|
750
|
+
# but it is compatible with phased restart.
|
751
|
+
#
|
752
|
+
# This option also enables the `refork` command (SIGURG), which optimizes copy-on-write performance
|
753
|
+
# in a running app.
|
754
|
+
#
|
755
|
+
# A refork will automatically trigger once after the specified number of requests
|
756
|
+
# (default 1000), or pass 0 to disable auto refork.
|
757
|
+
#
|
758
|
+
# @note Cluster mode only.
|
759
|
+
def fork_worker(after_requests=1000)
|
760
|
+
@options[:fork_worker] = Integer(after_requests)
|
761
|
+
end
|
422
762
|
|
423
|
-
|
424
|
-
|
763
|
+
# When enabled, Puma will GC 4 times before forking workers.
|
764
|
+
# If available (Ruby 2.7+), we will also call GC.compact.
|
765
|
+
# Not recommended for non-MRI Rubies.
|
766
|
+
#
|
767
|
+
# Based on the work of Koichi Sasada and Aaron Patterson, this option may
|
768
|
+
# decrease memory utilization of preload-enabled cluster-mode Pumas. It will
|
769
|
+
# also increase time to boot and fork. See your logs for details on how much
|
770
|
+
# time this adds to your boot process. For most apps, it will be less than one
|
771
|
+
# second.
|
772
|
+
def nakayoshi_fork(enabled=false)
|
773
|
+
@options[:nakayoshi_fork] = enabled
|
425
774
|
end
|
426
775
|
end
|
427
776
|
end
|