Skip to content

Commit 63e261a

Browse files
committed
以编写终端命令程序的方式编写多进程程序
1 parent 1f39008 commit 63e261a

File tree

7 files changed

+358
-61
lines changed

7 files changed

+358
-61
lines changed

README.md

Lines changed: 193 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ Soli PHP Console
33

44
Soli Console Component.
55

6-
Table of Contents
7-
=================
6+
## Table of Contents
87

98
* [安装](#安装)
109
* [使用](#使用)
@@ -20,7 +19,7 @@ Table of Contents
2019

2120
## 使用
2221

23-
如下我们编写 `test.php` 文件,内容为:
22+
如下我们编写 `task.php` 文件,内容为:
2423

2524
```php
2625
<?php
@@ -37,14 +36,17 @@ class Task extends \Soli\Console\Command
3736
/**
3837
* 默认执行的方法:index
3938
*/
40-
public function index()
39+
public function index($name = 'wukong')
4140
{
42-
return 'task:index';
41+
return "hello $name, in task:index.\n";
4342
}
4443

45-
public function handle()
44+
/**
45+
* 命令行输入的参数将按顺序作为 action 的参数传入
46+
*/
47+
public function handle($name = 'wukong', $alias = '孙行者')
4648
{
47-
return 'task:handle';
49+
return "hello $name <$alias>, in task:handle.\n";
4850
}
4951
}
5052

@@ -64,95 +66,232 @@ $app = new \Soli\Console\App();
6466
echo $app->handle();
6567
```
6668

67-
执行 task 类中的 index 方法:
69+
1. 执行 Task 类中的 index 方法:
70+
71+
```
72+
php task.php task
73+
// 或
74+
php task.php task:index
75+
```
76+
77+
2. 执行 Task 类中的 handle 方法:
78+
79+
```
80+
php task.php task:handle
81+
```
82+
83+
3. 命令行输入的参数将按顺序作为 action 的参数传入,例如输入两个参数 `hulk``绿巨人` 执行:
6884

69-
php test.php task
70-
// 或
71-
php test.php task:index
85+
```
86+
php task.php task:handle hulk 绿巨人
87+
```
7288

73-
执行 task 类中的 handle 方法
89+
将输出
7490

75-
php test.php task:handle
91+
```
92+
hello hulk <绿巨人>, in task:handle.
93+
```
7694

7795
## 编写多进程终端命令程序
7896

79-
我们可以结合 [Soli Process] 编写多进程终端命令程序
97+
`Soli Console` 结合 [Soli Process] 可以让我们以编写终端命令程序的方式编写多进程程序
8098
同时复用项目中的已有的 Model / Service 等代码。
8199

82-
文件位置 [examples/app/Console/Proc.php](examples/app/Console/Proc.php),内容为:
100+
注意这里的多进程只支持在 `Unix-like` 系统下运行。
101+
102+
文件位置 [examples/app/Console/Proc2.php](examples/app/Console/Proc2.php),内容为:
83103

84104
```php
85105
<?php
86106

87107
namespace App\Console;
88108

89-
class Proc extends \Soli\Console\Command
109+
/**
110+
* 终端命令结合多进程
111+
*/
112+
class Proc2 extends \Soli\Console\Command
90113
{
91-
/**
92-
* @var \Soli\Process
93-
*/
94-
protected $process;
114+
/** @var bool $runnable 这个属性决定了action是否以多进程方式运行 */
115+
protected $runnable = false;
116+
117+
/** @var string $name 进程名称,只在 Linux 系统下起作用 */
118+
protected $name = 'soli console proc2';
119+
120+
/** @var int $count 进程数 */
121+
protected $count = 4;
122+
123+
/** @var bool $daemonize 是否以守护进程方式运行 */
124+
protected $daemonize = false;
125+
126+
/** @var bool $refork 是否自动补充退出的进程 */
127+
protected $refork = false;
95128

96-
public function __construct(\Soli\Process $process)
129+
/** @var string $logFile 记录进程的输出、终止等信息到此文件 */
130+
protected $logFile = '/tmp/soli-console-proc2.log';
131+
132+
public function __construct()
97133
{
98-
$process->name = 'soli console';
99-
$process->count = 4;
100-
$process->daemonize = false;
101-
$process->logFile = '/tmp/soli-console-proc.log';
134+
// 针对不同的 action 可以选择是否使用多进程,以及指定不同的进程属性
135+
$action = $this->dispatcher->getActionName();
136+
switch ($action) {
137+
case 'command':
138+
$this->runnable = false;
139+
break;
140+
case 'process':
141+
$this->runnable = true;
142+
$this->logFile = null;
143+
break;
144+
case 'daemonize':
145+
$this->runnable = true;
146+
$this->daemonize = true;
147+
echo "Process output info in {$this->logFile}\n";
148+
break;
149+
case 'refork':
150+
$this->runnable = true;
151+
$this->refork = true;
152+
break;
153+
}
154+
}
102155

103-
$this->process = $process;
156+
public function command($name = 'wukong')
157+
{
158+
echo "hello $name. just a command.\n";
104159
}
105160

106161
/**
107-
* 默认执行的方法:index
162+
* $worker 参数将成为 action 的第一个参数,$worker 参数之后是从命令行输入的参数
108163
*/
109-
public function index()
164+
public function process(\Soli\Process $worker, $name = 'wukong')
110165
{
111-
$this->process->name .= ' proc:index';
112-
113-
$this->process->setJob(function ($worker) {
114-
$this->doIndex($worker);
115-
});
116-
117-
$this->process->start();
166+
echo "hello $name. dump message from [worker:{$worker->id} {$worker->workerPid}] process.\n";
167+
}
118168

119-
return "return message from master process.\n";
169+
public function daemonize(\Soli\Process $worker)
170+
{
171+
echo "dump message from [worker:{$worker->id} {$worker->workerPid}] daemonize process.\n";
120172
}
121173

122-
protected function doIndex($worker)
174+
public function refork(\Soli\Process $worker)
123175
{
124-
echo "dump message from worker[{$worker->id} {$worker->workerPid}] process.\n";
176+
echo "dump message from [worker:{$worker->id} {$worker->workerPid}] process.\n";
125177
}
126178
}
127179
```
128180

129-
执行前在当前项目根目录使用 composer 安装 [Soli Process] 多进程包,注意只支持 `Unix-like` 系统:
181+
与多进程相关的属性:
182+
183+
属性名称 | 类型 | 默认值 | 描述
184+
----------|--------|----------|-----------------------------------------
185+
runnable | bool | false | 这个属性决定了action是否以多进程方式运行
186+
name | string | '' | 进程名称,只在 Linux 系统下起作用
187+
count | int | 1 | 进程数
188+
daemonize | bool | false | 是否以守护进程方式运行
189+
refork | bool | true | 是否自动补充退出的进程
190+
logFile | string | null | 记录进程的输出、终止等信息的文件路径
191+
192+
设置 `runnable``true` 时,action 以多进程方式运行,`$worker 参数将成为 action 的第一个参数,$worker 参数之后是从命令行输入的参数`
193+
194+
设置 `daemonize` 属性为 `true` 时,将以守护进程的方式运行,所有输出内容将被重定向到 `logFile` 属性所指定的文件,
195+
未指定 `logFile` 属性时,输出内容将会被丢弃。
196+
197+
设置 `refork` 属性为 `true` 时,可以在进程退出(如程序出现异常)后自动补充新的进程。
198+
199+
下面执行 Proc2 类中的各个 action 方法,看看实际的执行效果:
200+
201+
1. 执行 Proc2 类中的 command 方法:
202+
203+
```
204+
php examples/console proc2:command
205+
```
206+
207+
将输出:
208+
209+
```
210+
hello wukong. just a command.
211+
```
212+
213+
2. 执行 Proc2 类中的 process 方法:
214+
215+
```
216+
php examples/console proc2:process bajie
217+
```
218+
219+
将输出类似以下内容(原始信息还会有进程启动、退出等相关信息,这里为了便于阅读,只贴出了 worker 进程中的输出信息):
220+
221+
```
222+
hello bajie. dump message from [worker:2 64163] process.
223+
hello bajie. dump message from [worker:1 64162] process.
224+
hello bajie. dump message from [worker:3 64164] process.
225+
hello bajie. dump message from [worker:4 64165] process.
226+
```
227+
228+
action 以多进程方式运行时:`$worker 参数将成为 action 的第一个参数,$worker 参数之后是从命令行输入的参数`
229+
如这里的方法定义,从第二个参数开始才是从终端输入的参数:
230+
231+
public function process(\Soli\Process $worker, $name = 'wukong')
232+
233+
3. 执行 Proc2 类中的 daemonize 方法:
234+
235+
```
236+
php examples/console proc2:daemonize
237+
```
238+
239+
将输出:
240+
```
241+
Process output info in /tmp/soli-console-proc2.log
242+
```
243+
244+
程序以守护进程的方式运行时,所有输出内容将被重定向到 `logFile` 属性所指定的文件,
245+
246+
查看 `/tmp/soli-console-proc2.log` 的文件内容为(原始信息还会有进程启动、退出等相关信息,这里为了便于阅读,只贴出了 worker 进程中的输出信息):
247+
248+
```
249+
dump message from [worker:2 64612] daemonize process.
250+
dump message from [worker:3 64613] daemonize process.
251+
dump message from [worker:1 64611] daemonize process.
252+
dump message from [worker:4 64614] daemonize process.
253+
```
254+
255+
4. 执行 Proc2 类中的 refork 方法:
130256

131-
composer require soliphp/process
257+
```
258+
php examples/console proc2:refork
259+
```
260+
261+
将输出类似以下内容(原始信息还会有其他进程启动、退出等相关信息,这里为了便于阅读,只贴出了 `1 号 worker 进程`的相关信息):
132262

133-
执行 proc 类中的 index 方法:
263+
```
264+
[2018-11-08 20:49:57] [master 73312] [worker:1 73332] process started
265+
dump message from [worker:1 73332] process.
266+
[2018-11-08 20:49:57] [master 73312] [worker:1 73332] process stopped with status 0
267+
[2018-11-08 20:49:57] [master 73312] [worker:1 73339] process started
268+
dump message from [worker:1 73339] process.
269+
[2018-11-08 20:49:57] [master 73312] [worker:1 73339] process stopped with status 0
270+
[2018-11-08 20:49:57] [master 73312] [worker:1 73343] process started
271+
dump message from [worker:1 73343] process.
272+
[2018-11-08 20:49:57] [master 73312] [worker:1 73343] process stopped with status 0
273+
[2018-11-08 20:49:57] [master 73312] [worker:1 73346] process started
274+
dump message from [worker:1 73346] process.
275+
[2018-11-08 20:49:57] [master 73312] [worker:1 73346] process stopped with status 0
276+
[2018-11-08 20:49:57] [master 73312] [worker:1 73350] process started
277+
dump message from [worker:1 73350] process.
278+
[2018-11-08 20:49:57] [master 73312] [worker:1 73350] process stopped with status 0
279+
```
134280

135-
php examples/console proc
136-
// 或
137-
php examples/console proc:index
138-
139-
将输出类似以下内容(原始信息还会有进程退出等相关信息,这里为阅读方便只贴出了 worker master 进程中的输出信息):
281+
设置 `refork` 属性为 `true` 时,可以在进程退出后自动补充新的进程。当程序需要保持进程数,而由于异常进程被退出时,refork 将相当有用。
140282

141-
dump message from worker[2 56649] process.
142-
dump message from worker[1 56648] process.
143-
dump message from worker[3 56650] process.
144-
dump message from worker[4 56651] process.
145-
return message from master process.
283+
可以看到 `worker:1` 每次在执行完毕退出进程后,就会有新的进程 fork 出来,进行补充,保持进程数。
146284

147285
## 示例
148286

149-
[examples] 文件夹下提供了一个带目录结构的终端命令例子,感兴趣的同学可以前去翻看
287+
[examples] 文件夹下提供了一个带目录结构的终端命令示例,感兴趣的同学可以直接翻看
150288

151289
examples
152290
├── app
153291
│   └── Console
154-
│   ├── Proc.php > proc 命令文件
155-
│   └── Task.php > task 命令文件
292+
│   ├── Proc.php > proc 命令使用 \Soli\Process 多进程的原始类文件
293+
│   ├── Proc2.php > proc2 命令结合 \Soli\Process 使用多进程的类文件
294+
│   └── Task.php > task 命令类文件
156295
├── bootstrap.php > 配置一些引导信息
157296
└── console > 入口文件
158297

composer.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
],
1818
"require": {
1919
"php": ">=7.0",
20-
"soliphp/framework": "^2.0"
20+
"soliphp/framework": "^2.0",
21+
"soliphp/process": "^1.0"
2122
},
2223
"autoload": {
2324
"psr-4": {
@@ -35,5 +36,6 @@
3536
"url": "https://packagist.laravel-china.org"
3637
}
3738
},
38-
"minimum-stability": "dev"
39+
"minimum-stability": "dev",
40+
"prefer-stable": true
3941
}

examples/app/Console/Proc.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public function __construct(Process $process)
2525
$process->name = 'soli console';
2626
$process->count = 4;
2727
$process->daemonize = false;
28+
$process->refork = false;
2829
$process->logFile = '/tmp/soli-console-proc.log';
2930

3031
$this->process = $process;
@@ -48,6 +49,6 @@ public function index()
4849

4950
protected function doIndex($worker)
5051
{
51-
echo "dump message from worker[{$worker->id} {$worker->workerPid}] process.\n";
52+
echo "dump message from [worker:{$worker->id} {$worker->workerPid}] process.\n";
5253
}
5354
}

0 commit comments

Comments
 (0)