swPromise

PHP纯异步非阻塞框架
授权协议 MIT
开发语言 PHP
所属分类 程序开发、 高性能网络开发库
软件类型 开源软件
地区 国产
投 递 者 宗政金鹏
操作系统 跨平台
开源组织
适用人群 未知
 软件概览

swPromise,基于swoole的PHP promise框架

一个业务请求可能会串行的请求多个接口A-> B-> C,此时如果接口B的响应时间较慢(关键性业务,需要有预先准备好的超时等待时间),并导致请求整体的时间过长,严重降低系统的响应能力。考虑到这个业务场景下,进展的主要时间用在等待网络io返回。的方式,逐渐极大的提升服务的爆炸(NodeJS的优势)。

如果某接口响应时间超过往常,会导致php-fpm过程数急剧上升,从而导致大量cpu资源浪费在进程调度上面,甚至导致服务崩溃。swPromise框架是为了解决该问题而开发的。

传统上,为进行初始化调用,会在代码中实现大量的替换函数,导致代码发生性与可维护性的急剧下降。为了解决这个问题,主流方案有以下几种:

  • 自定义事件式方案

  • 承诺/推迟

  • 高阶函数修正改局部函数

  • 协程(发电机)

Swoole是PHP语言的高级网络通信框架,提供了PHP语言的异步多线程服务器。swoole采用自定义事件样式方案,为我们提供网络层基本封装。基于swoole,可以扩展出业务层的模拟开发框架。

tsf(腾讯服务器框架)是腾讯公司推出的PHP协程方案,基于Swoole + PHP Generator实现的协程。该框架使用协程模式,基于swoole与swoole框架开发。实现了真正的异步非多重开发模式,同时具有极高的性能。其核心代码来源于该文章协同多任务处理使用协同程序(在PHP中!)。TSF使用了较为复杂的用户态任务调度逻辑,在腾讯的OpenAPI中使用。另外由于使用了swoole框架,略显重量级。

该类实现了基本的然后的方法,并通过对Promise流程的延迟计算,保证了流程的动态控制能力。该框架是一个非常基础的Web框架。 ,目前仅实现通用Future(通用延迟计算),HttpClientFuture,ResponseFuture三个连续计算类。

该框架需要配合Swoole master版本使用,编译参数。/configure--enable-async-httpclient,开启初始化http client。

演示代码

class Handler_Index extends \Core\Handler{
    public function run($request, $response){
        Promise::create ( Model::getUserInfo ( 'user1', 'haha' ) )
            ->then (function(&$promise){
                $user1 = $promise->get('user1');
                if($user1){
                    return Model::getUserInfo ( 'user2', 'haha2' )
                            ->then(function(&$promise){
                                $user2 = $promise->get('user2');
                                $promise->accept(['user3'=>$user2['body']]);
                            });
                }
                else $promise->accept();
            })
            ->then ( Model::getUserInfo ( 'user4', 'haha4' ) )
            ->then ( Model::getUserInfo ( 'user5', 'haha5' ) )
            ->then ( new ResponseFuture ($response) )
            ->start ( new PromiseContext () );
    }
}

这段流程表明了,先获取haha这个用户的信息,写入上下文的user1字段中。 如果获取到了数据,再获取haha2这个用户的信息,写入上下文user2字段中。 并将user2的body字段放入user3字段中。然后获取haha4和haha5的信息。 最后将所有数据输出到网页。

可以看到,在第一个then中,通过if条件返回promise对象,实现了对异步流程的动态控制。 同样的,整个流程通过then串联起来,已经较为接近同步代码的书写了。 而使用回调的方式,代码会变得极为恐怖。

并行请求

class Handler_Index extends \Core\Handler{
    public function run($request, $response){
        Promise::create([
            Model::getUserInfo ( 'user1', 'haha' ),
            Model::getUserInfo ( 'user2', 'haha2' ),
        ])->then(
            new ResponseFuture ($response)
        )->start(new PromiseContext ());
    }
}

这个请求并行获得haha与hah2两个用户的数据,分布放到user1和user2两个字段中。

存在问题

其中Handler_Sync实现的就是该框架同步的使用方式。 另外,目前reject方法以及异常处理流程均没有实现,有兴趣的朋友可以自行扩展。

目前有一个比较严重的bug,如果大量http request没有完成就自行中断的话,会导致swoole http server发生错误,从而退出。在swoole前面放一个nginx就可以解决问题。

测试方法

启动

php run.php

测试:

ab -n 10000 -c 100 "http://localhost:9502/async"
ab -n 10000 -c 100 "http://localhost:9502/sync"

经过测试,在后端接口响应性能有问题的情况下,swPromise 可以同时处理大量连接,用很低的 cpu 负载等待接口数据返回。

 相关资料
  • 我认为下面的流量链将通过事件循环放置/执行(像JS)。因此,运行下面的代码将首先打印阻塞循环&然后将执行通量链。 但是,整个通量总是先执行,然后才移动到循环。[我确实有一些语句正在阻塞。但是有两个阶段] 当我们使用reactor时,通过使用一些调度程序来实现异步/非阻塞行为的唯一方法? 如果我不使用任何调度器,并让代码使用当前线程执行,那么即使对于IO密集型应用程序,使用WebFlux而不是Spr

  • 本文向大家介绍请你说一下阻塞,非阻塞,同步,异步相关面试题,主要包含被问及请你说一下阻塞,非阻塞,同步,异步时的应答技巧和注意事项,需要的朋友参考一下 参考回答: 阻塞和非阻塞:调用者在事件没有发生的时候,一直在等待事件发生,不能去处理别的任务这是阻塞。调用者在事件没有发生的时候,可以去处理别的任务这是非阻塞。 同步和异步:调用者必须循环自去查看事件有没有发生,这种情况是同步。调用者不用自己去查看

  • 实时的web特性通常需要为每个用户一个大部分时间都处于空闲的长连接. 在传统的同步web服务器中,这意味着需要给每个用户分配一个专用的线程,这样的开销是十分巨大的. 为了减小对于并发连接需要的开销,Tornado使用了一种单线程事件循环的方式. 这意味着所有应用程序代码都应该是异步和非阻塞的,因为在同一时刻只有一个操作是有效的. 异步和非阻塞这两个属于联系十分紧密而且通常交换使用,但是它们并不完全

  • 从进程调度谈起 现代操作系统(如 Windows、Linux 等)都是分时系统。分时系统允许同时允许多个任务,但实际上,由于一台计算机通常只有一个 CPU,所以不可能真正地同时运行多个任务。这些进程实际上是轮番运行,每个进程运行一个时间片。由于时间片通常很短,用户不会感觉到,所以这些进程看起来就像是同时运行。 每个进程的时间片由操作系统完成初始化,所有进程轮番地执行相应的时间。具体下一个时间片轮到

  • 本文向大家介绍java 中同步、异步、阻塞和非阻塞区别详解,包括了java 中同步、异步、阻塞和非阻塞区别详解的使用技巧和注意事项,需要的朋友参考一下 java 中同步、异步、阻塞和非阻塞区别详解 简单点说: 阻塞就是干不完不准回来,一直处于等待中,直到事情处理完成才返回; 非阻塞就是你先干,我先看看有其他事没有,一发现事情被卡住,马上报告领导。 我们拿最常用的send和recv两个函数来说吧..

  • 本文向大家介绍详解socket阻塞与非阻塞,同步与异步、I/O模型,包括了详解socket阻塞与非阻塞,同步与异步、I/O模型的使用技巧和注意事项,需要的朋友参考一下 socket阻塞与非阻塞,同步与异步 1. 概念理解 在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式: 同步/异步主要针对C端: 同步: 所谓同步,就是在

  • 问题内容: 有没有一种干净的方法可以以Java异步,非阻塞的方式(例如,状态机,而不是1个查询= 1个线程)来解析DNS查询(通过主机名获取IP)-我想同时运行数万个查询,但是不能运行数万个线程)? 到目前为止,我发现了什么: 标准实现正在阻塞,并且看起来标准Java库缺少任何非阻塞实现。 批量解决DNS问题也讨论了类似的问题,但是找到的唯一解决方案是多线程方法(即,一个线程在每个给定的时间段内仅

  • 问题内容: 尝试为自己总结这两个概念之间的区别(因为当我看到人们在一句话中同时使用这两个概念时,我感到非常困惑,例如“ Non-blocking async IO”,我试图弄清楚它是做什么的)意思)。 因此,以我的理解,无阻塞IO是操作系统的主要机制,如果有任何可用数据,则该OS处理IO,否则仅返回错误/不执行任何操作。 在异步IO中,您仅提供回调,当数据可用时,系统将通知您的应用程序。 那么,实