puma 4.3.8 → 5.6.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/History.md +1543 -521
- data/LICENSE +23 -20
- data/README.md +120 -36
- data/bin/puma-wild +3 -9
- data/docs/architecture.md +63 -26
- data/docs/compile_options.md +21 -0
- data/docs/deployment.md +60 -69
- data/docs/fork_worker.md +33 -0
- data/docs/jungle/README.md +9 -0
- data/{tools → docs}/jungle/rc.d/README.md +1 -1
- data/{tools → docs}/jungle/rc.d/puma +2 -2
- data/docs/kubernetes.md +66 -0
- data/docs/nginx.md +1 -1
- data/docs/plugins.md +15 -15
- data/docs/rails_dev_mode.md +28 -0
- data/docs/restart.md +46 -23
- data/docs/signals.md +13 -11
- data/docs/stats.md +142 -0
- data/docs/systemd.md +85 -128
- data/ext/puma_http11/PumaHttp11Service.java +2 -4
- data/ext/puma_http11/ext_help.h +1 -1
- data/ext/puma_http11/extconf.rb +51 -9
- data/ext/puma_http11/http11_parser.c +68 -57
- data/ext/puma_http11/http11_parser.h +1 -1
- data/ext/puma_http11/http11_parser.java.rl +1 -1
- data/ext/puma_http11/http11_parser.rl +1 -1
- data/ext/puma_http11/http11_parser_common.rl +1 -1
- data/ext/puma_http11/mini_ssl.c +295 -124
- data/ext/puma_http11/no_ssl/PumaHttp11Service.java +15 -0
- data/ext/puma_http11/org/jruby/puma/Http11.java +5 -3
- data/ext/puma_http11/org/jruby/puma/Http11Parser.java +51 -51
- data/ext/puma_http11/org/jruby/puma/MiniSSL.java +109 -67
- data/ext/puma_http11/puma_http11.c +32 -51
- data/lib/puma/app/status.rb +50 -36
- data/lib/puma/binder.rb +225 -106
- data/lib/puma/cli.rb +24 -18
- data/lib/puma/client.rb +197 -92
- data/lib/puma/cluster/worker.rb +173 -0
- data/lib/puma/cluster/worker_handle.rb +94 -0
- data/lib/puma/cluster.rb +212 -220
- data/lib/puma/commonlogger.rb +2 -2
- data/lib/puma/configuration.rb +58 -49
- data/lib/puma/const.rb +26 -9
- data/lib/puma/control_cli.rb +99 -76
- data/lib/puma/detect.rb +29 -2
- data/lib/puma/dsl.rb +368 -96
- data/lib/puma/error_logger.rb +104 -0
- data/lib/puma/events.rb +55 -34
- data/lib/puma/io_buffer.rb +9 -2
- data/lib/puma/jruby_restart.rb +0 -58
- data/lib/puma/json_serialization.rb +96 -0
- data/lib/puma/launcher.rb +128 -46
- data/lib/puma/minissl/context_builder.rb +14 -9
- data/lib/puma/minissl.rb +137 -50
- data/lib/puma/null_io.rb +18 -1
- data/lib/puma/plugin.rb +3 -12
- data/lib/puma/queue_close.rb +26 -0
- data/lib/puma/rack/builder.rb +1 -5
- data/lib/puma/reactor.rb +85 -369
- data/lib/puma/request.rb +489 -0
- data/lib/puma/runner.rb +46 -61
- data/lib/puma/server.rb +292 -751
- data/lib/puma/single.rb +9 -65
- data/lib/puma/state_file.rb +48 -8
- data/lib/puma/systemd.rb +46 -0
- data/lib/puma/thread_pool.rb +125 -57
- data/lib/puma/util.rb +32 -4
- data/lib/puma.rb +48 -0
- data/lib/rack/handler/puma.rb +2 -3
- data/lib/rack/version_restriction.rb +15 -0
- data/tools/{docker/Dockerfile → Dockerfile} +1 -1
- metadata +29 -24
- data/docs/tcp_mode.md +0 -96
- data/ext/puma_http11/io_buffer.c +0 -155
- data/ext/puma_http11/org/jruby/puma/IOBuffer.java +0 -72
- data/lib/puma/accept_nonblock.rb +0 -29
- data/lib/puma/tcp_logger.rb +0 -41
- data/tools/jungle/README.md +0 -19
- data/tools/jungle/init.d/README.md +0 -61
- data/tools/jungle/init.d/puma +0 -421
- data/tools/jungle/init.d/run-puma +0 -18
- data/tools/jungle/upstart/README.md +0 -61
- data/tools/jungle/upstart/puma-manager.conf +0 -31
- data/tools/jungle/upstart/puma.conf +0 -69
- /data/{tools → docs}/jungle/rc.d/puma.conf +0 -0
data/LICENSE
CHANGED
@@ -1,26 +1,29 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
BSD 3-Clause License
|
2
|
+
|
3
|
+
Copyright (c) 2019, Evan Phoenix. Some code by Zed Shaw, (c) 2005.
|
3
4
|
All rights reserved.
|
4
5
|
|
5
|
-
Redistribution and use in source and binary forms, with or without
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
6
7
|
modification, are permitted provided that the following conditions are met:
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
10
|
+
list of conditions and the following disclaimer.
|
11
|
+
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
14
|
+
and/or other materials provided with the distribution.
|
15
|
+
|
16
|
+
3. Neither the name of the copyright holder nor the names of its
|
17
|
+
contributors may be used to endorse or promote products derived from
|
18
|
+
this software without specific prior written permission.
|
16
19
|
|
17
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
18
|
-
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19
|
-
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
20
|
-
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
21
|
-
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22
|
-
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
23
|
-
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
24
|
-
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
25
|
-
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
24
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
26
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
28
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
26
29
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
CHANGED
@@ -2,22 +2,21 @@
|
|
2
2
|
<img src="https://puma.io/images/logos/puma-logo-large.png">
|
3
3
|
</p>
|
4
4
|
|
5
|
-
# Puma: A Ruby Web Server Built For
|
6
|
-
|
7
|
-
[](https://gitter.im/puma/puma?utm\_source=badge&utm\_medium=badge&utm\_campaign=pr-badge)
|
8
|
-
[](https://github.com/puma/puma/actions)
|
9
|
-
[](https://travis-ci.org/puma/puma)
|
5
|
+
# Puma: A Ruby Web Server Built For Parallelism
|
10
6
|
|
7
|
+
[](https://github.com/puma/puma/actions?query=workflow%3AMRI)
|
8
|
+
[](https://github.com/puma/puma/actions?query=workflow%3Anon_MRI)
|
11
9
|
[](https://codeclimate.com/github/puma/puma)
|
12
10
|
[](https://dependabot.com/compatibility-score.html?dependency-name=puma&package-manager=bundler&version-scheme=semver)
|
11
|
+
[]( https://stackoverflow.com/questions/tagged/puma )
|
13
12
|
|
14
|
-
Puma is a **simple, fast, multi-threaded, and highly
|
13
|
+
Puma is a **simple, fast, multi-threaded, and highly parallel HTTP 1.1 server for Ruby/Rack applications**.
|
15
14
|
|
16
|
-
## Built For Speed &
|
15
|
+
## Built For Speed & Parallelism
|
17
16
|
|
18
|
-
Puma processes requests using a C-optimized Ragel extension (inherited from Mongrel) that provides fast, accurate HTTP 1.1 protocol parsing in a portable way. Puma then serves the request using a thread pool. Each request is served in a separate thread, so truly
|
17
|
+
Puma processes requests using a C-optimized Ragel extension (inherited from Mongrel) that provides fast, accurate HTTP 1.1 protocol parsing in a portable way. Puma then serves the request using a thread pool. Each request is served in a separate thread, so truly parallel Ruby implementations (JRuby, Rubinius) will use all available CPU cores.
|
19
18
|
|
20
|
-
|
19
|
+
Originally designed as a server for [Rubinius](https://github.com/rubinius/rubinius), Puma also works well with Ruby (MRI) and JRuby.
|
21
20
|
|
22
21
|
On MRI, there is a Global VM Lock (GVL) that ensures only one thread can run Ruby code at a time. But if you're doing a lot of blocking IO (such as HTTP calls to external APIs like Twitter), Puma still improves MRI's throughput by allowing IO waiting to be done in parallel.
|
23
22
|
|
@@ -28,7 +27,16 @@ $ gem install puma
|
|
28
27
|
$ puma
|
29
28
|
```
|
30
29
|
|
31
|
-
Without arguments, puma will look for a rackup (.ru) file in
|
30
|
+
Without arguments, puma will look for a rackup (.ru) file in
|
31
|
+
working directory called `config.ru`.
|
32
|
+
|
33
|
+
## SSL Connection Support
|
34
|
+
|
35
|
+
Puma will install/compile with support for ssl sockets, assuming OpenSSL
|
36
|
+
development files are installed on the system.
|
37
|
+
|
38
|
+
If the system does not have OpenSSL development files installed, Puma will
|
39
|
+
install/compile, but it will not allow ssl connections.
|
32
40
|
|
33
41
|
## Frameworks
|
34
42
|
|
@@ -56,19 +64,29 @@ You can run your Sinatra application with Puma from the command line like this:
|
|
56
64
|
$ ruby app.rb -s Puma
|
57
65
|
```
|
58
66
|
|
59
|
-
|
67
|
+
In order to actually configure Puma using a config file, like `puma.rb`, however, you need to use the `puma` executable. To do this, you must add a rackup file to your Sinatra app:
|
60
68
|
|
61
69
|
```ruby
|
62
|
-
|
63
|
-
|
70
|
+
# config.ru
|
71
|
+
require './app'
|
72
|
+
run Sinatra::Application
|
73
|
+
```
|
74
|
+
|
75
|
+
You can then start your application using:
|
76
|
+
|
77
|
+
```
|
78
|
+
$ bundle exec puma
|
64
79
|
```
|
65
80
|
|
66
81
|
## Configuration
|
67
82
|
|
68
|
-
Puma provides numerous options. Consult `puma -h` (or `puma --help`) for a full list of CLI options, or see [dsl.rb](https://github.com/puma/puma/blob/master/lib/puma/dsl.rb).
|
83
|
+
Puma provides numerous options. Consult `puma -h` (or `puma --help`) for a full list of CLI options, or see `Puma::DSL` or [dsl.rb](https://github.com/puma/puma/blob/master/lib/puma/dsl.rb).
|
69
84
|
|
70
85
|
You can also find several configuration examples as part of the
|
71
|
-
[test](test/config) suite.
|
86
|
+
[test](https://github.com/puma/puma/tree/master/test/config) suite.
|
87
|
+
|
88
|
+
For debugging purposes, you can set the environment variable `PUMA_LOG_CONFIG` with a value
|
89
|
+
and the loaded configuration will be printed as part of the boot process.
|
72
90
|
|
73
91
|
### Thread Pool
|
74
92
|
|
@@ -78,7 +96,7 @@ Puma uses a thread pool. You can set the minimum and maximum number of threads t
|
|
78
96
|
$ puma -t 8:32
|
79
97
|
```
|
80
98
|
|
81
|
-
Puma will automatically scale the number of threads, from the minimum until it caps out at the maximum, based on how much traffic is present. The current default is `0:16`. Feel free to experiment, but be careful not to set the number of maximum threads to a large number, as you may exhaust resources on the system (or cause contention for the Global VM Lock, when using MRI).
|
99
|
+
Puma will automatically scale the number of threads, from the minimum until it caps out at the maximum, based on how much traffic is present. The current default is `0:16` and on MRI is `0:5`. Feel free to experiment, but be careful not to set the number of maximum threads to a large number, as you may exhaust resources on the system (or cause contention for the Global VM Lock, when using MRI).
|
82
100
|
|
83
101
|
Be aware that additionally Puma creates threads on its own for internal purposes (e.g. handling slow clients). So, even if you specify -t 1:1, expect around 7 threads created in your application.
|
84
102
|
|
@@ -119,6 +137,11 @@ This code can be used to setup the process before booting the application, allow
|
|
119
137
|
you to do some Puma-specific things that you don't want to embed in your application.
|
120
138
|
For instance, you could fire a log notification that a worker booted or send something to statsd. This can be called multiple times.
|
121
139
|
|
140
|
+
Constants loaded by your application (such as `Rails`) will not be available in `on_worker_boot`.
|
141
|
+
However, these constants _will_ be available if `preload_app!` is enabled, either explicitly in your `puma` config or automatically if
|
142
|
+
using 2 or more workers in cluster mode.
|
143
|
+
If `preload_app!` is not enabled and 1 worker is used, then `on_worker_boot` will fire, but your app will not be preloaded and constants will not be available.
|
144
|
+
|
122
145
|
`before_fork` specifies a block to be run before workers are forked:
|
123
146
|
|
124
147
|
```ruby
|
@@ -128,14 +151,14 @@ before_fork do
|
|
128
151
|
end
|
129
152
|
```
|
130
153
|
|
131
|
-
Preloading can’t be used with phased restart, since phased restart kills and restarts workers one-by-one, and preload_app copies the code of master into the workers.
|
154
|
+
Preloading can’t be used with phased restart, since phased restart kills and restarts workers one-by-one, and `preload_app!` copies the code of master into the workers.
|
132
155
|
|
133
156
|
### Error handling
|
134
157
|
|
135
158
|
If puma encounters an error outside of the context of your application, it will respond with a 500 and a simple
|
136
|
-
textual error message (see `lowlevel_error`
|
159
|
+
textual error message (see `Puma::Server#lowlevel_error` or [server.rb](https://github.com/puma/puma/blob/master/lib/puma/server.rb)).
|
137
160
|
You can specify custom behavior for this scenario. For example, you can report the error to your third-party
|
138
|
-
error-tracking service (in this example, [rollbar](
|
161
|
+
error-tracking service (in this example, [rollbar](https://rollbar.com)):
|
139
162
|
|
140
163
|
```ruby
|
141
164
|
lowlevel_error_handler do |e|
|
@@ -169,6 +192,38 @@ Need a bit of security? Use SSL sockets:
|
|
169
192
|
```
|
170
193
|
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert'
|
171
194
|
```
|
195
|
+
#### Self-signed SSL certificates (via the [`localhost`] gem, for development use):
|
196
|
+
|
197
|
+
Puma supports the [`localhost`] gem for self-signed certificates. This is particularly useful if you want to use Puma with SSL locally, and self-signed certificates will work for your use-case. Currently, the integration can only be used in MRI.
|
198
|
+
|
199
|
+
Puma automatically configures SSL when the [`localhost`] gem is loaded in a `development` environment:
|
200
|
+
|
201
|
+
```ruby
|
202
|
+
# Add the gem to your Gemfile
|
203
|
+
group(:development) do
|
204
|
+
gem 'localhost'
|
205
|
+
end
|
206
|
+
|
207
|
+
# And require it implicitly using bundler
|
208
|
+
require "bundler"
|
209
|
+
Bundler.require(:default, ENV["RACK_ENV"].to_sym)
|
210
|
+
|
211
|
+
# Alternatively, you can require the gem in config.ru:
|
212
|
+
require './app'
|
213
|
+
require 'localhost'
|
214
|
+
run Sinatra::Application
|
215
|
+
```
|
216
|
+
|
217
|
+
Additionally, Puma must be listening to an SSL socket:
|
218
|
+
|
219
|
+
```shell
|
220
|
+
$ puma -b 'ssl://localhost:9292' config.ru
|
221
|
+
|
222
|
+
# The following options allow you to reach Puma over HTTP as well:
|
223
|
+
$ puma -b ssl://localhost:9292 -b tcp://localhost:9393 config.ru
|
224
|
+
```
|
225
|
+
|
226
|
+
[`localhost`]: https://github.com/socketry/localhost
|
172
227
|
|
173
228
|
#### Controlling SSL Cipher Suites
|
174
229
|
|
@@ -186,7 +241,7 @@ $ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert&ssl_cipher_fil
|
|
186
241
|
$ puma -b 'ssl://127.0.0.1:9292?keystore=path_to_keystore&keystore-pass=keystore_password&ssl_cipher_list=TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA'
|
187
242
|
```
|
188
243
|
|
189
|
-
See https://www.openssl.org/docs/man1.
|
244
|
+
See https://www.openssl.org/docs/man1.1.1/man1/ciphers.html for cipher filter format and full list of cipher suites.
|
190
245
|
|
191
246
|
Disable TLS v1 with the `no_tlsv1` option:
|
192
247
|
|
@@ -194,6 +249,23 @@ Disable TLS v1 with the `no_tlsv1` option:
|
|
194
249
|
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert&no_tlsv1=true'
|
195
250
|
```
|
196
251
|
|
252
|
+
#### Controlling OpenSSL Verification Flags
|
253
|
+
|
254
|
+
To enable verification flags offered by OpenSSL, use `verification_flags` (not available for JRuby):
|
255
|
+
|
256
|
+
```
|
257
|
+
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert&verification_flags=PARTIAL_CHAIN'
|
258
|
+
```
|
259
|
+
|
260
|
+
You can also set multiple verification flags (by separating them with coma):
|
261
|
+
|
262
|
+
```
|
263
|
+
$ puma -b 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert&verification_flags=PARTIAL_CHAIN,CRL_CHECK'
|
264
|
+
```
|
265
|
+
|
266
|
+
List of available flags: `USE_CHECK_TIME`, `CRL_CHECK`, `CRL_CHECK_ALL`, `IGNORE_CRITICAL`, `X509_STRICT`, `ALLOW_PROXY_CERTS`, `POLICY_CHECK`, `EXPLICIT_POLICY`, `INHIBIT_ANY`, `INHIBIT_MAP`, `NOTIFY_POLICY`, `EXTENDED_CRL_SUPPORT`, `USE_DELTAS`, `CHECK_SS_SIGNATURE`, `TRUSTED_FIRST`, `SUITEB_128_LOS_ONLY`, `SUITEB_192_LOS`, `SUITEB_128_LOS`, `PARTIAL_CHAIN`, `NO_ALT_CHAINS`, `NO_CHECK_TIME`
|
267
|
+
(see https://www.openssl.org/docs/manmaster/man3/X509_VERIFY_PARAM_set_hostflags.html#VERIFICATION-FLAGS).
|
268
|
+
|
197
269
|
### Control/Status Server
|
198
270
|
|
199
271
|
Puma has a built-in status and control app that can be used to query and control Puma.
|
@@ -202,7 +274,7 @@ Puma has a built-in status and control app that can be used to query and control
|
|
202
274
|
$ puma --control-url tcp://127.0.0.1:9293 --control-token foo
|
203
275
|
```
|
204
276
|
|
205
|
-
Puma will start the control server on localhost port 9293. All requests to the control server will need to include control token (in this case, `token=foo`) as a query parameter. This allows for simple authentication. Check out [status.rb](https://github.com/puma/puma/blob/master/lib/puma/app/status.rb) to see what the status app has available.
|
277
|
+
Puma will start the control server on localhost port 9293. All requests to the control server will need to include control token (in this case, `token=foo`) as a query parameter. This allows for simple authentication. Check out `Puma::App::Status` or [status.rb](https://github.com/puma/puma/blob/master/lib/puma/app/status.rb) to see what the status app has available.
|
206
278
|
|
207
279
|
You can also interact with the control server via `pumactl`. This command will restart Puma:
|
208
280
|
|
@@ -220,27 +292,31 @@ You can also provide a configuration file with the `-C` (or `--config`) flag:
|
|
220
292
|
$ puma -C /path/to/config
|
221
293
|
```
|
222
294
|
|
223
|
-
If no configuration file is specified, Puma will look for a configuration file at `config/puma.rb`. If an environment is specified
|
295
|
+
If no configuration file is specified, Puma will look for a configuration file at `config/puma.rb`. If an environment is specified (via the `--environment` flag or through the `APP_ENV`, `RACK_ENV`, or `RAILS_ENV` environment variables) Puma looks for a configuration file at `config/puma/<environment_name>.rb` and then falls back to `config/puma.rb`.
|
224
296
|
|
225
|
-
If you want to prevent Puma from looking for a configuration file in those locations,
|
297
|
+
If you want to prevent Puma from looking for a configuration file in those locations, include the `--no-config` flag:
|
226
298
|
|
227
299
|
```
|
300
|
+
$ puma --no-config
|
301
|
+
|
302
|
+
# or
|
303
|
+
|
228
304
|
$ puma -C "-"
|
229
305
|
```
|
230
306
|
|
231
|
-
The other side-effects of setting the environment are whether to show stack traces (in `development` or `test`), and setting RACK_ENV may potentially affect middleware looking for this value to change their behavior. The default puma RACK_ENV value is `development`. You can see all config default values [
|
307
|
+
The other side-effects of setting the environment are whether to show stack traces (in `development` or `test`), and setting RACK_ENV may potentially affect middleware looking for this value to change their behavior. The default puma RACK_ENV value is `development`. You can see all config default values in `Puma::Configuration#puma_default_options` or [configuration.rb](https://github.com/puma/puma/blob/61c6213fbab/lib/puma/configuration.rb#L182-L204).
|
232
308
|
|
233
|
-
Check out [dsl.rb](https://github.com/puma/puma/blob/master/lib/puma/dsl.rb) to see all available options.
|
309
|
+
Check out `Puma::DSL` or [dsl.rb](https://github.com/puma/puma/blob/master/lib/puma/dsl.rb) to see all available options.
|
234
310
|
|
235
311
|
## Restart
|
236
312
|
|
237
313
|
Puma includes the ability to restart itself. When available (MRI, Rubinius, JRuby), Puma performs a "hot restart". This is the same functionality available in *Unicorn* and *NGINX* which keep the server sockets open between restarts. This makes sure that no pending requests are dropped while the restart is taking place.
|
238
314
|
|
239
|
-
For more, see the [
|
315
|
+
For more, see the [Restart documentation](docs/restart.md).
|
240
316
|
|
241
317
|
## Signals
|
242
318
|
|
243
|
-
Puma responds to several signals. A detailed guide to using UNIX signals with Puma can be found in the [
|
319
|
+
Puma responds to several signals. A detailed guide to using UNIX signals with Puma can be found in the [Signals documentation](docs/signals.md).
|
244
320
|
|
245
321
|
## Platform Constraints
|
246
322
|
|
@@ -248,10 +324,11 @@ Some platforms do not support all Puma features.
|
|
248
324
|
|
249
325
|
* **JRuby**, **Windows**: server sockets are not seamless on restart, they must be closed and reopened. These platforms have no way to pass descriptors into a new process that is exposed to Ruby. Also, cluster mode is not supported due to a lack of fork(2).
|
250
326
|
* **Windows**: Cluster mode is not supported due to a lack of fork(2).
|
327
|
+
* **Kubernetes**: The way Kubernetes handles pod shutdowns interacts poorly with server processes implementing graceful shutdown, like Puma. See the [kubernetes section of the documentation](docs/kubernetes.md) for more details.
|
251
328
|
|
252
329
|
## Known Bugs
|
253
330
|
|
254
|
-
For MRI versions 2.2.7, 2.2.8, 2.2.9, 2.2.10 2.3.4 and 2.4.1, you may see ```stream closed in another thread (IOError)```. It may be caused by a [Ruby bug](https://bugs.ruby-lang.org/issues/13632). It can be fixed with the gem https://rubygems.org/gems/stopgap_13632:
|
331
|
+
For MRI versions 2.2.7, 2.2.8, 2.2.9, 2.2.10, 2.3.4 and 2.4.1, you may see ```stream closed in another thread (IOError)```. It may be caused by a [Ruby bug](https://bugs.ruby-lang.org/issues/13632). It can be fixed with the gem https://rubygems.org/gems/stopgap_13632:
|
255
332
|
|
256
333
|
```ruby
|
257
334
|
if %w(2.2.7 2.2.8 2.2.9 2.2.10 2.3.4 2.4.1).include? RUBY_VERSION
|
@@ -266,25 +343,32 @@ end
|
|
266
343
|
|
267
344
|
Puma has support for Capistrano with an [external gem](https://github.com/seuros/capistrano-puma).
|
268
345
|
|
269
|
-
It is common to use process monitors with Puma. Modern process monitors like systemd or
|
346
|
+
It is common to use process monitors with Puma. Modern process monitors like systemd or rc.d
|
270
347
|
provide continuous monitoring and restarts for increased
|
271
348
|
reliability in production environments:
|
272
349
|
|
273
|
-
* [
|
274
|
-
* [
|
350
|
+
* [rc.d](docs/jungle/rc.d/README.md)
|
351
|
+
* [systemd](docs/systemd.md)
|
352
|
+
|
353
|
+
Community guides:
|
275
354
|
|
276
|
-
|
355
|
+
* [Deploying Puma on OpenBSD using relayd and httpd](https://gist.github.com/anon987654321/4532cf8d6c59c1f43ec8973faa031103)
|
356
|
+
|
357
|
+
## Community Extensions
|
358
|
+
|
359
|
+
### Plugins
|
277
360
|
|
278
|
-
* [puma-heroku](https://github.com/evanphx/puma-heroku) — default Puma configuration for running on Heroku
|
279
361
|
* [puma-metrics](https://github.com/harmjanblok/puma-metrics) — export Puma metrics to Prometheus
|
280
362
|
* [puma-plugin-statsd](https://github.com/yob/puma-plugin-statsd) — send Puma metrics to statsd
|
281
363
|
* [puma-plugin-systemd](https://github.com/sj26/puma-plugin-systemd) — deeper integration with systemd for notify, status and watchdog
|
282
364
|
|
283
|
-
|
365
|
+
### Monitoring
|
284
366
|
|
285
|
-
|
367
|
+
* [puma-status](https://github.com/ylecuyer/puma-status) — Monitor CPU/Mem/Load of running puma instances from the CLI
|
368
|
+
|
369
|
+
## Contributing
|
286
370
|
|
287
|
-
[contribution guide]
|
371
|
+
Find details for contributing in the [contribution guide](CONTRIBUTING.md).
|
288
372
|
|
289
373
|
## License
|
290
374
|
|
data/bin/puma-wild
CHANGED
@@ -5,24 +5,18 @@
|
|
5
5
|
|
6
6
|
require 'rubygems'
|
7
7
|
|
8
|
-
|
8
|
+
cli_arg = ARGV.shift
|
9
9
|
|
10
10
|
inc = ""
|
11
11
|
|
12
|
-
if
|
12
|
+
if cli_arg == "-I"
|
13
13
|
inc = ARGV.shift
|
14
14
|
$LOAD_PATH.concat inc.split(":")
|
15
|
-
gems = ARGV.shift
|
16
|
-
end
|
17
|
-
|
18
|
-
gems.split(",").each do |s|
|
19
|
-
name, ver = s.split(":",2)
|
20
|
-
gem name, ver
|
21
15
|
end
|
22
16
|
|
23
17
|
module Puma; end
|
24
18
|
|
25
|
-
Puma.const_set("WILD_ARGS", ["-I", inc
|
19
|
+
Puma.const_set("WILD_ARGS", ["-I", inc])
|
26
20
|
|
27
21
|
require 'puma/cli'
|
28
22
|
|
data/docs/architecture.md
CHANGED
@@ -2,36 +2,73 @@
|
|
2
2
|
|
3
3
|
## Overview
|
4
4
|
|
5
|
-

|
6
6
|
|
7
|
-
Puma is a threaded
|
7
|
+
Puma is a threaded Ruby HTTP application server processing requests across a TCP
|
8
|
+
and/or UNIX socket.
|
8
9
|
|
9
|
-
Workers accept connections from the socket and a thread in the worker's thread pool processes the client's request.
|
10
10
|
|
11
|
-
|
11
|
+
Puma processes (there can be one or many) accept connections from the socket via
|
12
|
+
a thread (in the [`Reactor`](../lib/puma/reactor.rb) class). The connection,
|
13
|
+
once fully buffered and read, moves into the `todo` list, where an available
|
14
|
+
thread will pick it up (in the [`ThreadPool`](../lib/puma/thread_pool.rb)
|
15
|
+
class).
|
12
16
|
|
13
|
-
|
17
|
+
Puma works in two main modes: cluster and single. In single mode, only one Puma
|
18
|
+
process boots. In cluster mode, a `master` process is booted, which prepares
|
19
|
+
(and may boot) the application and then uses the `fork()` system call to create
|
20
|
+
one or more `child` processes. These `child` processes all listen to the same
|
21
|
+
socket. The `master` process does not listen to the socket or process requests -
|
22
|
+
its purpose is primarily to manage and listen for UNIX signals and possibly kill
|
23
|
+
or boot `child` processes.
|
14
24
|
|
15
|
-
|
25
|
+
We sometimes call `child` processes (or Puma processes in `single` mode)
|
26
|
+
_workers_, and we sometimes call the threads created by Puma's
|
27
|
+
[`ThreadPool`](../lib/puma/thread_pool.rb) _worker threads_.
|
28
|
+
|
29
|
+
## How Requests Work
|
30
|
+
|
31
|
+

|
16
32
|
|
17
33
|
* Upon startup, Puma listens on a TCP or UNIX socket.
|
18
|
-
* The backlog of this socket is configured
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
* This
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
* The backlog of this socket is configured with a default of 1024, but the
|
35
|
+
actual backlog value is capped by the `net.core.somaxconn` sysctl value.
|
36
|
+
The backlog determines the size of the queue for unaccepted connections. If
|
37
|
+
the backlog is full, the operating system is not accepting new connections.
|
38
|
+
* This socket backlog is distinct from the `backlog` of work as reported by
|
39
|
+
`Puma.stats` or the control server. The backlog that `Puma.stats` refers to
|
40
|
+
represents the number of connections in the process' `todo` set waiting for
|
41
|
+
a thread from the [`ThreadPool`](../lib/puma/thread_pool.rb).
|
42
|
+
* By default, a single, separate thread (created by the
|
43
|
+
[`Reactor`](../lib/puma/reactor.rb) class) reads and buffers requests from the
|
44
|
+
socket.
|
45
|
+
* When at least one worker thread is available for work, the reactor thread
|
46
|
+
listens to the socket and accepts a request (if one is waiting).
|
47
|
+
* The reactor thread waits for the entire HTTP request to be received.
|
48
|
+
* Puma exposes the time spent waiting for the HTTP request body to be
|
49
|
+
received to the Rack app as `env['puma.request_body_wait']`
|
50
|
+
(milliseconds).
|
51
|
+
* Once fully buffered and received, the connection is pushed into the "todo"
|
52
|
+
set.
|
53
|
+
* Worker threads pop work off the "todo" set for processing.
|
54
|
+
* The worker thread processes the request via `call`ing the configured Rack
|
55
|
+
application. The Rack application generates the HTTP response.
|
56
|
+
* The worker thread writes the response to the connection. While Puma buffers
|
57
|
+
requests via a separate thread, it does not use a separate thread for
|
58
|
+
responses.
|
59
|
+
* Once done, the thread becomes available to process another connection in the
|
60
|
+
"todo" set.
|
61
|
+
|
62
|
+
### `queue_requests`
|
63
|
+
|
64
|
+

|
65
|
+
|
66
|
+
The `queue_requests` option is `true` by default, enabling the separate reactor
|
67
|
+
thread used to buffer requests as described above.
|
68
|
+
|
69
|
+
If set to `false`, this buffer will not be used for connections while waiting
|
70
|
+
for the request to arrive.
|
71
|
+
|
72
|
+
In this mode, when a connection is accepted, it is added to the "todo" queue
|
73
|
+
immediately, and a worker will synchronously do any waiting necessary to read
|
74
|
+
the HTTP request from the socket.
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Compile Options
|
2
|
+
|
3
|
+
There are some `cflags` provided to change Puma's default configuration for its
|
4
|
+
C extension.
|
5
|
+
|
6
|
+
## Query String, `PUMA_QUERY_STRING_MAX_LENGTH`
|
7
|
+
|
8
|
+
By default, the max length of `QUERY_STRING` is `1024 * 10`. But you may want to
|
9
|
+
adjust it to accept longer queries in GET requests.
|
10
|
+
|
11
|
+
For manual install, pass the `PUMA_QUERY_STRING_MAX_LENGTH` option like this:
|
12
|
+
|
13
|
+
```
|
14
|
+
gem install puma -- --with-cflags="-D PUMA_QUERY_STRING_MAX_LENGTH=64000"
|
15
|
+
```
|
16
|
+
|
17
|
+
For Bundler, use its configuration system:
|
18
|
+
|
19
|
+
```
|
20
|
+
bundle config build.puma "--with-cflags='-D PUMA_QUERY_STRING_MAX_LENGTH=64000'"
|
21
|
+
```
|