Swoole入门 第三个程序 异步task
一、swoole task
- 常用的场景:异步支付处理、异步订单处理、异步日志处理、异步发送邮件/短信等。
- Swoole 异步Task,主要实现调用异步任务的执行。实现方式是 worker 进程处理数据请求,分配给 task 进程执行。
- task 底层使用Unix Socket管道通信,是全内存的,没有IO消耗。单进程读写性能可达100万/s,不同的进程使用不同的管道通信,可以最大化利用多核。
二、 创建异步服务(可执行)
<?php
class Server
{
private $serv;
public function __construct(){
$this->serv = new swoole_server('0,0,0,0',9502);
$this->serv ->set([
'worker_num' =>2, //开启2 个woker 进程
'max_request' =>4,//每个worker进程 max_request设置为4次
'task_worker_num' =>4, //开启4个task 进程
'dispatch_mode' =>2 //数据分包策略 - 固定模式
]);
$this->serv->on('Start', [$this, 'onStart']);
$this->serv->on('Connect', [$this, 'onConnect']);
$this->serv->on('Receive', [$this, 'onReceive']);
$this->serv->on('Close', [$this, 'onClose']);
$this->serv->on('Task', [$this, 'onTask']);
$this->serv->on('Finish', [$this, 'onFinsh']);
$this->serv->start();
}
public function onStart($serv){
echo "#### onStart ###".PHP_EOL;
echo "SWOOLE " . SWOOLE_VERSION . " 服务已启动 " . PHP_EOL;
echo "master_pid: {$serv->master_pid}" . PHP_EOL;
echo "manager_pid: {$serv->manager_pid}" . PHP_EOL;
echo "########".PHP_EOL.PHP_EOL;
}
public function onConnect($serv, $fd){
echo "#### onConnect ####" . PHP_EOL;
echo "客户端:" . $fd . "已连接" . PHP_EOL;
echo '#######'. PHP_EOL . PHP_EOL;
}
public function onReceive($serv, $fd, $form_id, $data){
echo "### onReceive ####" . PHP_EOL;
echo "worker_pid: { $serv->worker_pid}" .PHP_EOL;
echo "客户端: {$fd} 发来的Email:{$data}" . PHP_EOL;
$param = [
'fd' =>$fd,
'email'=> $data
];
$res = $serv->task(json_encode($param));
if($res === false){
echo "任务分配失败 Task " . $res . PHP_EOL;
}else{
echo "任务分配成功 Task " . $res . PHP_EOL;
}
echo "############" . PHP_EOL . PHP_EOL;
}
public function onTask($serv, $task_id, $form_id, $data){
echo "##### onTask ####" . PHP_EOL;
echo "#{$serv->worker_id} onTask: [PID = {$serv->worker_pid}] : task_id = {$task_id}" . PHP_EOL;
//业务代码
for($i = 1; $i <= 5; $i ++){
sleep(2);
echo "Task {task_id} 已完成{$i}/5的任务" . PHP_EOL;
}
$data_arr = json_decode($data, true);
$serv->send($data_arr['fd'], 'Email:)' . $data_arr['email'] . ',发送成功');
$serv->finish($data);
echo "######". PHP_EOL . PHP_EOL;
}
public function onFinsh($serv, $task_id, $data){
echo "### onFinsh ####" . PHP_EOL;
echo "Task {$task_id} 已完成" .PHP_EOL;
echo "######" . PHP_EOL . PHP_EOL;
}
public function onClose($serv, $fd){
echo "Client Close" . PHP_EOL;
}
}
$server = new Server();
三 创建异步客户端(执行失败)
引用官方原话:在 Swoole4+ 下所有的业务代码都是同步写法(Swoole1.x 时代才支持异步写法,现在已经移除了异步客户端,对应的需求完全可以用协程客户端实现),完全没有心智负担,符合人类思维习惯!
此处有坑 踩坑踩坑
- www.codeleading.com/article/259247...
- github.com/swoole/ext-async
- wiki.swoole.com/wiki/page/p-async_...
<?php
class Client
{
private $client;
public function __construct(){
//这里有个坑 swoole 4.3 后不支持这个写法 需要安装扩展ext-async
//ext-async目前只支持最新 swoole4.4.16 如果你的版本过新 安装这个扩展很可能编译不通过
// 本人swoole4.5.5 尝试安装失败 建议改成协程写法,暂时不会 哈哈哈 后续试试
$this->client = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);
$this->client->on('Connect', [$this, 'onConnect']);
$this->client->on('Recive', [$this, 'onRecive']);
$this->client->on('Close', [$this, 'onClose']);
$this->client->on('Error', [$this, 'onError']);
}
public function connect(){
if(!$fp = $this->client->connect("127.0.0.1", 9502, 1)){
echo "Error: {$fp->errMsg}[{$fp->errCode}]" .PHP_EOL;
return;
}
}
public function onConnect($cli){
fwrite(STDOUT, "输入Email:");
swoole_event_add(STDIN, function(){
fwrite(STDOUT, "输入Email");
$msg = trim(fgets(STDIN));
$this ->send($msg);
});
}
public function onRecive($cli, $data){
echo PHP_EOL . "Recived: " . $data . PHP_EOL;
}
public function send($data){
$this ->client->send($data);
}
public function onClose($cli){
echo "Client close connection" . PHP_EOL;
}
public function onError(){
}
}
$client = new Client();
$client->connect();
学习整理于https://github.com/xinliangnote/Swoole 不懂可以结合来看或评论
考虑到代码比较传统 不是swoole推崇的协程化 后续不再更新或者后续改成协程代码发出
个人博客停止维护,部分博客转载到这
- peter
- 2021-04-17 17:23:01
本作品采用《CC 协议》,转载必须注明作者和本文链接