swoole异步任务池实现
呀,第一次写博客文章,体谅一下。而且这篇文章不是为了记录是为了让你们挑我毛病(滑稽)。
正在学swoole,但是没在实战使用过 一直在自己尝试 肯定有错误 你们提出来我会改的
这篇是基于swoole文档的内容扩展成任务池,任务可扩展
异步任务池实现思路
首先基于tcp服务增加onTask和onFinish事件回调函数
onTask回调函数中执行异步任务,onFinish为任务完成后的回调函数
首先先做一个简易的tcp服务
<?php
class Server{
public $serv;
public function __construct()
{
$this->serv=new swoole_server('0.0.0.0',9501);
$this->serv->on('Start',[$this,'onStart']);
$this->serv->on('Receive',[$this,'onReceive']);
$this->serv->on('Close',[$this,'onClose']);
$this->serv->start();
}
#监听链接回调函数
public function onStart(){
echo "swoole 异步任务服务启动成功".PHP_EOL;
}
#监听数据接收回调函数
public function onReceive($serv,$fd,$from_id,$data){
echo "接收到客户端信息".PHP_EOL;
print_r($data);
}
#客户端断开连接回调函数
public function onClose($serv,$fd){
echo "client-{$fd} :CLOSE".PHP_EOL;
}
}
new Server();
基于tcp服务加上onTask 和 onFinish回调函数
服务端代码:Server.php
<?php
class Server{
public $serv;
public function __construct()
{
$this->serv=new swoole_server('0.0.0.0',9501);
$this->serv->set([
'task_worker_num'=>4#任务池数量
]);
$this->serv->on('Start',[$this,'onStart']);
$this->serv->on('Receive',[$this,'onReceive']);
$this->serv->on('Task',[$this,'onTask']);
$this->serv->on('Finish',[$this,'onFinish']);
$this->serv->start();
}
public function onStart(){
echo "swoole 异步任务池服务启动成功".PHP_EOL;
}
public function onReceive($serv,$fd,$from_id,$data){
$task_id=$serv->task($data);
echo "投递任务 {$task_id} 成功".PHP_EOL;
}
public function onTask($serv,$task_id,$from_id,$data){
echo "执行任务 {$task_id}".PHP_EOL;
$msg=include $data.'.php';#根据需按过来的文件名称 执行相对于文件 实现多任务扩展
$serv->finish($msg);
}
public function onFinish($serv,$task_id,$data){
echo "任务 {$task_id} 执行完成,执行结果:{$data}".PHP_EOL;
}
#此文件函数可以适当加入记录日志操作
}
new Server();
?>
这里采用文件形式执行任务代码,将某一任务的代码放到新文件中,在我们客户端连接tcp的时候将我们写好的文件名称传给任务池服务端,服务端接收到文件名称会去执行此文件代码(格式自定),最好包含返回值
客户端连接tcp
执行函数进行发送要执行的文件名称到服务端
客户端代码:TaskClient.php
<?php
class TaskClient{
public $client;
public function __construct(){
$this->client=new swoole_client(SWOOLE_SOCK_TCP);
}
public function runTask($filename){
$this->client->connect('服务器ip',9501,1);#链接server
$this->client->send($filename);#发送任务文件名称 此例子为sendEmail文件名称
$result=$this->client->recv();
$this->client->close();
return $result;
}
}
$client=new TaskClient();
$result=$client->runTask('sendEmail');#使用参数传递文件名称 客户端也可复用
echo json_encode($result);die;
?>
任务逻辑文件
此文件会被引入执行:sendEmail.php
<?php
#此段代码为任务逻辑 start
#由于邮箱较少 直接采用sql操作修改字段 10000条数据 循环去修改某字段模拟发送邮件操作
$db=new PDO('mysql:host=127.0.0.1;dbname=study', 'root', 'root');
$sql = "SELECT * FROM `test_user`";
$list = $db->query($sql)->fetchAll(PDO::FETCH_ASSOC);
$time = date('Y-m-d H:i:s');
$result = [];
foreach ($list as $v) {
$sql = "UPDATE `test_user` SET `send_time`='{$time}' WHERE `id`={$v['id']}";
$result[] = $db->exec($sql);
}
$result = array_filter($result);
if (count($result) == count($list)) {
$msg = '全部完成';
} else {
$msg = '部分完成,请排查';
}
#任务逻辑 end
#这里可以返回msg 也可以记录日志 异步任务一般时间较长 应该记录日志
return $msg;
?>
作者:言成