serverengine 1.5.9 → 1.5.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/Changelog +9 -0
- data/README.md +82 -34
- data/lib/serverengine.rb +1 -0
- data/lib/serverengine/multi_spawn_server.rb +87 -0
- data/lib/serverengine/multi_thread_server.rb +1 -0
- data/lib/serverengine/process_manager.rb +1 -1
- data/lib/serverengine/server.rb +3 -0
- data/lib/serverengine/supervisor.rb +2 -0
- data/lib/serverengine/version.rb +1 -1
- data/lib/serverengine/worker.rb +9 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
OWNiN2U5ZGRhMjk1NGI1ZDAxNmY3OWE5OTZkMWI0ZDI5Nzg3NDQzYw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MTFlMzk4MjE1ZDdhZDdiMWRkNzg2YmY3M2MxMWU5MjY5OWU3ZTFkNw==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NGI0NjQyMWMxNTJmMzBlYTFhM2YwM2U2OGUwMWM4OGMzMzI4ODA4YmQ4ZGI3
|
10
|
+
ZjE5MTUzMzk2YTJkYWVjNTNkMzU0ZjkwZWU1ODY2M2VkNDUwZmM5ZjgxY2Qw
|
11
|
+
NWUyYzhmOWIyYTA0ZGQ3ZGUwYWMwYTNjODZlNzAyM2IwNWFlNDI=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ZTRjMWQ0N2E4OTI5ZGUzOTZjYTU3ZTI5MzVmYzdiMjBjOGU5Yjg4NzBjOGE0
|
14
|
+
OGEwYzM2MDNiMTc5ZmE1NDQ4MjkwNGVhZjFiZDIxMzEzMTBiNzRkOWU0ZTM0
|
15
|
+
NmFkZWM1NTgyYjBmOGRhYzU1NmZjNzJiOGM5ZDYyNjBiYzQxNDI=
|
data/Changelog
CHANGED
@@ -1,4 +1,13 @@
|
|
1
1
|
|
2
|
+
2014-10-27 version 1.5.10:
|
3
|
+
|
4
|
+
* Added worker_type=spawn (experimental)
|
5
|
+
* Fixed Worker#config to reference Server#config so that Worker#reload reads
|
6
|
+
the new config reloaded by Server#reload (=ConfigLoader#reload_config) in
|
7
|
+
worker_type=thread and embedded
|
8
|
+
* Server#stop, #restart and #reload show a debug log message
|
9
|
+
|
10
|
+
|
2
11
|
2014-07-24 version 1.5.9:
|
3
12
|
|
4
13
|
* Fixed DaemonLogger#reoepen! on Ruby >= 2.1.0
|
data/README.md
CHANGED
@@ -50,9 +50,9 @@ module MyWorker
|
|
50
50
|
end
|
51
51
|
|
52
52
|
se = ServerEngine.create(nil, MyWorker, {
|
53
|
-
:
|
54
|
-
:
|
55
|
-
:
|
53
|
+
daemonize: true,
|
54
|
+
log: 'myserver.log',
|
55
|
+
pid_path: 'myserver.pid',
|
56
56
|
})
|
57
57
|
se.run
|
58
58
|
```
|
@@ -66,11 +66,11 @@ Simply set **worker_type=process** or **worker_type=thread** parameter, and set
|
|
66
66
|
|
67
67
|
```ruby
|
68
68
|
se = ServerEngine.create(nil, MyWorker, {
|
69
|
-
:
|
70
|
-
:
|
71
|
-
:
|
72
|
-
:
|
73
|
-
:
|
69
|
+
daemonize: true,
|
70
|
+
log: 'myserver.log',
|
71
|
+
pid_path: 'myserver.pid',
|
72
|
+
worker_type: 'process',
|
73
|
+
workers: 4,
|
74
74
|
})
|
75
75
|
se.run
|
76
76
|
```
|
@@ -111,13 +111,54 @@ module MyWorker
|
|
111
111
|
end
|
112
112
|
|
113
113
|
se = ServerEngine.create(MyServer, MyWorker, {
|
114
|
-
:
|
115
|
-
:
|
116
|
-
:
|
117
|
-
:
|
118
|
-
:
|
119
|
-
:
|
120
|
-
:
|
114
|
+
daemonize: true,
|
115
|
+
log: 'myserver.log',
|
116
|
+
pid_path: 'myserver.pid',
|
117
|
+
worker_type: 'process',
|
118
|
+
workers: 4,
|
119
|
+
bind: '0.0.0.0',
|
120
|
+
port: 9071,
|
121
|
+
})
|
122
|
+
se.run
|
123
|
+
```
|
124
|
+
|
125
|
+
|
126
|
+
### Multiprocess server on Windows and JRuby platform
|
127
|
+
|
128
|
+
Above **worker_type=process** depends on `fork` system call, which doesn't work on Windows or JRuby platform.
|
129
|
+
ServerEngine provides **worker_type=spawn** for those platforms (This is still EXPERIMENTAL). However, unfortunately, you need to implement different worker module because `worker_type=spawn` is not compatible with **worker_type=process** in terms of API.
|
130
|
+
|
131
|
+
What you need to implement at least to use worker_type=spawn is `spawn(process_manager)` method. You will call `process_manager.spawn` at the method, where `spawn` is same with `Process.spawn` excepting return value.
|
132
|
+
|
133
|
+
```ruby
|
134
|
+
module MyWorker
|
135
|
+
def spawn(process_manager)
|
136
|
+
env = {
|
137
|
+
'SERVER_ENGINE_CONFIG' => config.to_json
|
138
|
+
}
|
139
|
+
script = %[
|
140
|
+
require 'serverengine'
|
141
|
+
require 'json'
|
142
|
+
|
143
|
+
conf = JSON.parse(ENV['SERVER_ENGINE_CONFIG'], symbolize_names: true)
|
144
|
+
logger = ServerEngine::DaemonLogger.new(conf[:log] || STDOUT, conf)
|
145
|
+
|
146
|
+
@stop = false
|
147
|
+
trap(:SIGTERM) { @stop = true }
|
148
|
+
trap(:SIGINT) { @stop = true }
|
149
|
+
|
150
|
+
until @stop
|
151
|
+
logger.info 'Awesome work!'
|
152
|
+
sleep 1
|
153
|
+
end
|
154
|
+
]
|
155
|
+
process_manager.spawn(env, "ruby", "-e", script)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
se = ServerEngine.create(nil, MyWorker, {
|
160
|
+
worker_type: 'spawn',
|
161
|
+
log: 'myserver.log',
|
121
162
|
})
|
122
163
|
se.run
|
123
164
|
```
|
@@ -129,10 +170,10 @@ ServerEngine logger rotates logs by 1MB and keeps 5 generations by default.
|
|
129
170
|
|
130
171
|
```ruby
|
131
172
|
se = ServerEngine.create(MyServer, MyWorker, {
|
132
|
-
:
|
133
|
-
:
|
134
|
-
:
|
135
|
-
:
|
173
|
+
log: 'myserver.log',
|
174
|
+
log_level: 'debug',
|
175
|
+
log_rotate_age: 5,
|
176
|
+
log_rotate_size: 1*1024*1024,
|
136
177
|
})
|
137
178
|
se.run
|
138
179
|
```
|
@@ -154,9 +195,9 @@ Supervisor process runs as the parent process of the server process and monitor
|
|
154
195
|
|
155
196
|
```ruby
|
156
197
|
se = ServerEngine.create(nil, MyWorker, {
|
157
|
-
:
|
158
|
-
:
|
159
|
-
:
|
198
|
+
daemonize: true,
|
199
|
+
pid_path: 'myserver.pid',
|
200
|
+
supervisor: true, # enable supervisor process
|
160
201
|
})
|
161
202
|
se.run
|
162
203
|
```
|
@@ -229,8 +270,8 @@ end
|
|
229
270
|
|
230
271
|
se = ServerEngine.create(nil, MyWorker) do
|
231
272
|
YAML.load_file("config.yml").merge({
|
232
|
-
:
|
233
|
-
:
|
273
|
+
daemonize: true,
|
274
|
+
worker_type: 'process',
|
234
275
|
})
|
235
276
|
end
|
236
277
|
se.run
|
@@ -264,8 +305,8 @@ end
|
|
264
305
|
|
265
306
|
se = ServerEngine.create(nil, MyWorker) do
|
266
307
|
YAML.load_file(config).merge({
|
267
|
-
:
|
268
|
-
:
|
308
|
+
daemonize: true,
|
309
|
+
worker_type: 'process'
|
269
310
|
})
|
270
311
|
end
|
271
312
|
se.run
|
@@ -276,13 +317,16 @@ se.run
|
|
276
317
|
|
277
318
|
### Worker module
|
278
319
|
|
320
|
+
Available methods are different depending on `worker_type`.
|
321
|
+
|
279
322
|
- interface
|
280
323
|
- `initialize` is called in the parent process (or thread) in contrast to the other methods
|
281
|
-
- `before_fork` is called before fork for each worker process
|
282
|
-
- `run` is the required method
|
283
|
-
- `
|
284
|
-
- `
|
285
|
-
- `
|
324
|
+
- `before_fork` is called before fork for each worker process [`worker_type` = "thread", "process"]
|
325
|
+
- `run` is the required method for `worker_type` = "embedded", "thread", "process"
|
326
|
+
- `spawn(process_manager)` is the required method for `worker_type` = "spawn". Should call `process_manager.spawn([env,] command... [,options])`.
|
327
|
+
- `stop` is called when TERM signal is received [`worker_type` = "embedded", "thread", "process"]
|
328
|
+
- `reload` is called when USR2 signal is received [`worker_type` = "embedded", "thread", "process"]
|
329
|
+
- `after_start` is called after starting the worker process in the parent process (or thread) [`worker_type` = "thread", "process", "spawn"]
|
286
330
|
- api
|
287
331
|
- `server` server instance
|
288
332
|
- `config` configuration
|
@@ -296,7 +340,7 @@ se.run
|
|
296
340
|
- `initialize` is called in the parent process in contrast to the other methods
|
297
341
|
- `before_run` is called before starting workers
|
298
342
|
- `after_run` is called before shutting down
|
299
|
-
- `after_start` is called after starting the server process in the parent process (available
|
343
|
+
- `after_start` is called after starting the server process in the parent process (available if `supervisor` parameter is true)
|
300
344
|
- hook points (call `super` in these methods)
|
301
345
|
- `reload_config`
|
302
346
|
- `stop(stop_graceful)`
|
@@ -312,7 +356,8 @@ ServerEngine supports 3 worker types:
|
|
312
356
|
|
313
357
|
- **embedded**: uses a thread to run worker module (default). This type doesn't support immediate shutdown or immediate restart.
|
314
358
|
- **thread**: uses threads to run worker modules. This type doesn't support immediate shutdown or immediate restart.
|
315
|
-
- **process**: uses processes to run worker modules. This type doesn't work on
|
359
|
+
- **process**: uses processes to run worker modules. This type doesn't work on Windows or JRuby platform.
|
360
|
+
- **spawn**: uses processes to run worker modules. This type works on Windows and JRuby platform but available interface of worker module is limited (See also Worker module section).
|
316
361
|
|
317
362
|
|
318
363
|
## Signals
|
@@ -352,7 +397,7 @@ Graceful shutdown and restart call `Worker#stop` method and wait for completion
|
|
352
397
|
- **workers** sets number of workers (default: 1) [dynamic reloadable]
|
353
398
|
- **start_worker_delay** sets wait time before starting a new worker (default: 0) [dynamic reloadable]
|
354
399
|
- **start_worker_delay_rand** randomizes start_worker_delay at this ratio (default: 0.2) [dynamic reloadable]
|
355
|
-
- Multiprocess server: available only when `worker_type` is "process"
|
400
|
+
- Multiprocess server: available only when `worker_type` is "process"
|
356
401
|
- **worker_process_name** changes process name ($0) of workers [dynamic reloadable]
|
357
402
|
- **worker_heartbeat_interval** sets interval of heartbeats in seconds (default: 1.0) [dynamic reloadable]
|
358
403
|
- **worker_heartbeat_timeout** sets timeout of heartbeat in seconds (default: 180) [dynamic reloadable]
|
@@ -362,6 +407,9 @@ Graceful shutdown and restart call `Worker#stop` method and wait for completion
|
|
362
407
|
- **worker_immediate_kill_interval** sets the first interval of QUIT signals in seconds (default: 10) [dynamic reloadable]
|
363
408
|
- **worker_immediate_kill_interval_increment** sets increment of QUIT signal interval in seconds (default: 10) [dynamic reloadable]
|
364
409
|
- **worker_immediate_kill_timeout** sets promotion timeout from QUIT to KILL signal in seconds. -1 means no timeout (default: 600) [dynamic reloadable]
|
410
|
+
- Multiprocess spawn server: available only when `worker_type` is "spawn"
|
411
|
+
- all parameters of multiprocess server excepting worker_process_name
|
412
|
+
- **worker_reload_signal** sets the signal to notice configuration reload to a spawned process. Set nil to disable (default: nil)
|
365
413
|
- Logger
|
366
414
|
- **log** sets path to log file. Set "-" for STDOUT (default: STDERR) [dynamic reloadable]
|
367
415
|
- **log_level** log level: trace, debug, info, warn, error or fatal. (default: debug) [dynamic reloadable]
|
data/lib/serverengine.rb
CHANGED
@@ -33,6 +33,7 @@ module ServerEngine
|
|
33
33
|
:MultiWorkerServer => 'serverengine/multi_worker_server',
|
34
34
|
:MultiProcessServer => 'serverengine/multi_process_server',
|
35
35
|
:MultiThreadServer => 'serverengine/multi_thread_server',
|
36
|
+
:MultiSpawnServer => 'serverengine/multi_spawn_server',
|
36
37
|
:ProcessManager => 'serverengine/process_manager',
|
37
38
|
:Worker => 'serverengine/worker',
|
38
39
|
:VERSION => 'serverengine/version',
|
@@ -0,0 +1,87 @@
|
|
1
|
+
#
|
2
|
+
# ServerEngine
|
3
|
+
#
|
4
|
+
# Copyright (C) 2012-2013 Sadayuki Furuhashi
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
module ServerEngine
|
19
|
+
|
20
|
+
class MultiSpawnServer < MultiWorkerServer
|
21
|
+
def initialize(worker_module, load_config_proc={}, &block)
|
22
|
+
@pm = ProcessManager.new(
|
23
|
+
auto_tick: false,
|
24
|
+
graceful_kill_signal: Daemon::Signals::GRACEFUL_STOP,
|
25
|
+
immediate_kill_signal: Daemon::Signals::IMMEDIATE_STOP,
|
26
|
+
enable_heartbeat: false,
|
27
|
+
)
|
28
|
+
|
29
|
+
super(worker_module, load_config_proc, &block)
|
30
|
+
|
31
|
+
@reload_signal = @config[:worker_reload_signal]
|
32
|
+
end
|
33
|
+
|
34
|
+
def run
|
35
|
+
super
|
36
|
+
ensure
|
37
|
+
@pm.close
|
38
|
+
end
|
39
|
+
|
40
|
+
def logger=(logger)
|
41
|
+
super
|
42
|
+
@pm.logger = logger
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def reload_config
|
48
|
+
super
|
49
|
+
|
50
|
+
@pm.configure(@config, prefix: 'worker_')
|
51
|
+
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
|
55
|
+
def start_worker(wid)
|
56
|
+
w = create_worker(wid)
|
57
|
+
|
58
|
+
w.before_fork
|
59
|
+
begin
|
60
|
+
pmon = w.spawn(@pm)
|
61
|
+
ensure
|
62
|
+
w.after_start
|
63
|
+
end
|
64
|
+
|
65
|
+
return WorkerMonitor.new(w, wid, pmon, @reload_signal)
|
66
|
+
end
|
67
|
+
|
68
|
+
def wait_tick
|
69
|
+
@pm.tick(0.5)
|
70
|
+
end
|
71
|
+
|
72
|
+
class WorkerMonitor < MultiProcessServer::WorkerMonitor
|
73
|
+
def initialize(worker, wid, pmon, reload_signal)
|
74
|
+
super(worker, wid, pmon)
|
75
|
+
@reload_signal = reload_signal
|
76
|
+
end
|
77
|
+
|
78
|
+
def send_reload
|
79
|
+
if @reload_signal
|
80
|
+
@pmon.send_signal(@reload_signal) if @pmon
|
81
|
+
end
|
82
|
+
nil
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
data/lib/serverengine/server.rb
CHANGED
@@ -40,6 +40,7 @@ module ServerEngine
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def stop(stop_graceful)
|
43
|
+
@logger.info "Received #{stop_graceful ? 'graceful' : 'immediate'} stop" if @logger
|
43
44
|
@stop = true
|
44
45
|
nil
|
45
46
|
end
|
@@ -48,12 +49,14 @@ module ServerEngine
|
|
48
49
|
end
|
49
50
|
|
50
51
|
def restart(stop_graceful)
|
52
|
+
@logger.info "Received #{stop_graceful ? 'graceful' : 'immediate'} restart" if @logger
|
51
53
|
reload_config
|
52
54
|
@logger.reopen! if @logger
|
53
55
|
nil
|
54
56
|
end
|
55
57
|
|
56
58
|
def reload
|
59
|
+
@logger.info "Received reload" if @logger
|
57
60
|
reload_config
|
58
61
|
@logger.reopen! if @logger
|
59
62
|
nil
|
data/lib/serverengine/version.rb
CHANGED
data/lib/serverengine/worker.rb
CHANGED
@@ -20,13 +20,16 @@ module ServerEngine
|
|
20
20
|
class Worker
|
21
21
|
def initialize(server, worker_id)
|
22
22
|
@server = server
|
23
|
-
@config = server.config
|
24
23
|
@logger = @server.logger
|
25
24
|
@worker_id = worker_id
|
26
25
|
end
|
27
26
|
|
28
27
|
attr_reader :server, :worker_id
|
29
|
-
attr_accessor :
|
28
|
+
attr_accessor :logger
|
29
|
+
|
30
|
+
def config
|
31
|
+
@server.config
|
32
|
+
end
|
30
33
|
|
31
34
|
def before_fork
|
32
35
|
end
|
@@ -35,6 +38,10 @@ module ServerEngine
|
|
35
38
|
raise NoMethodError, "Worker#run method is not implemented"
|
36
39
|
end
|
37
40
|
|
41
|
+
def spawn(process_manager)
|
42
|
+
raise NoMethodError, "Worker#spawn(process_manager) method is required for worker_type=spawn"
|
43
|
+
end
|
44
|
+
|
38
45
|
def stop
|
39
46
|
end
|
40
47
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: serverengine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.5.
|
4
|
+
version: 1.5.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sadayuki Furuhashi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-10-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sigdump
|
@@ -75,6 +75,7 @@ files:
|
|
75
75
|
- lib/serverengine/daemon_logger.rb
|
76
76
|
- lib/serverengine/embedded_server.rb
|
77
77
|
- lib/serverengine/multi_process_server.rb
|
78
|
+
- lib/serverengine/multi_spawn_server.rb
|
78
79
|
- lib/serverengine/multi_thread_server.rb
|
79
80
|
- lib/serverengine/multi_worker_server.rb
|
80
81
|
- lib/serverengine/process_manager.rb
|