PRipple:现代化PHP原生协程引擎

转载自微信公众号 《开源技术小栈》

简介

PRipple是一个高性能的原生PHP协程框架,旨在处理高并发、复杂的网络通信和数据操作。项目基于PHP8.1自身的纤程特性实现协程,提供了更加简单易用的API和工具,使得开发者可以轻松地构建高性能的PHP应用。

文档地址

官方文档

特点

  • 高性能: 通过使用原生PHP协程, 大幅提高了应用的并发处理能力
  • 兼容性: 兼容现有的PHP框架和库, 支持在FPM/CLI环境下使用
  • 易于使用: 100%的PHP代码实现,无需更多的学习成本,提供了简单易用的API,
  • 协程调度: 使用 Fiber 和 Promise 机制, 实现了高效的协程调度。
  • 异步I/O: 提供异步的网络和文件I/O操作,避免阻塞。
  • 高并发处理: 支持高并发请求处理,适用于实时应用和高负载场景。
  • 易于集成: 可以与传统项目无缝集成,提供简单的安装和使用指南。

特性

  • 原生:基于PHP原生协程实现,100%的PHP代码率, 无需第三方扩展, 所有函数都如你所知的方式工作, 无需额外的学习成本
  • 生态:保持所有组件的原生性, 提供丰富的生态支持, 与绝大多数的composer包兼容, 无需担心生态问题
  • 集成:传统的PHP框架支持高度集成, 无缝支持Laravel, Symfony, ThinkPHP, Yii等主流框架, 无需改动原有代码, 支持FPM环境使用

运行机制 Runtime

介绍

在PRipple中,所有define的异步闭包都由EventLoop驱动, EventLoop将会在恰当的时候运行指定事件, 开发者无需过于关心EventLoop的处理机制, 只需做好流程的控制, 不同的闭包可能会在不同的上下文空间中被执行, 开发过程中应该注意这些上下文空间的约束

PRipple对任何一个闭包的发生运行时都会特别声明与严格把控, 所有对于插件/组件的开发者也应该关心这点,防止闭包发生进程/纤程逃逸, 运行黑洞的情况

主程运行时

框架的的使用者几乎不用关心该运行时,因为开发者的代码通常运行在事件运行时与协程运行时上下文

进程的入口点, 构建PRipple的过程即是主程运行时, 它发生在PRipple驱动机之前, 以Laravel的入口文件为例子

<?php
use Illuminate\Http\Request;
define('LARAVEL_START', microtime(true));
if (file_exists($maintenance = __DIR__.'/../storage/framework/maintenance.php')) {
    require $maintenance;
}
require __DIR__.'/../vendor/autoload.php';

//TODO: 主程运行时
\P\async(function(){
    //TODO: 协程运行时,包括 Laravel中间件/服务提供者/控制器 等运行过程都处于协程序空间中
    (require_once __DIR__.'/../bootstrap/app.php')
        ->handleRequest(Request::capture());
});

# 启动PRipple
\P\tick();

安装

Composer 安装

composer require cclilshy/p-ripple-drive

Webman 配置

配置config/server.php文件

<?php
return [
    //...
    'event_loop' => \Psc\Drive\Workerman\PDrive::class,
];

使用方法

手动创建

public function index(Request $request): string
{
    $handle = new \Psc\Plugins\Guzzle\PHandler([
       'pool' => 1 // 是否启用Http长连接
    ]);
    $client = new \GuzzleHttp\Client(['handle' => $handle]);

    // 发送请求(即使该请求耗时很长, 也不会堵塞当前进程的其他请求)
    $response = $client->get('http://www.baidu.com');
    return $response->getBody()->getContents();
}

全局使用(荐)

public function index(Request $request): string
{
    $client = \P\Plugin::Guzzle();

    // 发送请求(即使该请求耗时很长, 也不会堵塞当前进程的其他请求)
    $response = $client->get('http://www.baidu.com');
    return $response->getBody()->getContents();
}

效果演示

use function P\async;
use function P\await;

/**
 * @desc 方法描述
 * @param Request $request
 * @return string
 * @author Tinywan(ShaoBo Wan)
 */
public function index(Request $request): string
{
    for ($i = 0; $i < 100; $i++) {
        async(function () use ($i) {
            $response = await(\P\Plugin::Guzzle()->getAsync('https://www.qq.com/'));
            $time = microtime(true);
            $responseStatusCode = $response->getStatusCode();
            var_dump("[{$time}] request {$i} status: {$responseStatusCode}");
        });
    }
    return '开源技术小栈!';
}
posted @ 2024-08-07 09:50  cclilshy  阅读(302)  评论(0)    收藏  举报