rhebok 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Changes +4 -0
- data/README.md +17 -2
- data/lib/rack/handler/rhebok.rb +66 -26
- data/lib/rhebok/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 62de5b0358298e1e28e289b07234b31d1f7ecd45
|
4
|
+
data.tar.gz: 9e1abac8fe69c3876717ef143c3c4f2e5ba8a065
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 67a54bf9fb0820178c01a5a9c60678ce40883f3c47d02ceb4ab8e3bf75c9bd3edf9e77b3e03e86032f0b296fefc42807eecd94beb56e2a5a6fb883bc6a2e9dfa
|
7
|
+
data.tar.gz: 04b4648772b4e6fb723786337c10cdab5170d5357002eef7aa9b1ce6555354f15b33680fd3f88f0748c9612ab691e2b50741efbe4aa063af470d1587c2808833
|
data/Changes
CHANGED
data/README.md
CHANGED
@@ -12,6 +12,7 @@ Rhebok supports following features.
|
|
12
12
|
- prefork and graceful shutdown using prefork_engine
|
13
13
|
- hot deploy and unix domain socket using start_server
|
14
14
|
- only supports HTTP/1.0. But does not support Keepalive.
|
15
|
+
- supports OobGC
|
15
16
|
|
16
17
|
This server is suitable for running HTTP application servers behind a reverse proxy like nginx.
|
17
18
|
|
@@ -33,7 +34,7 @@ Or install it yourself as:
|
|
33
34
|
|
34
35
|
## Usage
|
35
36
|
|
36
|
-
$ rackup -s Rhebok -O Port=8080 -O MaxWorkers=10 -O MaxRequestPerChild=1000 -E production config.ru
|
37
|
+
$ rackup -s Rhebok -O Port=8080 -O MaxWorkers=10 -O MaxRequestPerChild=1000 -O OobGC=yes -E production config.ru
|
37
38
|
|
38
39
|
## Sample configuration with Nginx
|
39
40
|
|
@@ -74,7 +75,7 @@ number of worker processes (default: 10)
|
|
74
75
|
|
75
76
|
### MaxRequestPerChild
|
76
77
|
|
77
|
-
|
78
|
+
Max number of requests to be handled before a worker process exits (default: 1000)
|
78
79
|
If set to `0`. worker never exists. This option looks like Apache's MaxRequestPerChild
|
79
80
|
|
80
81
|
### MinRequestPerChild
|
@@ -85,6 +86,20 @@ if set, randomizes the number of requests handled by a single worker process bet
|
|
85
86
|
|
86
87
|
seconds until timeout (default: 300)
|
87
88
|
|
89
|
+
### OobGC
|
90
|
+
|
91
|
+
Boolean like string. If true, Rhebok execute GC after close client socket. (defualt: false)
|
92
|
+
|
93
|
+
### MaxGCPerRequest
|
94
|
+
|
95
|
+
If [gctools](https://github.com/tmm1/gctools) is available, this option is not used. invoke GC by `GC::OOB.run` after every requests.
|
96
|
+
|
97
|
+
Max number of request before invoking GC (defualt: 5)
|
98
|
+
|
99
|
+
### MinGCPerRequest
|
100
|
+
|
101
|
+
If set, randomizes the number of request before invoking GC between the number of MaxGCPerRequest (defualt: none)
|
102
|
+
|
88
103
|
### SpawnInterval
|
89
104
|
|
90
105
|
if set, worker processes will not be spawned more than once than every given seconds. Also, when SIGHUP is being received, no more than one worker processes will be collected every given seconds. This feature is useful for doing a "slow-restart". See http://blog.kazuhooku.com/2011/04/web-serverstarter-parallelprefork.html for more information. (default: none)
|
data/lib/rack/handler/rhebok.rb
CHANGED
@@ -11,6 +11,13 @@ require 'io/nonblock'
|
|
11
11
|
require 'prefork_engine'
|
12
12
|
require 'rhebok'
|
13
13
|
|
14
|
+
$RACK_HANDLER_RHEBOK_GCTOOL = true
|
15
|
+
begin
|
16
|
+
require 'gctools/oobgc'
|
17
|
+
rescue LoadError
|
18
|
+
$RACK_HANDLER_RHEBOK_GCTOOL = false
|
19
|
+
end
|
20
|
+
|
14
21
|
module Rack
|
15
22
|
module Handler
|
16
23
|
class Rhebok
|
@@ -23,7 +30,10 @@ module Rack
|
|
23
30
|
:MaxRequestPerChild => 1000,
|
24
31
|
:MinRequestPerChild => nil,
|
25
32
|
:SpawnInterval => nil,
|
26
|
-
:ErrRespawnInterval => nil
|
33
|
+
:ErrRespawnInterval => nil,
|
34
|
+
:OobGC => false,
|
35
|
+
:MaxGCPerRequest => 5,
|
36
|
+
:MinGCPerRequest => nil,
|
27
37
|
}
|
28
38
|
NULLIO = StringIO.new("").set_encoding('BINARY')
|
29
39
|
|
@@ -41,16 +51,20 @@ module Rack
|
|
41
51
|
end
|
42
52
|
|
43
53
|
def initialize(options={})
|
54
|
+
if options[:OobGC].instance_of?(String)
|
55
|
+
options[:OobGC] = options[:OobGC].match(/^(true|yes|1)$/i) ? true : false
|
56
|
+
end
|
44
57
|
@options = DEFAULT_OPTIONS.merge(options)
|
58
|
+
p @options[:OobGC]
|
45
59
|
@server = nil
|
46
60
|
@_is_tcp = false
|
47
61
|
@_using_defer_accept = false
|
48
62
|
end
|
49
63
|
|
50
64
|
def setup_listener()
|
51
|
-
if ENV["SERVER_STARTER_PORT"]
|
65
|
+
if ENV["SERVER_STARTER_PORT"]
|
52
66
|
hostport, fd = ENV["SERVER_STARTER_PORT"].split("=",2)
|
53
|
-
if m = hostport.match(/(.*):(\d+)/)
|
67
|
+
if m = hostport.match(/(.*):(\d+)/)
|
54
68
|
@options[:Host] = m[0]
|
55
69
|
@options[:Port] = m[1].to_i
|
56
70
|
else
|
@@ -67,7 +81,7 @@ module Rack
|
|
67
81
|
@_is_tcp = true
|
68
82
|
end
|
69
83
|
|
70
|
-
if RUBY_PLATFORM.match(/linux/) && @_is_tcp == true
|
84
|
+
if RUBY_PLATFORM.match(/linux/) && @_is_tcp == true
|
71
85
|
begin
|
72
86
|
@server.setsockopt(Socket::IPPROTO_TCP, 9, 1)
|
73
87
|
@_using_defer_accept = true
|
@@ -83,49 +97,68 @@ module Rack
|
|
83
97
|
"HUP" => 'TERM',
|
84
98
|
},
|
85
99
|
}
|
86
|
-
if @options[:SpawnInterval]
|
100
|
+
if @options[:SpawnInterval]
|
87
101
|
pm_args["trap_signals"]["USR1"] = ["TERM", @options[:SpawnInterval].to_i]
|
88
102
|
pm_args["spawn_interval"] = @options[:SpawnInterval].to_i
|
89
103
|
end
|
90
|
-
if @options[:ErrRespawnInterval]
|
104
|
+
if @options[:ErrRespawnInterval]
|
91
105
|
pm_args["err_respawn_interval"] = @options[:ErrRespawnInterval].to_i
|
92
106
|
end
|
93
107
|
Signal.trap('INT','SYSTEM_DEFAULT') # XXX
|
94
108
|
|
95
109
|
pe = PreforkEngine.new(pm_args)
|
96
110
|
while !pe.signal_received.match(/^(TERM|USR1)$/)
|
97
|
-
pe.start
|
98
|
-
|
111
|
+
pe.start do
|
112
|
+
srand
|
99
113
|
self.accept_loop(app)
|
100
|
-
|
114
|
+
end
|
101
115
|
end
|
102
116
|
pe.wait_all_children
|
103
117
|
end
|
104
118
|
|
105
119
|
def _calc_reqs_per_child
|
120
|
+
if @options[:MinRequestPerChild] == nil
|
121
|
+
return @options[:MaxRequestPerChild].to_i
|
122
|
+
end
|
106
123
|
max = @options[:MaxRequestPerChild].to_i
|
107
|
-
|
108
|
-
|
109
|
-
|
124
|
+
min = @options[:MinRequestPerChild].to_i
|
125
|
+
if min < max
|
126
|
+
max - ((max - min + 1) * rand).to_i
|
127
|
+
else
|
128
|
+
max
|
110
129
|
end
|
111
|
-
return max
|
112
130
|
end
|
113
131
|
|
132
|
+
def _calc_gc_per_req
|
133
|
+
if @options[:MinGCPerRequest] == nil
|
134
|
+
return @options[:MaxGCPerRequest].to_i
|
135
|
+
end
|
136
|
+
max = @options[:MaxGCPerRequest].to_i
|
137
|
+
min = @options[:MinGCPerRequest].to_i
|
138
|
+
if min < max
|
139
|
+
max - ((max - min + 1) * rand).to_i
|
140
|
+
else
|
141
|
+
max
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
|
114
146
|
def accept_loop(app)
|
115
147
|
@can_exit = true
|
116
148
|
@term_received = 0
|
117
149
|
proc_req_count = 0
|
118
150
|
Signal.trap(:TERM) do
|
119
151
|
@term_received += 1
|
120
|
-
if @can_exit
|
152
|
+
if @can_exit
|
121
153
|
exit!(true)
|
122
154
|
end
|
123
|
-
if @can_exit || @term_received > 1
|
155
|
+
if @can_exit || @term_received > 1
|
124
156
|
exit!(true)
|
125
157
|
end
|
126
158
|
end
|
127
159
|
Signal.trap(:PIPE, "IGNORE")
|
128
160
|
max_reqs = self._calc_reqs_per_child()
|
161
|
+
gc_reqs = self._calc_gc_per_req()
|
129
162
|
fileno = @server.fileno
|
130
163
|
|
131
164
|
env_template = {
|
@@ -144,15 +177,15 @@ module Rack
|
|
144
177
|
@can_exit = true
|
145
178
|
env = env_template.clone
|
146
179
|
connection, buf = ::Rhebok.accept_rack(fileno, @options[:Timeout], @_is_tcp, env)
|
147
|
-
if connection
|
180
|
+
if connection
|
148
181
|
# for tempfile
|
149
182
|
buffer = nil
|
150
183
|
begin
|
151
184
|
proc_req_count += 1
|
152
185
|
@can_exit = false
|
153
186
|
# handle request
|
154
|
-
if env.key?("CONTENT_LENGTH") && env["CONTENT_LENGTH"].to_i > 0
|
155
|
-
cl = env["CONTENT_LENGTH"].to_i
|
187
|
+
if env.key?("CONTENT_LENGTH") && env["CONTENT_LENGTH"].to_i > 0
|
188
|
+
cl = env["CONTENT_LENGTH"].to_i
|
156
189
|
if cl > MAX_MEMORY_BUFFER_SIZE
|
157
190
|
buffer = Tempfile.open('r')
|
158
191
|
buffer.binmode
|
@@ -162,12 +195,12 @@ module Rack
|
|
162
195
|
end
|
163
196
|
while cl > 0
|
164
197
|
chunk = ""
|
165
|
-
if buf.bytesize > 0
|
198
|
+
if buf.bytesize > 0
|
166
199
|
chunk = buf
|
167
200
|
buf = ""
|
168
201
|
else
|
169
202
|
readed = ::Rhebok.read_timeout(connection, chunk, cl, 0, @options[:Timeout])
|
170
|
-
if readed == nil
|
203
|
+
if readed == nil
|
171
204
|
return
|
172
205
|
end
|
173
206
|
end
|
@@ -179,13 +212,13 @@ module Rack
|
|
179
212
|
end
|
180
213
|
|
181
214
|
status_code, headers, body = app.call(env)
|
182
|
-
if body.instance_of?(Array)
|
215
|
+
if body.instance_of?(Array)
|
183
216
|
::Rhebok.write_response(connection, @options[:Timeout], status_code, headers, body)
|
184
217
|
else
|
185
218
|
::Rhebok.write_response(connection, @options[:Timeout], status_code, headers, [])
|
186
219
|
body.each do |part|
|
187
220
|
ret = ::Rhebok.write_all(connection, part, 0, @options[:Timeout])
|
188
|
-
if ret == nil
|
221
|
+
if ret == nil
|
189
222
|
break
|
190
223
|
end
|
191
224
|
end #body.each
|
@@ -196,9 +229,19 @@ module Rack
|
|
196
229
|
buffer.close!
|
197
230
|
end
|
198
231
|
::Rhebok.close_rack(connection)
|
232
|
+
# out of band gc
|
233
|
+
if @options[:OobGC]
|
234
|
+
if $RACK_HANDLER_RHEBOK_GCTOOL
|
235
|
+
GC::OOB.run
|
236
|
+
elsif proc_req_count % gc_reqs == 0
|
237
|
+
disabled = GC.enable
|
238
|
+
GC.start
|
239
|
+
GC.disable if disabled
|
240
|
+
end
|
241
|
+
end
|
199
242
|
end #begin
|
200
243
|
end # accept
|
201
|
-
if @term_received > 0
|
244
|
+
if @term_received > 0
|
202
245
|
exit!(true)
|
203
246
|
end
|
204
247
|
end #while max_reqs
|
@@ -207,6 +250,3 @@ module Rack
|
|
207
250
|
end
|
208
251
|
end
|
209
252
|
end
|
210
|
-
|
211
|
-
|
212
|
-
|
data/lib/rhebok/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rhebok
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Masahiro Nagano
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-12-
|
11
|
+
date: 2014-12-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|