2
2
3
3
namespace Codeages \Plumber ;
4
4
5
+ use swoole_process ;
6
+ use Psr \Log \LoggerInterface ;
5
7
use Pimple \Container ;
6
8
use Monolog \Logger ;
7
9
use Monolog \Handler \StreamHandler ;
8
10
use Monolog \ErrorHandler ;
9
- use Psr \Log \LoggerInterface ;
10
- use swoole_process ;
11
+ use Codeages \RateLimiter \RateLimiter ;
11
12
12
13
class Plumber
13
14
{
@@ -16,8 +17,10 @@ class Plumber
16
17
*/
17
18
protected $ container ;
18
19
20
+ protected $ configFilePath ;
21
+
19
22
/**
20
- * @var boolean
23
+ * @var bool
21
24
*/
22
25
protected $ daemon ;
23
26
@@ -28,15 +31,27 @@ class Plumber
28
31
*/
29
32
protected $ logger ;
30
33
34
+ /**
35
+ * @var RateLimiter
36
+ */
37
+ protected $ limiter ;
38
+
31
39
const ALREADY_RUNNING_ERROR = 1 ;
32
40
33
41
const LOCK_PROCESS_ERROR = 2 ;
34
42
35
- public function __construct (Container $ container )
43
+ public function __construct (Container $ container, $ configFilePath )
36
44
{
37
45
$ container ['run_flag ' ] = new SharedRunFlag ();
38
46
$ this ->locker = new ProcessLocker ($ container ['pid_path ' ]);
47
+ $ this ->limiter = new RateLimiter (
48
+ 'process_recreate ' ,
49
+ 10 ,
50
+ 600 ,
51
+ new \Codeages \RateLimiter \Storage \ArrayStorage ()
52
+ );
39
53
$ this ->container = $ container ;
54
+ $ this ->configFilePath = $ configFilePath ;
40
55
}
41
56
42
57
public function main ($ op )
@@ -70,7 +85,7 @@ protected function start($daemon = true)
70
85
exit (self ::LOCK_PROCESS_ERROR );
71
86
}
72
87
73
- swoole_set_process_name ('plumber: master ' );
88
+ swoole_set_process_name (sprintf ( 'plumber: master (%s) ' , $ this -> configFilePath ) );
74
89
75
90
$ logger = new Logger ('plumber ' );
76
91
if ($ daemon ) {
@@ -81,12 +96,12 @@ protected function start($daemon = true)
81
96
ErrorHandler::register ($ logger );
82
97
$ this ->container ['logger ' ] = $ this ->logger = $ logger ;
83
98
84
- $ this ->workers = $ this ->createWorkers ();
99
+ $ this ->workers = $ this ->startWorkers ();
85
100
$ this ->registerSignal ();
86
101
87
102
foreach ($ this ->workers as $ worker ) {
88
- swoole_event_add ($ worker ->pipe , function ($ pipe ) use ($ worker , $ logger ) {
89
- $ logger ->info (" read from worker: " .$ worker ->read ());
103
+ swoole_event_add ($ worker[ ' process ' ] ->pipe , function ($ pipe ) use ($ worker , $ logger ) {
104
+ $ logger ->info (' read from worker: ' .$ worker[ ' process ' ] ->read ());
90
105
});
91
106
}
92
107
@@ -106,6 +121,7 @@ protected function stop()
106
121
$ pid = $ this ->locker ->getId ();
107
122
if (empty ($ pid )) {
108
123
echo "plumber is not running. \n" ;
124
+
109
125
return ;
110
126
}
111
127
@@ -132,20 +148,23 @@ protected function restart()
132
148
/**
133
149
* 创建队列的监听器.
134
150
*/
135
- private function createWorkers ()
151
+ private function startWorkers ()
136
152
{
137
153
$ workers = [];
138
154
foreach ($ this ->container ['tubes ' ] as $ name => $ options ) {
139
155
for ($ i = 0 ; $ i < $ options ['worker_num ' ]; ++$ i ) {
140
- $ worker = $ this ->createWorker ($ name );
141
- $ workers [$ worker ->pid ] = $ worker ;
156
+ $ worker = $ this ->startWorker ($ name );
157
+ $ workers [$ worker ->pid ] = array (
158
+ 'tube ' => $ name ,
159
+ 'process ' => $ worker ,
160
+ );
142
161
}
143
162
}
144
163
145
164
return $ workers ;
146
165
}
147
166
148
- private function createWorker ($ queueName )
167
+ private function startWorker ($ queueName )
149
168
{
150
169
$ worker = new \swoole_process (function ($ process ) use ($ queueName ) {
151
170
$ process ->name ("plumber: queue ` {$ queueName }` worker " );
@@ -172,18 +191,26 @@ private function registerSignal()
172
191
}
173
192
174
193
if ($ this ->container ['run_flag ' ]->isRuning ()) {
175
- $ newPid = $ this ->workers [$ ret ['pid ' ]]->start ();
176
- $ this ->workers [$ newPid ] = $ this ->workers [$ ret ['pid ' ]];
194
+ $ worker = $ this ->workers [$ ret ['pid ' ]];
177
195
unset($ this ->workers [$ ret ['pid ' ]]);
178
- $ this ->logger ->notice ("process # {$ ret ['pid ' ]} exited, # {$ newPid } is recreated. " , $ ret );
196
+
197
+ $ remainTimes = $ this ->limiter ->check ($ worker ['tube ' ]);
198
+ if ($ remainTimes > 0 ) {
199
+ $ newPid = $ worker ['process ' ]->start ();
200
+ $ this ->workers [$ newPid ] = $ worker ;
201
+ $ this ->logger ->notice ("tube {$ worker ['tube ' ]} process # {$ ret ['pid ' ]} exited, # {$ newPid } is recreated, remain {$ remainTimes } recreated times. . " , $ ret );
202
+ } else {
203
+ $ this ->logger ->notice ("tube {$ worker ['tube ' ]} process # {$ ret ['pid ' ]} exited, reached max recreated times. " , $ ret );
204
+ }
179
205
} else {
180
206
unset($ this ->workers [$ ret ['pid ' ]]);
181
207
$ this ->logger ->info ("process # {$ ret ['pid ' ]} exited. " , $ ret );
182
- if (empty ($ this ->workers )) {
183
- $ this ->locker ->release ();
184
- $ this ->logger ->info ("stoped. " );
185
- swoole_event_exit ();
186
- }
208
+ }
209
+
210
+ if (empty ($ this ->workers )) {
211
+ $ this ->locker ->release ();
212
+ $ this ->logger ->info ('stoped. ' );
213
+ swoole_event_exit ();
187
214
}
188
215
}
189
216
});
0 commit comments