puma 2.8.0 → 2.8.1
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 +4 -4
- data/DEPLOYMENT.md +92 -0
- data/History.txt +16 -0
- data/Manifest.txt +2 -0
- data/README.md +6 -0
- data/bin/puma-wild +17 -0
- data/lib/puma/cli.rb +17 -4
- data/lib/puma/const.rb +4 -4
- data/test/test_http11.rb +6 -7
- metadata +14 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 74aab6aaab377487d53393978bbb59ffae181f66
|
4
|
+
data.tar.gz: 383b6735116a87480a5c73403107de1941da3e99
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2d9663eec2cf39f8e7471937887633cb56a6b8a8989ab3055a8c64497637decc45b56b9d87d2873004ee56665ba9d8386da28c1dd9d216ff9c15942a5961a1e5
|
7
|
+
data.tar.gz: e65857e59cda95b3980761ec5bf8b00f55c55fa1798d6dc43c56c775e84872f7d36d28a5260c232c360f354d4fe865fcc9a76e731b1430e7f26d6291066c60fd
|
data/DEPLOYMENT.md
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
# Deployment engineering for puma
|
2
|
+
|
3
|
+
Puma is software that is expected to be run in a deployed environment eventually.
|
4
|
+
You can centainly use it as your dev server only, but most people look to use
|
5
|
+
it in their production deployments as well.
|
6
|
+
|
7
|
+
To that end, this is meant to serve as a foundation of wisdom how to do that
|
8
|
+
in a way that increases happiness and decreases downtime.
|
9
|
+
|
10
|
+
## Specifying puma
|
11
|
+
|
12
|
+
Most people want to do this by putting `gem "puma"` into their Gemfile, so we'll
|
13
|
+
go ahead and assume that. Go add it now... we'll wait.
|
14
|
+
|
15
|
+
|
16
|
+
Welcome back!
|
17
|
+
|
18
|
+
## Single vs Cluster mode
|
19
|
+
|
20
|
+
Puma was originally concieved as a thread-only webserver, but grew the ability to
|
21
|
+
also use processes in version 2.
|
22
|
+
|
23
|
+
Here are some rules of thumb:
|
24
|
+
|
25
|
+
### MRI
|
26
|
+
|
27
|
+
* Use cluster mode and set the number of workers to 1.5x the number of cpu cores
|
28
|
+
in the machine, minimum 2.
|
29
|
+
* Set the number of threads to desired concurrent requests / number of workers.
|
30
|
+
Puma defaults to 8 and thats a decent number.
|
31
|
+
|
32
|
+
#### Migrating from Unicorn
|
33
|
+
|
34
|
+
* If you're migrating from unicorn though, here are some settings to start with:
|
35
|
+
* Set workers to half the number of unicorn workers you're using
|
36
|
+
* Set threads to 2
|
37
|
+
* Enjoy 50% memory savings
|
38
|
+
* As you grow more confident in the thread safety of your app, you can tune the
|
39
|
+
workers down and the threads up.
|
40
|
+
|
41
|
+
#### Worker utilization
|
42
|
+
|
43
|
+
**How do you know if you're got enough (or too many workers)?**
|
44
|
+
|
45
|
+
A good question. Due to MRI's GIL, only one thread can be executing at a time.
|
46
|
+
But since so many apps are waiting on IO from DBs, etc., they can utilize threads
|
47
|
+
to make better use of the process.
|
48
|
+
|
49
|
+
The rule of thumb is you never want processes that are pegged all the time. This
|
50
|
+
means that there is more work to do that the process can get through. On the other
|
51
|
+
hand, if you have processes that sit around doing nothing, then they're just eating
|
52
|
+
up resources.
|
53
|
+
|
54
|
+
Watching your CPU utilization over time and aim for about 70% on average. This means
|
55
|
+
you've got capacity still but aren't starving threads.
|
56
|
+
|
57
|
+
## Daemonizing
|
58
|
+
|
59
|
+
I prefer to not daemonize my servers and use something like `runit` or `upstrart` to
|
60
|
+
monitor them as child processes. This gives them fast response to crashes and
|
61
|
+
makes it easy to figure out what is going on. Additionally, unlike `unicorn`,
|
62
|
+
puma does not require daemonization to do zero-downtime restarts.
|
63
|
+
|
64
|
+
I see people using daemonization because they start puma directly via capistrano
|
65
|
+
task and thus want it to live on past the `cap deploy`. To this people I said:
|
66
|
+
You need to be using a process monitor. Nothing is making sure puma stays up in
|
67
|
+
this scenario! You're just waiting for something weird to happen, puma to die,
|
68
|
+
and to get paged at 3am. Do yourself a favor, at least the process monitoring
|
69
|
+
your OS comes with, be it `sysvinit`, `upstart`, or `systemd`. Or branch out
|
70
|
+
and use `runit` or hell, even `monit`.
|
71
|
+
|
72
|
+
## Restarting
|
73
|
+
|
74
|
+
You probably will want to deploy some new code at some point, and you'd like
|
75
|
+
puma to start running that new code. Minimizing the amount of time the server
|
76
|
+
is unavailable would be nice as well. Here's how to do it:
|
77
|
+
|
78
|
+
1. Don't use `preload!`. This dirties the master process and means it will have
|
79
|
+
to shutdown all the workers and re-exec itself to get your new code, which means
|
80
|
+
much higher waiting around for things to load.
|
81
|
+
|
82
|
+
1. Use `prune_bundler`. This makes it so that the cluster master will detach itself
|
83
|
+
from a Bundler context on start. This allows the cluster workers to load your app
|
84
|
+
and start a brand new Bundler context within the worker only. This means your
|
85
|
+
master remains pristine and can live on between new releases of your code.
|
86
|
+
|
87
|
+
1. Use phased-restart (`SIGUSR1` or `pumactl phased-restart`). This tells the master
|
88
|
+
to kill off one worker at a time and restart them in your new code. This minimizes
|
89
|
+
downtime and staggers the restart nicely. **WARNING** This means that both your
|
90
|
+
old code and your new code will be running concurrently. Most deployment solutions
|
91
|
+
already cause that, but it's worth warning you about it again. Be careful with your
|
92
|
+
migrations, etc!
|
data/History.txt
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
=== 2.8.1 / 2014-03-06
|
2
|
+
|
3
|
+
* 1 bug fixes:
|
4
|
+
* Run puma-wild with proper deps for prune_bundler
|
5
|
+
|
6
|
+
* 2 doc changes:
|
7
|
+
* Described the configuration file finding behavior added in 2.8.0 and how to disable it.
|
8
|
+
* Start the deployment doc
|
9
|
+
|
10
|
+
* 6 PRs merged:
|
11
|
+
* Merge pull request #471 from arthurnn/fix_test
|
12
|
+
* Merge pull request #485 from joneslee85/patch-9
|
13
|
+
* Merge pull request #486 from joshwlewis/patch-1
|
14
|
+
* Merge pull request #490 from tobinibot/patch-1
|
15
|
+
* Merge pull request #491 from brianknight10/clarify-no-config
|
16
|
+
|
1
17
|
=== 2.8.0 / 2014-02-28
|
2
18
|
|
3
19
|
* 8 minor features:
|
data/Manifest.txt
CHANGED
data/README.md
CHANGED
@@ -149,6 +149,12 @@ You can also provide a configuration file which Puma will use with the `-C` (or
|
|
149
149
|
|
150
150
|
$ puma -C /path/to/config
|
151
151
|
|
152
|
+
By default, if no configuration file is specifed, Puma will look for a configuration file at config/puma.rb. If an environment is specified, either via the `-e` and `--environment` flags, or through the `RACK_ENV` environment variable, the default file location will be config/puma/environment_name.rb.
|
153
|
+
|
154
|
+
If you want to prevent Puma from looking for a configuration file in those locations, provide a dash as the argument to the `-C` (or `--config`) flag:
|
155
|
+
|
156
|
+
$ puma -C "-"
|
157
|
+
|
152
158
|
Take the following [sample configuration](https://github.com/puma/puma/blob/master/examples/config.rb) as inspiration or check out [configuration.rb](https://github.com/puma/puma/blob/master/lib/puma/configuration.rb) to see all available options.
|
153
159
|
|
154
160
|
## Restart
|
data/bin/puma-wild
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Copyright (c) 2014 Evan Phoenix
|
4
|
+
#
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
|
8
|
+
deps = ARGV.shift.split(",").each do |s|
|
9
|
+
name, ver = s.split(":",2)
|
10
|
+
gem name, ver
|
11
|
+
end
|
12
|
+
|
13
|
+
require 'puma/cli'
|
14
|
+
|
15
|
+
cli = Puma::CLI.new ARGV
|
16
|
+
|
17
|
+
cli.run
|
data/lib/puma/cli.rb
CHANGED
@@ -456,14 +456,27 @@ module Puma
|
|
456
456
|
end
|
457
457
|
|
458
458
|
if prune_bundler? && defined?(Bundler)
|
459
|
-
|
459
|
+
puma = Bundler.rubygems.loaded_specs("puma")
|
460
|
+
|
461
|
+
dirs = puma.require_paths.map { |x| File.join(puma.full_gem_path, x) }
|
462
|
+
|
463
|
+
puma_lib_dir = dirs.detect { |x| File.exist? File.join(x, "../bin/puma-wild") }
|
464
|
+
|
465
|
+
deps = puma.runtime_dependencies.map { |d|
|
466
|
+
spec = Bundler.rubygems.loaded_specs(d.name)
|
467
|
+
"#{d.name}:#{spec.version.to_s}"
|
468
|
+
}.join(",")
|
460
469
|
|
461
470
|
if puma_lib_dir
|
462
471
|
log "* Pruning Bundler environment"
|
463
472
|
Bundler.with_clean_env do
|
464
|
-
|
465
|
-
|
466
|
-
|
473
|
+
|
474
|
+
wild = File.expand_path(File.join(puma_lib_dir, "../bin/puma-wild"))
|
475
|
+
|
476
|
+
args = [Gem.ruby] + dirs.map { |x| ["-I", x] }.flatten +
|
477
|
+
[wild, deps] + @original_argv
|
478
|
+
|
479
|
+
Kernel.exec(*args)
|
467
480
|
end
|
468
481
|
end
|
469
482
|
|
data/lib/puma/const.rb
CHANGED
@@ -28,8 +28,8 @@ module Puma
|
|
28
28
|
# too taxing on performance.
|
29
29
|
module Const
|
30
30
|
|
31
|
-
PUMA_VERSION = VERSION = "2.8.
|
32
|
-
CODE_NAME = "Sir Edmund Percival Hillary"
|
31
|
+
PUMA_VERSION = VERSION = "2.8.1".freeze
|
32
|
+
CODE_NAME = "Sir Edmund Percival Hillary".freeze
|
33
33
|
|
34
34
|
FAST_TRACK_KA_TIMEOUT = 0.2
|
35
35
|
|
@@ -58,7 +58,7 @@ module Puma
|
|
58
58
|
PUMA_TMP_BASE = "puma".freeze
|
59
59
|
|
60
60
|
# Indicate that we couldn't parse the request
|
61
|
-
ERROR_400_RESPONSE = "HTTP/1.1 400 Bad Request\r\n\r\n"
|
61
|
+
ERROR_400_RESPONSE = "HTTP/1.1 400 Bad Request\r\n\r\n".freeze
|
62
62
|
|
63
63
|
# The standard empty 404 response for bad requests. Use Error4040Handler for custom stuff.
|
64
64
|
ERROR_404_RESPONSE = "HTTP/1.1 404 Not Found\r\nConnection: close\r\nServer: Puma #{PUMA_VERSION}\r\n\r\nNOT FOUND".freeze
|
@@ -69,7 +69,7 @@ module Puma
|
|
69
69
|
CONTENT_LENGTH = "CONTENT_LENGTH".freeze
|
70
70
|
|
71
71
|
# Indicate that there was an internal error, obviously.
|
72
|
-
ERROR_500_RESPONSE = "HTTP/1.1 500 Internal Server Error\r\n\r\n"
|
72
|
+
ERROR_500_RESPONSE = "HTTP/1.1 500 Internal Server Error\r\n\r\n".freeze
|
73
73
|
|
74
74
|
# A common header for indicating the server is too busy. Not used yet.
|
75
75
|
ERROR_503_RESPONSE = "HTTP/1.1 503 Service Unavailable\r\n\r\nBUSY".freeze
|
data/test/test_http11.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# Copyright (c) 2011 Evan Phoenix
|
2
|
-
# Copyright (c) 2005 Zed A. Shaw
|
2
|
+
# Copyright (c) 2005 Zed A. Shaw
|
3
3
|
|
4
|
-
require '
|
4
|
+
require 'testhelp'
|
5
5
|
|
6
6
|
include Puma
|
7
7
|
|
@@ -24,11 +24,11 @@ class Http11ParserTest < Test::Unit::TestCase
|
|
24
24
|
assert_equal 'GET', req['REQUEST_METHOD']
|
25
25
|
assert_nil req['FRAGMENT']
|
26
26
|
assert_nil req['QUERY_STRING']
|
27
|
-
|
27
|
+
|
28
28
|
parser.reset
|
29
29
|
assert parser.nread == 0, "Number read after reset should be 0"
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
def test_parse_dumbfuck_headers
|
33
33
|
parser = HttpParser.new
|
34
34
|
req = {}
|
@@ -38,7 +38,7 @@ class Http11ParserTest < Test::Unit::TestCase
|
|
38
38
|
assert parser.finished?
|
39
39
|
assert !parser.error?
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
def test_parse_error
|
43
43
|
parser = HttpParser.new
|
44
44
|
req = {}
|
@@ -72,7 +72,7 @@ class Http11ParserTest < Test::Unit::TestCase
|
|
72
72
|
def rand_data(min, max, readable=true)
|
73
73
|
count = min + ((rand(max)+1) *10).to_i
|
74
74
|
res = count.to_s + "/"
|
75
|
-
|
75
|
+
|
76
76
|
if readable
|
77
77
|
res << Digest::SHA1.hexdigest(rand(count * 100).to_s) * (count / 40)
|
78
78
|
else
|
@@ -142,4 +142,3 @@ class Http11ParserTest < Test::Unit::TestCase
|
|
142
142
|
|
143
143
|
end
|
144
144
|
end
|
145
|
-
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: puma
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.8.
|
4
|
+
version: 2.8.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Evan Phoenix
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-03-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -84,6 +84,7 @@ executables:
|
|
84
84
|
extensions:
|
85
85
|
- ext/puma_http11/extconf.rb
|
86
86
|
extra_rdoc_files:
|
87
|
+
- DEPLOYMENT.md
|
87
88
|
- History.txt
|
88
89
|
- Manifest.txt
|
89
90
|
- README.md
|
@@ -95,6 +96,7 @@ extra_rdoc_files:
|
|
95
96
|
- tools/jungle/upstart/README.md
|
96
97
|
files:
|
97
98
|
- COPYING
|
99
|
+
- DEPLOYMENT.md
|
98
100
|
- Gemfile
|
99
101
|
- History.txt
|
100
102
|
- LICENSE
|
@@ -102,6 +104,7 @@ files:
|
|
102
104
|
- README.md
|
103
105
|
- Rakefile
|
104
106
|
- bin/puma
|
107
|
+
- bin/puma-wild
|
105
108
|
- bin/pumactl
|
106
109
|
- docs/config.md
|
107
110
|
- docs/nginx.md
|
@@ -152,14 +155,6 @@ files:
|
|
152
155
|
- lib/puma/util.rb
|
153
156
|
- lib/rack/handler/puma.rb
|
154
157
|
- puma.gemspec
|
155
|
-
- tools/jungle/README.md
|
156
|
-
- tools/jungle/init.d/README.md
|
157
|
-
- tools/jungle/init.d/puma
|
158
|
-
- tools/jungle/init.d/run-puma
|
159
|
-
- tools/jungle/upstart/README.md
|
160
|
-
- tools/jungle/upstart/puma-manager.conf
|
161
|
-
- tools/jungle/upstart/puma.conf
|
162
|
-
- tools/trickletest.rb
|
163
158
|
- test/test_app_status.rb
|
164
159
|
- test/test_cli.rb
|
165
160
|
- test/test_config.rb
|
@@ -177,6 +172,14 @@ files:
|
|
177
172
|
- test/test_thread_pool.rb
|
178
173
|
- test/test_unix_socket.rb
|
179
174
|
- test/test_ws.rb
|
175
|
+
- tools/jungle/README.md
|
176
|
+
- tools/jungle/init.d/README.md
|
177
|
+
- tools/jungle/init.d/puma
|
178
|
+
- tools/jungle/init.d/run-puma
|
179
|
+
- tools/jungle/upstart/README.md
|
180
|
+
- tools/jungle/upstart/puma-manager.conf
|
181
|
+
- tools/jungle/upstart/puma.conf
|
182
|
+
- tools/trickletest.rb
|
180
183
|
homepage: http://puma.io
|
181
184
|
licenses:
|
182
185
|
- BSD
|
@@ -199,7 +202,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
199
202
|
version: '0'
|
200
203
|
requirements: []
|
201
204
|
rubyforge_project: puma
|
202
|
-
rubygems_version: 2.
|
205
|
+
rubygems_version: 2.2.2
|
203
206
|
signing_key:
|
204
207
|
specification_version: 4
|
205
208
|
summary: Puma is a simple, fast, threaded, and highly concurrent HTTP 1.1 server for
|