#### 使用
- 服务端启动worker服务,用于消费队列任务
```bash
php zcswooe.php queue start|stop|kill
```
- 客户端调用方式:
```php
RedisDB::getConnection()->lPush('queue_name', json_encode([
'router' => '/queue/test/save',
'params' => [['value1', 'value2'], ['key'=>'value3'], 'value4']
]));
```
队列内容必须包括两个参数router和params,具体参数如下:
- router表示任务处理的控制器路由,路由的解析和http服务的路由解析一样,例如/user/saveContent表示调用app/controllers/userController的saveContent方法,即队列的任务可以直接调用http控制器的方法处理,具体参考router解析
- params表示控制器方法参数,params必须是一个数组,参考call_user_func_array参数
- 如上,任务的处理将由testController控制器处理,相当于:
```php
$controller = new app/controllers/queue/testController();
$controller->save(['value1', 'value2'], ['key'=>'value3'], 'value4')
```
#### 实现
- swoole_timer + swoole_process + redis(rabbitmq)
#### 流程
![](https://box.kancloud.cn/1de00fdd7cf22eab35099756fec261b6_644x378.png)
流程图
![](https://box.kancloud.cn/705c80c56fd0a1d1347841273b975293_913x411.png)
运行图
#### 简单说明
- 原理参考: https://github.com/kcloze/swoole-jobs
- 一个队列可以有多个worker来处理任务,一个worker即一个子进程
- 一个队列可以设置最小worker数,最大worker数,当队列积压的任务数超过指定峰值之后,便会动态新增worker处理任务,总数量不超过最大worker数
- 一个队列总会保持最小worker数处理任务数,动态新增的worker在处理完指定任务数之后便会退出
- 父进程(即master主进程)负责子进程的启动和动态添加,负责子进程退出之后处理(swoole_wait)
- 子进程负责处理对应的队列的任务
- 异步定时器(swoole_timer),指定周期内检测队列积压数量,根据积压数值来决定是否新增worker来处理任务
#### 信号处理器
- SIGCHLD: 子进程退出触发SIGCHLD信号,处理子进程退出
- SIGINT: 终端强制退出(ctrl + c)
- SIGTERM: 强制终止进程退出(kill mpid)
- SIGUSR1: 平滑退出进程,等待子进程处理完任务后退出,退出时间由定时器周期决定
#### 注意问题
- 多个进程不能共享一个数据连接
- 子进程创建之后,会得到父进程一个副本,所以子进程不能共享全局变量或其他类型变量,所以子进程需要共享父进程状态,需要将父进程状态写到第三方类库(文件,数据库等等)
- 子进程退出后,父进程务必要执行swoole_process::wait进行回收,否则这个子进程就会变为僵尸进程。会浪费操作系统的进程资源。
#### 主要代码文件
- /zcswoole/command/QueueCommand.php