-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathWorker.php
More file actions
197 lines (159 loc) · 6.53 KB
/
Copy pathWorker.php
File metadata and controls
197 lines (159 loc) · 6.53 KB
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
<?php
namespace TphpWorker;
use TphpWorker\Server\TcpServer;
use TphpWorker\Event\EventLoop;
use TphpWorker\Process\SignalHandler;
use TphpWorker\Process\ProcessManager;
class Worker {
// 服务器列表:array<int, TcpServer>
public array $servers = [];
// 事件循环
public EventLoop $loop;
// 信号处理器
public SignalHandler $signalHandler;
// 进程管理器
public ProcessManager $processManager;
// 是否运行中
public bool $running = false;
// 工作进程数(所有 server 的最大值,用于决定是否启用多进程)
public int $maxProcessCount = 1;
// 是否为子进程(由 fork 设置)
public bool $isChild = false;
// 子进程的工作进程索引
public int $workerIndex = 0;
public function __construct() {
$this->loop = new EventLoop();
$this->signalHandler = new SignalHandler($this->loop);
$this->processManager = new ProcessManager();
}
// 添加服务器
public function addServer(TcpServer $server): void {
$this->servers[] = $server;
// 更新最大进程数
if ($server->processCount > $this->maxProcessCount) {
$this->maxProcessCount = $server->processCount;
}
}
// 启动所有服务器并进入事件循环
// 若 maxProcessCount > 1 且 pcntl 可用,则 fork 子进程
public function runAll(): void {
if (count($this->servers) === 0) {
echo sprintf("Worker: no servers registered\n");
return;
}
echo sprintf("Worker: starting %d server(s), max processes=%d\n",
count($this->servers), $this->maxProcessCount);
// 判断是否需要多进程
$needFork = $this->maxProcessCount > 1 && $this->processManager->pcntlAvailable;
if ($needFork) {
$this->runMultiProcess();
} else {
if ($this->maxProcessCount > 1 && !$this->processManager->pcntlAvailable) {
echo sprintf("Worker: pcntl not available, running in single process mode\n");
}
$this->runSingleProcess();
}
}
// 单进程模式运行
public function runSingleProcess(): void {
// 启动所有服务器
$this->startAllServers();
// 设置信号处理(周期性检查停止标志)
$this->signalHandler->setupPeriodicCheck(1.0);
// 进入事件循环
$this->running = true;
echo sprintf("Worker: event loop started (single process)\n");
$this->loop->run();
// 事件循环退出,清理
$this->running = false;
$this->signalHandler->cleanup();
$this->stopAll();
echo sprintf("Worker: stopped\n");
}
// 多进程模式运行
public function runMultiProcess(): void {
$processCount = $this->maxProcessCount;
echo sprintf("Worker: forking %d worker process(es)\n", $processCount);
// fork 子进程
// 注:闭包内直接使用 $this(TinyPHP 自动绑定),避免 use ($worker) 导致类型推断失败
$this->processManager->fork($processCount, function(int $index) {
// 子进程内执行
$this->isChild = true;
$this->workerIndex = $index;
// 子进程创建自己的 EventLoop(避免与父进程共享)
$this->loop = new EventLoop();
$this->signalHandler = new SignalHandler($this->loop);
// 启动所有服务器(在子进程的 EventLoop 中)
$this->startAllServers();
// 设置信号处理
$this->signalHandler->setupPeriodicCheck(1.0);
// 进入事件循环
$this->running = true;
echo sprintf("Worker[%d]: event loop started\n", $index);
$this->loop->run();
// 事件循环退出,清理
$this->running = false;
$this->signalHandler->cleanup();
$this->stopAll();
echo sprintf("Worker[%d]: stopped\n", $index);
});
// 父进程:监控子进程
if ($this->processManager->isParent) {
echo sprintf("Worker: parent process monitoring %d children\n",
$this->processManager->childCount());
// 设置信号处理(父进程也检查停止标志)
$this->signalHandler->setupPeriodicCheck(1.0);
// 父进程等待子进程退出
// 子进程异常退出时,重新 fork
$this->processManager->wait(function(int $workerIndex, int $status) {
echo sprintf("Worker: child %d exited abnormally (status=%d), reforking\n",
$workerIndex, $status);
// 重新 fork 一个子进程
$this->processManager->fork(1, function(int $index) use ($workerIndex) {
$this->isChild = true;
$this->workerIndex = $workerIndex;
$this->loop = new EventLoop();
$this->signalHandler = new SignalHandler($this->loop);
$this->startAllServers();
$this->signalHandler->setupPeriodicCheck(1.0);
$this->running = true;
echo sprintf("Worker[%d]: event loop restarted\n", $workerIndex);
$this->loop->run();
$this->running = false;
$this->signalHandler->cleanup();
$this->stopAll();
});
});
}
}
// 启动所有服务器(注册到 EventLoop)
public function startAllServers(): void {
$serverCount = count($this->servers);
for ($i = 0; $i < $serverCount; $i++) {
$server = $this->servers[$i];
echo "Worker: starting server on " . $server->address
. " (processes=" . $server->processCount . ")\n";
$server->start($this->loop);
}
}
// 停止所有服务器
public function stopAll(): void {
$serverCount = count($this->servers);
for ($i = 0; $i < $serverCount; $i++) {
$server = $this->servers[$i];
if ($server->started) {
$server->stop();
}
}
}
// 请求停止(可由信号处理或外部调用)
public function stop(): void {
echo sprintf("Worker: stop requested\n");
$this->signalHandler->requestStop();
$this->loop->stop();
// 如果是父进程,终止所有子进程
if (!$this->isChild && $this->processManager->isParent) {
$this->processManager->terminateAll();
}
}
}