/
multi_worker_server.rb
136 lines (109 loc) · 2.81 KB
/
multi_worker_server.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#
# ServerEngine
#
# Copyright (C) 2012-2013 Sadayuki Furuhashi
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
module ServerEngine
class MultiWorkerServer < Server
def initialize(worker_module, load_config_proc={}, &block)
@monitors = []
@last_start_worker_time = 0
super(worker_module, load_config_proc, &block)
end
def stop(stop_graceful)
super
@monitors.each do |m|
m.send_stop(stop_graceful) if m
end
nil
end
def restart(stop_graceful)
super
@monitors.each do |m|
m.send_stop(stop_graceful) if m
end
nil
end
def reload
super
@monitors.each_with_index do |m|
m.send_reload if m
end
nil
end
def run
while true
num_alive = keepalive_workers
break if num_alive == 0
wait_tick
end
end
def scale_workers(n)
@num_workers = n
plus = n - @monitors.size
if plus > 0
@monitors.concat Array.new(plus, nil)
end
nil
end
def join_workers
@monitors.each {|m|
m.join if m
}
end
private
def reload_config
super
@start_worker_delay = @config[:start_worker_delay] || 0
@start_worker_delay_rand = @config[:start_worker_delay_rand] || 0.2
scale_workers(@config[:workers] || 1)
nil
end
def wait_tick
sleep 0.5
end
def keepalive_workers
num_alive = 0
@monitors.each_with_index do |m,wid|
if m && m.alive?
# alive
num_alive += 1
elsif wid < @num_workers
# scale up or reboot
unless @stop
@monitors[wid] = delayed_start_worker(wid)
num_alive += 1
end
elsif m
# scale down
@monitors[wid] = nil
end
end
return num_alive
end
def delayed_start_worker(wid)
if @start_worker_delay > 0
delay = @start_worker_delay +
Kernel.rand * @start_worker_delay * @start_worker_delay_rand -
@start_worker_delay * @start_worker_delay_rand / 2
now = Time.now.to_f
wait = delay - (now - @last_start_worker_time)
sleep wait if wait > 0
@last_start_worker_time = now
end
start_worker(wid)
end
end
end