首页 后端开发 php教程 关于异步任务队列之PHP使用swoole来实现实时异步任务队列。

关于异步任务队列之PHP使用swoole来实现实时异步任务队列。

Jun 20, 2016 pm 12:30 PM

背景:关于PHP的异步回调啥的,其实PHP这种语言的运行机制想优雅实现是不可能的,有一个叫swoole的扩展实现这个队列的处理是很不错的,之前有张宴兄弟写过一个叫https的队列处理(基于libevent),后面有韩天峰兄弟写的swoole,更注重了异步IO实现对CPU的IO的吃满(基于自己编写的epoll加队列链表内存分配一堆东西,反正我是看过没看明白有空再研究),但是,作为swoole的粉丝兼顾问,异步问题在PHP业界的一个需求量还是蛮大的,尤其是日志异步写、url访问、邮件异步发、跨机房db特殊的小同步、审核异步队列、框架底层对接口访问排查错误的db和cache接口查询及返回,这些目前对于大并发网站都是需要异步来解决的,但是异步归异步,回调这块也实现异步回调(真大并发想知道结果可能阻塞了PHP进程产生进程等待异步返回而新来的连接没法及时处理的php-fpm进程性雪崩),在实际运用中常规处理办法是开一个新的端口,下面的swoole也是开了新的端口来处理,于httpsqs不同在于swoole可以把简单的curl啥的逻辑也可封装里面,在httpsqs里只是纯队列,一个投递进来,再起一个php的daemon进行读取队列,因为如果真是繁忙,导致异步处理返回慢,这个等待也是太漫长,我觉得看具体业务而看要不要等待,在实际中异步和队列大都用于抛数据以及解耦,swoole在这块不光有了异步还有异步回调,所以,最大限度的解决了上面这些场景,先抄一篇文章再说,有空再研究研究其实现,假如能看懂的话:-),异步回调这块如果有明白的可以留言给我,谢谢。

————————————————————————————————————————————————————————————————————————

关于异步任务队列

用户打开了我们的网站。他要做的就是勾选需要发邮件的代理商列表,然后把结算邮件发出去。

假如我们需要发1封邮件,我们写个函数执行即可。考虑到网络可能会稍微有点延迟,但是是可以接受的,用户会乖乖等你的网页发完邮件了再关闭网页。

假如我们要发布10封邮件,用一个for循环,循环10遍执行发邮件操作。这时候,也许10倍的网络延迟会让用户稍微有点不耐烦,但勉强可以等吧。

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

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

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

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

在云平台SAE和BAE上,都有taskqueue服务来解决上面的问题。而如果是自己假设服务器,则如何解决?本文将探讨用php扩展swoole实现实时异步任务队列的方案。

安装swoole

pecl 安装:

pecl install swoole

看命令行提示,如果它提示说没有写php.ini,则自己手动在PHP.ini后面加上:

extension = "swoole.so"

服务端

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

1

<?phpclass 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} finishn";        //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();

登录后复制

由于服务端是异步、常驻内存的,因此必须通过命令行来启动。在命令行执行以上代码以启动服务

php Server.php

执行完毕后关闭命令行窗口即可。服务会在后台以守护进程运行

客户端

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

代码如下:

1

<?phpclass 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) ) {            echo "Connect Error";        }        $data = array(            "url" =>  "http://192.168.10.19/send_mail" ,            "param" => array(                "username"=>'test',                "password" => 'test'                )            );        $json_data = json_encode($data);        $this->client->send( $json_data );    }}$client = new Client();$client->connect();

登录后复制

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

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

查看与关闭

swoole好像没有很便捷的关闭方式。所以只能直接通过关闭进程来关闭。

查看命令:

ps -ef | grep php

结束单个进程:

kill -9 {进程号}

结束所有进程的命令:

killall -9 php

摘自第七星尘的博客:http://blog.star7th.com/2016/01/1905.html

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
2 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

在Laravel中使用Flash会话数据 在Laravel中使用Flash会话数据 Mar 12, 2025 pm 05:08 PM

Laravel使用其直观的闪存方法简化了处理临时会话数据。这非常适合在您的应用程序中显示简短的消息,警报或通知。 默认情况下,数据仅针对后续请求: $请求 -

php中的卷曲:如何在REST API中使用PHP卷曲扩展 php中的卷曲:如何在REST API中使用PHP卷曲扩展 Mar 14, 2025 am 11:42 AM

PHP客户端URL(curl)扩展是开发人员的强大工具,可以与远程服务器和REST API无缝交互。通过利用Libcurl(备受尊敬的多协议文件传输库),PHP curl促进了有效的执行

简化的HTTP响应在Laravel测试中模拟了 简化的HTTP响应在Laravel测试中模拟了 Mar 12, 2025 pm 05:09 PM

Laravel 提供简洁的 HTTP 响应模拟语法,简化了 HTTP 交互测试。这种方法显着减少了代码冗余,同时使您的测试模拟更直观。 基本实现提供了多种响应类型快捷方式: use Illuminate\Support\Facades\Http; Http::fake([ 'google.com' => 'Hello World', 'github.com' => ['foo' => 'bar'], 'forge.laravel.com' =>

在Codecanyon上的12个最佳PHP聊天脚本 在Codecanyon上的12个最佳PHP聊天脚本 Mar 13, 2025 pm 12:08 PM

您是否想为客户最紧迫的问题提供实时的即时解决方案? 实时聊天使您可以与客户进行实时对话,并立即解决他们的问题。它允许您为您的自定义提供更快的服务

PHP记录:PHP日志分析的最佳实践 PHP记录:PHP日志分析的最佳实践 Mar 10, 2025 pm 02:32 PM

PHP日志记录对于监视和调试Web应用程序以及捕获关键事件,错误和运行时行为至关重要。它为系统性能提供了宝贵的见解,有助于识别问题并支持更快的故障排除

解释PHP中晚期静态结合的概念。 解释PHP中晚期静态结合的概念。 Mar 21, 2025 pm 01:33 PM

文章讨论了PHP 5.3中引入的PHP中的晚期静态结合(LSB),从而允许静态方法的运行时分辨率调用以获得更灵活的继承。 LSB的实用应用和潜在的触摸

在Laravel中发现文件下载的存储::下载 在Laravel中发现文件下载的存储::下载 Mar 06, 2025 am 02:22 AM

Laravel框架的Storage::download方法提供了一个简洁的API,用于安全地处理文件下载,同时管理文件存储的抽象。 以下是一个在示例控制器中使用Storage::download()的例子:

如何注册和使用Laravel服务提供商 如何注册和使用Laravel服务提供商 Mar 07, 2025 am 01:18 AM

Laravel的服务容器和服务提供商是其架构的基础。 本文探讨了服务容器,详细信息服务提供商创建,注册,并通过示例演示了实际用法。 我们将从OVE开始

See all articles