PHP异步进程async-helper实例详解

PHP 的异步进程助手,借助于 AMQP 实现异步执行 PHP 的方法,将一些很耗时、追求高可用、需要重试机制的操作放到异步进程中去执行,将你的 HTTP 服务从繁重的业务逻辑中解脱出来。以一个较低的成本将传统 PHP 业务逻辑转换成非阻塞、高可用、可扩展的异步模式。本文主要和大家介绍PHP异步进程助手async-helper的详细用法以及相关代码实例,对此有需要的朋友学习下。希望能帮助到大家。

依赖

php 5.6+

ext-bcmath

ext-amqp 1.9.1+

ext-memcached 3.0.3+

安装

通过 composer 安装

1

composer require l669/async-helper

或直接下载项目源码

1

wget https://github.com/l669306630/async-helper/archive/master.zip

使用范例

业务逻辑:这里定义了很多等待被调用的类和方法,在你的项目中这可能是数据模型、或是一个发送邮件的类。

1

2

3

4

5

6

7

8

9

10

11

12

13

<?php

class SendMailHelper

{

/**

* @param array $mail

* @throws Exception

*/

public static function request($mail)

{

// 在这里发送邮件,或是通过调用第三方提供的服务发送邮件

// 发送失败的时候你抛出了异常,希望被进程捕获,并按设定的规则进行重试

}

}

生产者:通常是 HTTP 服务,传统的 PHP 项目或是一个命令行程序,接收到某个请求或指令后进行一系列的操作。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

<?php

use l669\AsyncHelper;

class UserController

{

public function register()

{

// 假设这是一个用户注册的请求,用户提交了姓名、邮箱、验证码

// 第一步、校验用户信息

// 第二步、实例化异步助手,这时候会连接 AMQP

$async_helper = new AsyncHelper([

'host' => '127.0.0.1',

'port' => '5672',

'user' => 'root',

'pass' => '123456',

'vhost' => '/'

]);

// 第三步、保存用户信息到数据库

$mail = [

'from' => 'service@yourdomain.com',

'to' => 'username@163.com',

'subject' => '恭喜你注册成功',

'body' => '请点击邮件中的链接完成验证....'

];

// 第四步、通过异步助手发送邮件

$async_helper->run('\\SendMailHelper', 'request', [$mail]);

// 这是同步的模式去发送邮件,如果邮件服务响应迟缓或异常,就会直接影响该请求的响应时间,甚至丢失这封重要邮件

// SendMailHelper::request($mail);

}

}

消费者:PHP 的异步进程,监听消息队列,执行你指定的方法。并且该消费者进程是可扩展的高可用的服务,这一切都得益于 AMQP,这是系统解耦、布局微服务的最佳方案。

consume.php

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

<?php

require_once('vendor/autoload.php');

require_once('SendMailHelper.php');

use l669\AsyncHelper;

use l669\CacheHelper;

$cache_helper = new CacheHelper('127.0.0.1', 11211);

while(true){

try{

$async_helper = new AsyncHelper([

'host' => '127.0.0.1',

'port' => '5672',

'user' => 'root',

'pass' => '123456',

'vhost' => '/',

'cacheHelper' => $cache_helper

]);

$async_helper->consume();

}catch(Exception $e){

// 可以在这里记录一些日志

sleep(2);

}

}

# 在命令行下启动消费者进程,推荐使用 supervisor 来管理进程

php consume.php

支持事务:需要一次提交执行多个异步方法,事务可以确保完成性。

1

2

3

4

5

6

7

8

9

10

// 接着上面的示例来说,这里省略了一些重复的代码,下同

$async_helper->beginTransaction();

try{

$async_helper->run('\\SendMailHelper', 'request', [$mail1]);

$async_helper->run('\\SendMailHelper', 'request', [$mail2]);

$async_helper->run('\\SendMailHelper', 'request', [$mail3]);

$async_helper->commit();

}catch(\Exception $e){

$async_helper->rollback();

}

阻塞式重试:当异步进程执行一个方法,方法内部抛出异常时进行重试,一些必须遵循执行顺序的业务就要采用阻塞式的重试,通过指定重试最大阻塞时长来控制。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

use l669\CacheHelper;

use l669\AsyncHelper;

$async_helper = new AsyncHelper([

'host' => '127.0.0.1',

'port' => '5672',

'user' => 'root',

'pass' => '123456',

'vhost' => '/',

'cacheHelper' => new CacheHelper('127.0.0.1', 11211),

'retryMode' => AsyncHelper::RETRY_MODE_REJECT, // 阻塞式重试

'maxDuration' => 600              // 最长重试 10 分钟

]);

$send_mail_helper = new \SendMailHelper();

$mail = new \stdClass();

$mail->from = 'service@yourdomain.com';

$mail->to = 'username@163.com';

$mail->subject = '恭喜你注册成功';

$mail->body = '请点击邮件中的链接完成验证....';

$async_helper->run($send_mail_helper, 'request', [$mail]);

// 如果方法中需要抛出异常来结束程序,又不希望被异步进程重试,可以抛出以下几种错误码,进程捕获到这些异常后会放弃重试:

// l669\AsyncException::PARAMS_ERROR

// l669\AsyncException::METHOD_DOES_NOT_EXIST

// l669\AsyncException::KNOWN_ERROR

非阻塞式重试:当异步执行的方法内部抛出异常,async-helper 会将该方法重新放进队列的尾部,先执行新进入队列的方法,回头再重试刚才执行失败的方法,通过指定最大重试次数来控制。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

use l669\CacheHelper;

use l669\AsyncHelper;

$async_helper = new AsyncHelper([

'host' => '127.0.0.1',

'port' => '5672',

'user' => 'root',

'pass' => '123456',

'vhost' => 'new',

'cacheHelper' => new CacheHelper('127.0.0.1', 11211),

'queueName' => 'emails.vip',          // 给付费的大爷走 VIP 队列

'retryMode' => AsyncHelper::RETRY_MODE_TTL,   // 非阻塞式重试

'maxRetries' => 10               // 最多重试 10 次

]);

$mail = new \stdClass();

$mail->from = 'service@yourdomain.com';

$mail->to = 'username@163.com';

$mail->subject = '恭喜你注册成功';

$mail->body = '请点击邮件中的链接完成验证....';

$async_helper->run('\\SendMailHelper', 'request', [$mail]);

应用和解惑

我们采用的是开源的 RabbitMQ 来为我们提供的 AMQP 服务。

你的项目部署在拥有很多服务器节点的集群上,每个节点的程序都需要写日志文件,现在的问题就是要收集所有节点上面的日志到一个地方,方便我们及时发现问题或是做一些统计。所有节点都可以使用 async-helper 异步调用一个写日志的方法,而执行这个写日志的方法的进程只需要在一台机器上启动就可以了,这样所有节点的日志就都实时掌握在手里了。

做过微信公众号开发的都知道,腾讯微信可以将用户的消息推送到我们的服务器,如果我们在 5s 内未及时响应,腾讯微信会重试 3 次,其实这就是消息队列的应用,使用 async-helper 可以轻松的做和这一样的事情。

得益于 RabbitMQ,你可以轻松的横向扩展你的消费者进程的能力,因为 RabbitMQ 天生就支持集群部署,你可以轻松的启动多个消费者进程,或是将消费者进程分布到多台机器上。

如果 RabbitMQ 服务不可用怎么办呢?部署 RabbitMQ 高可用服务是容易的,对外提供单一 IP,这个 IP 是个负载均衡,背后是 RabbitMQ 集群,负载均衡承担对后端集群节点的健康检查。

async-helper 能否承受高并发请求?async-helper 生产者使用的是短连接,也就说在你的 HTTP 还没有响应浏览器的时候 async-helper 就已经结束了工作,你连接 RabbitMQ 的时间是百分之百小于 HTTP 请求的时间的,换言之,只要 RabbitMQ 承受并发的能力超过你的 HTTP 服务的承受并发的能力,RabbitMQ 就永远不会崩,通过横向扩展 RabbitMQ 很容易做到的。

和传统 PHP 相比

对任何 PHP 方法通过反射进行异步执行;

高可用,执行方法进入消息队列,可持久化,即使服务器宕机,执行任务也不丢失;

高可用,对异常可以进行不限次数和时间的重试,重试次数和时间可配置;

支持对多个异步方法包含在事务中执行,支持回滚事务;

方法的参数类型支持除资源类型(resource)和回调函数(callable)外的任意类型的参数;

得益于 AMQP,异步方法可以承受高并发、高负载,支持集群部署、横向扩展;

低延时,实测延时时间 0.016 ~ 0.021s;

适用于:日常数据库操作、日志收集、金融交易、消息推送、发送邮件和短信、数据导入导出、计算大量数据生成报表;

以上就是PHP异步进程async-helper实例详解的详细内容!

「微信小程序」PHP异步进程async-helper实例详解的更多相关文章

  1. 微信小程序 PHP后端form表单提交实例详解

    微信小程序php后端form表单 https://www.cnblogs.com/tdalcn/p/7092716.html 1.小程序相对于之前的WEB+PHP建站来说,个人理解为只是将web放到了 ...

  2. 对于前端,「微信小程序」其实不美好

    微信小程序开放公测了,9月底我曾经写过一篇 「微信小程序」来了,其中最后一句:"谢天谢地,我居然还是个前端". 这种火爆的新事物总是令人激动,感谢这个时代. 但是,当我真作为开发者 ...

  3. 「前端开发者」如何把握住「微信小程序」这波红利?

    由于前两周一直在老家处理重要事情,虽然朋友圈被「微信小程序」刷爆了,但并没有时间深入了解. 昨天回广州之后,第一件事情就是把「微信小程序」相关的文章.开发文档.设计规范全部看了一遍,基本上明白了「微信 ...

  4. 「微信小程序」有哪些冲击与机会?

    昨天晚上相信大家的朋友圈被「微信小程序」刷屏了,这影响力赶上了国务院出台新政策一样,足以说明微信在中国的影响力之大. 然后今天公号后台一大堆人问我怎么看这件事,不少人非常忧虑,仿佛自己将要失业一样. ...

  5. 「微信小程序」来了

    ps:微信APP Store.微信小程序.微信应用号都是指同一个事情. 苦逼程序猿刚下班到家,还没来得及洗漱,收到条小道消息的推送.于是我有气无力的拿着手机点开了这条推送消息,映入眼帘的就是这张封面图 ...

  6. 微信小程序 WXML、WXSS 和JS介绍及详解

    前几天折腾了下.然后列出一些实验结果,供大家参考. 百牛信息技术bainiu.ltd整理发布于博客园 0. 使用开发工具模拟的和真机差异还是比较大的.也建议大家还是真机调试比较靠谱. 1. WXML( ...

  7. 微信小程序官方示例 官方weui-wxss下载于安装 详解

    1.小程序示例源码:https://github.com/wechat-miniprogram/miniprogram-demo 2.微信 weui下载地址:https://github.com/we ...

  8. 微信小程序页面跳转方法和携带参数详解

    1.页面跳转方式     (1)标签跳转   open-type的属性值对应api里的用法即wx.的用法   1 <navigator url="/page/navigate/navi ...

  9. 微信小程序中支持es7的async语法

    最近在原生的微信小程序项目中需要把原来es6的promise方法改成es7的async await,这样代码看起来更直观,也方便以后的兄弟维护,但是改了代码之后项目就报错了. 提示的错误是:regen ...

随机推荐

  1. Mac里用终端ssh远程连接Centos服务器

    在mac终端下输入 ssh -l root *.*.*.* 就可以远程连接Centos服务器了,端口没变还是:22 如果改变端口用下面方法输入: ssh -p 448(你改变的端口) -l root( ...

  2. C++多线程编程(教程+Demo)

    下载地址:C++多线程编程(教程+Demo) Win32 SDK函数支持进行多线程的程序设计,并提供了操作系统原理中的各种同步.互斥和临界区等操作.Visual C++ 6.0中,使用MFC类库也实现 ...

  3. 一步一步pwn路由器之栈溢出实战

    前言 本文由 本人 首发于 先知安全技术社区: https://xianzhi.aliyun.com/forum/user/5274 本文以 DVRF 中的第一个漏洞程序 stack_bof_01 为 ...

  4. PHP array_flip() array_merge() array+array的使用总结

    array_flip(array); //传递一个数组参数,对该数组的键.值进行翻转 例如: $a = array( 'a', 'b', 'c' ); print_r(array_flip($a)); ...

  5. Linked List Cycle 判断一个链表是否存在回路(循环)

    Given a linked list, determine if it has a cycle in it. Follow up:Can you solve it without using ext ...

  6. error:将字符串转换为 uniqueidentifier 时失败

    sql server查询中出现 将字符串转换为 uniqueidentifier 时失败异常 原因为id设置为uniqueidentifier 字段,在where查询时需要做转换cast(id as ...

  7. SQL Server ->> 高可用与灾难恢复(HADR)技术之 -- Windows故障转移群集

    WSFC 群集 (WSFC cluster)“Windows Server 故障转移群集”(WSFC) 群集是一组独立的服务器,它们共同协作以提高应用程序和服务的可用性. 故障转移群集实例 (Fail ...

  8. NexusFile(文件管理器)

    NexusFile是一款来自于韩国的文件管理器,类似于TotalCommander,拥有两个并排的文件夹窗口. NexusFile软件的特性如下: 基本功能:复制/移动, 复制/剪切/粘贴, 删除/擦 ...

  9. CSS边框长度控制

    以前需要边框长度比容器小一些时,我用div嵌套.后来发现伪类在实现这个效果时很方便,只需要一个div就够了,另外调整padding和margin都不会很麻烦. <div class=" ...

  10. nginx+php+swoole安装记录

    领了台阿里服务器1vCPU 1G,做下测试研究. 系统 centos7,使用yum安装. Nginx yum install nginx ##开启nginx service nginx start 安 ...