PHP扩展Swoole实现实时异步任务队列示例


Posted in PHP onApril 13, 2019

本文实例讲述了PHP扩展Swoole实现实时异步任务队列。分享给大家供大家参考,具体如下:

假如要发100封邮件,for循环100遍,用户直接揭竿而起,什么破网站!

但实际上,我们很可能有超过1万的邮件。怎么处理这个延迟的问题?

答案就是用异步。把“发邮件”这个操作封装,然后后台异步地执行1万遍。这样的话,用户提交网页后,他所等待的时间只是“把发邮件任务请求推送进队列里”的时间。而我们的后台服务将在用户看不见的地方跑。

在实现“异步队列”这点上,有人采用MySQL表或者redis来存放待发送的邮件,然后,每分钟定时读取待发送列表,然后处理。这便是定时异步任务队列。但当前提交的任务要一分钟后才能执行,在某些实时性要求应用场景里还是不快。有些场景要求,只有一提交任务,便马上执行,但用户不需要等待返回结果。

本文将探讨用php扩展swoole实现实时异步任务队列的方案。

服务端

在打算放置脚本的目录(你也可以自行新建)新建Server.php,代码如下

<?php
class Server
{
  private $serv;
  public function __construct()
  {
    $this->serv = new swoole_server("0.0.0.0", 9501);
    $this->serv->set(array(
      'worker_num' => 1, //一般设置为服务器CPU数的1-4倍
      'daemonize' => 1, //以守护进程执行
      'max_request' => 10000,
      'dispatch_mode' => 2,
      'task_worker_num' => 8, //task进程的数量
      "task_ipc_mode " => 3, //使用消息队列通信,并设置为争抢模式
      //"log_file" => "log/taskqueueu.log" ,//日志
    ));
    $this->serv->on('Receive', array($this, 'onReceive'));
    // bind callback
    $this->serv->on('Task', array($this, 'onTask'));
    $this->serv->on('Finish', array($this, 'onFinish'));
    $this->serv->start();
  }
  public function onReceive(swoole_server $serv, $fd, $from_id, $data)
  {
    //echo "Get Message From Client {$fd}:{$data}\n";
    // send a task to task worker.
    $serv->task($data);
  }
  public function onTask($serv, $task_id, $from_id, $data)
  {
    $array = json_decode($data, true);
    if ($array['url']) {
      return $this->httpGet($array['url'], $array['param']);
    }
  }
  public function onFinish($serv, $task_id, $data)
  {
    //echo "Task {$task_id} finish\n";
    //echo "Result: {$data}\n";
  }
  protected function httpGet($url, $data)
  {
    if ($data) {
      $url .= '?' . http_build_query($data);
    }
    $curlObj = curl_init(); //初始化curl,
    curl_setopt($curlObj, CURLOPT_URL, $url); //设置网址
    curl_setopt($curlObj, CURLOPT_RETURNTRANSFER, 1); //将curl_exec的结果返回
    curl_setopt($curlObj, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($curlObj, CURLOPT_SSL_VERIFYHOST, FALSE);
    curl_setopt($curlObj, CURLOPT_HEADER, 0); //是否输出返回头信息
    $response = curl_exec($curlObj); //执行
    curl_close($curlObj); //关闭会话
    return $response;
  }
}
$server = new Server();

客户端

启动服务后,让我们看看如何调用服务。新建测试文件Client_test.php

<?php
class Client
{
  private $client;
  public function __construct()
  {
    $this->client = new swoole_client(SWOOLE_SOCK_TCP);
  }
  public function connect()
  {
    if (!$this->client->connect("127.0.0.1", 9501, 1)) {
      throw new Exception(sprintf('Swoole Error: %s', $this->client->errCode));
    }
  }
  public function send($data)
  {
    if ($this->client->isConnected()) {
      if (!is_string($data)) {
        $data = json_encode($data);
      }
      return $this->client->send($data);
    } else {
      throw new Exception('Swoole Server does not connected.');
    }
  }
  public function close()
  {
    $this->client->close();
  }
}
$data = array(
  "url" => "http://192.168.10.19/send_mail",
  "param" => array(
    "username" => 'test',
    "password" => 'test'
  )
);
$client = new Client();
$client->connect();
if ($client->send($data)) {
  echo 'success';
} else {
  echo 'fail';
}
$client->close();

在上面代码中,url即为任务所在地址,param为所需传递参数。

保存好代码,在命令行或者浏览器中执行Client_test.php,便实现了异步任务队列。你所填写的URL,将会在每次异步任务被提交后,以HTTP GET的方式异步执行。

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
PHP stristr() 函数(不区分大小写的字符串查找)
Jun 03 PHP
php实现执行某一操作时弹出确认、取消对话框
Dec 30 PHP
php判断电脑访问、手机访问的例子
May 10 PHP
PHP读取RSS(Feed)简单实例
Jun 12 PHP
CodeIgniter框架数据库事务处理的设计缺陷和解决方案
Jul 25 PHP
跟我学Laravel之请求(Request)的生命周期
Oct 15 PHP
PHP Curl模拟登录微信公众平台、新浪微博实例代码
Jan 28 PHP
php设计模式之委托模式
Feb 13 PHP
thinkPHP多域名情况下使用memcache方式共享session数据的实现方法
Jul 21 PHP
php中array_slice和array_splice函数解析
Oct 18 PHP
PHP 传输会话curl函数的实例详解
Sep 12 PHP
Yii2框架自定义验证规则操作示例
Feb 08 PHP
php+ajax实现商品对比功能示例
Apr 13 #PHP
PHP开发的文字水印,缩略图,图片水印实现类与用法示例
Apr 12 #PHP
详解PHP素材图片上传、下载功能
Apr 12 #PHP
laravel 事件/监听器实例代码
Apr 12 #PHP
Laravel5.7 数据库操作迁移的实现方法
Apr 12 #PHP
laravel使用Faker数据填充的实现方法
Apr 12 #PHP
Laravel5.7 Eloquent ORM快速入门详解
Apr 12 #PHP
You might like
PHP字符串中特殊符号的过滤方法介绍
2014/02/18 PHP
Yii2.0表关联查询实例分析
2016/07/18 PHP
PHP用FTP类上传文件视频等的简单实现方法
2016/09/23 PHP
Javascript 兼容firefox的一些问题
2009/05/21 Javascript
document.getElementById的简写方式(获取id对象的简略写法)
2010/09/10 Javascript
jQuery实现用方向键控制层的上下左右移动
2013/01/13 Javascript
Javascript中valueOf与toString区别浅析
2013/03/19 Javascript
JQuery的ready函数与JS的onload的区别详解
2013/11/21 Javascript
javascript中的__defineGetter__和__defineSetter__介绍
2014/08/15 Javascript
WEB前端开发都应知道的jquery小技巧及jquery三个简写
2015/11/15 Javascript
JavaScript拖动层Div代码
2017/03/01 Javascript
详解javascript 正则表达式之分组与前瞻匹配
2018/05/30 Javascript
Echart折线图手柄触发事件示例详解
2018/12/16 Javascript
vue+element UI实现树形表格带复选框的示例代码
2019/04/16 Javascript
js加减乘除精确运算方法实例代码
2021/01/17 Javascript
[01:59]深扒TI7聊天轮盘语音出处 1
2017/05/11 DOTA
[52:39]完美世界DOTA2联赛PWL S3 CPG vs Forest 第一场 12.16
2020/12/17 DOTA
Python基于Tkinter的HelloWorld入门实例
2015/06/17 Python
Python之os操作方法(详解)
2017/06/15 Python
Python实现字典去除重复的方法示例
2017/07/31 Python
Python中pandas dataframe删除一行或一列:drop函数详解
2018/07/03 Python
opencv-python 读取图像并转换颜色空间实例
2019/12/09 Python
python GUI库图形界面开发之PyQt5中QWebEngineView内嵌网页与Python的数据交互传参详细方法实例
2020/02/26 Python
Python描述符descriptor使用原理解析
2020/03/21 Python
linux mint中搜狗输入法导致pycharm卡死的问题
2020/10/28 Python
python开发一个解析protobuf文件的简单编译器
2020/11/17 Python
html5使用canvas画三角形
2014/12/15 HTML / CSS
急诊科护士自我鉴定
2013/10/14 职场文书
会计师职业生涯规划范文
2014/02/18 职场文书
白血病捐款倡议书
2014/05/14 职场文书
公司外出活动方案
2014/08/14 职场文书
产品陈列协议书(标准版)
2014/09/17 职场文书
团队会宣传标语
2014/10/09 职场文书
2014年项目经理工作总结
2014/11/24 职场文书
Java内存模型之happens-before概念详解
2021/06/13 Java/Android
MySQL多表查询机制
2022/03/17 MySQL