前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >workerman5.0 异步非阻塞HTTP协程客户端

workerman5.0 异步非阻塞HTTP协程客户端

作者头像
Tinywan
发布2024-04-19 18:37:21
1470
发布2024-04-19 18:37:21
举报
文章被收录于专栏:开源技术小栈开源技术小栈

概述

Workerman 5.0 版本中的异步HTTP协程客户端组件是一个基于PHP协程的高性能HTTP客户端,它能够充分利用PHP的异步特性来提高HTTP请求的效率和性能。这个组件允许开发者在编写PHP代码时,以同步的方式发送异步HTTP请求,从而使得编写的代码更加简洁易懂,同时也能够处理大量的并发请求。

这个组件的特点包括:

  • 异步非阻塞:所有的请求和响应都是异步进行的,不会阻塞主线程,这意味着可以同时处理多个HTTP请求和响应。
  • 内置连接池:为了提高效率和性能,该组件内置了连接池,可以复用TCP连接,减少建立和关闭连接的开销。
  • 符合PSR-7规范:消息请求和响应都符合PSR-7规范,这使得它能够与遵循该规范的其他PHP组件和库无缝集成。
  • 支持多种协议:除了HTTP和HTTPS协议,该组件还支持WebSocket、WSS等协议,使其能够应对更多的应用场景。

安装

注意:5.0需要PHP版本大于8.2.4及以上版本

通过php -v查看你当前PHP版本信息

代码语言:javascript
复制
php -v
PHP 8.2.18 (cli) (built: Apr 11 2024 19:20:54) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.18, Copyright (c) Zend Technologies
    with Zend OPcache v8.2.18, Copyright (c), by Zend Technologies
workerman 5.0 安装
代码语言:javascript
复制
composer require workerman/workerman v5.0.0-beta.7
revolt/event-loop 安装

Revolt是什么?

Revolt是并发PHP应用程序的坚如磐石的事件循环。通常的PHP应用程序将大部分时间花在等待I/O上。虽然PHP是单线程的,但可以使用协作多任务来允许并发性,方法是使用等待时间来做不同的事情。

PHP的传统同步执行流程很容易理解。一次只做一件事。如果查询数据库,则发送查询并等待数据库服务器的响应。一旦你有了答案,你就可以开始做下一件事。

ReactPHP和其他库已经在PHP中提供了很长一段时间的协作多任务。然而,它们的事件驱动特性与许多现有的接口不兼容,需要不同的思维模型。PHP 8.1内置了fibers,它提供了协作多线程。调用可以是异步的,没有promise或回调,同时仍然允许非阻塞I/O

每个使用协同多任务的应用程序都需要一个调度器(也称为事件循环),这个包提供了这个调度器。Revolt是结合了React和ReactPHP的事件循环实现的多年经验的结果。然而,它并不是一个用于编写并发PHP应用程序的成熟框架,而只是提供了必要的公共基础。不同的(强烈的)固执己见的库可以在它的基础上构建,React和ReactPHP将继续共存。

Revolt 支持事件

  • Defer 回调在事件循环的下一次迭代中执行。如果有延迟调度,事件循环不会在迭代之间等待。
  • Delay 在指定的秒数后执行回调。秒的分数可以表示为浮点数。
  • Repeat 在指定的秒数后重复执行回调。秒的分数可以表示为浮点数。
  • Stream readable 当流上有数据要读取或连接关闭时,将执行回调。
  • Stream writable 当写缓冲区中有足够的空间来接受要写入的新数据时,就会执行回调。
  • Signal 当进程从操作系统接收到特定信号时执行回调。

安装

代码语言:javascript
复制
composer require revolt/event-loop
workerman/http-client安装

workerman/http-client是一个异步http客户端组件。所有请求响应异步非阻塞,内置连接池,消息请求和响应符合PSR7规范。更多了解:https://www.workerman.net/doc/workerman/components/workerman-http-client.html

代码语言:javascript
复制
composer require workerman/http-client

编写代码

http.php伪代码

代码语言:javascript
复制
<?php
/**
 * @desc 伪代码
 * @author Tinywan(ShaoBo Wan)
 * @date 2024/11/14 15:14
 */
declare(strict_types=1);

use Workerman\Worker;

require_once '../vendor/autoload.php';

try {
    $worker = new Worker();
    $worker->onWorkerStart = function () {
        $http = new Workerman\Http\Client();

        $response = $http->get('https://www.tinywan.com/');
        var_dump($response->getStatusCode());
        echo $response->getBody() . PHP_EOL;

        $response = $http->post('https://www.tinywan.com/', ['key1' => 'value1', 'key2' => 'value2']);
        var_dump($response->getStatusCode());
        echo $response->getBody() . PHP_EOL;

        $response = $http->request('https://www.tinywan.com/', [
            'method' => 'GET',
            'version' => '1.1',
            'headers' => ['Connection' => 'keep-alive'],
            'data' => ['key1' => 'value1', 'key2' => 'value2'],
        ]);
        echo $response->getBody() . PHP_EOL;
    };
    Worker::runAll();
} catch (Throwable $throwable) {
    var_dump($throwable->getMessage());
}

启动服务

代码语言:javascript
复制
/var/www/workerman5.x-demo/coroutine # php http.php start
Workerman[http.php] start in USER mode
---------------------------------------- WORKERMAN -----------------------------------------
Workerman version:5.0.0-beta.7    PHP version:8.2.18     Event-loop:Workerman\Events\Revolt
----------------------------------------- WORKERS ------------------------------------------
proto   user            worker          listen          processes    state            
tcp     root            none            none            1             [OK]            
--------------------------------------------------------------------------------------------
Press Ctrl+C to stop. Start success.

注意:这里使用Event-loop:Workerman\Events\Revolt事件

执行结果

代码语言:javascript
复制
int(200)
int(405)
int(200)

http-client 协程异步并发

代码语言:javascript
复制
<?php
/**
 * @desc 伪代码
 * @author Tinywan(ShaoBo Wan)
 * @date 2024/11/14 15:14
 */
declare(strict_types=1);

use Workerman\Worker;
use \Workerman\Connection\TcpConnection;
use \Workerman\Protocols\Http\Request;

require_once '../vendor/autoload.php';

// 创建一个Worker监听8217端口,使用http协议通讯
$httpWorker = new Worker("http://0.0.0.0:8217");

// 启动8个进程对外提供服务
$httpWorker->count = 8;

// 接收到浏览器发送的数据时回复给浏览器
$httpWorker->onMessage = function (TcpConnection $connection, Request $request) {
    $http = new \Workerman\Http\Client();

    $count = 50;
    $result = [];
    while ($count--) {
        $startTime = microtime(true);
        echo '开始时间:' . $startTime . PHP_EOL;
        $response = $http->get('https://api.tinywan.com/systems/website');
        $endTime = microtime(true);
        echo '结束时间:' . $endTime . PHP_EOL;
        $result[] = sprintf('第%d个 | 耗时%s秒 | 状态码%d', $count, $endTime - $startTime, $response->getStatusCode());
    }
    $connection->send(json_encode($result));
};

// 运行worker
Worker::runAll();

执行结果(未完,待续……)

代码语言:javascript
复制
[
    "第49个 | 耗时0.53055596351624秒 | 状态码200",
    "第48个 | 耗时0.11245107650757秒 | 状态码200",
    "第47个 | 耗时0.13903284072876秒 | 状态码200",
    "第46个 | 耗时0.21533107757568秒 | 状态码200",
    "第45个 | 耗时0.11252999305725秒 | 状态码200",
    "第44个 | 耗时0.15401482582092秒 | 状态码200",
    "第43个 | 耗时0.10678505897522秒 | 状态码200",
    "第42个 | 耗时0.099571943283081秒 | 状态码200",
    "第41个 | 耗时0.12561202049255秒 | 状态码200",
    "第40个 | 耗时0.10563802719116秒 | 状态码200",
    "第39个 | 耗时0.11354088783264秒 | 状态码200",
    "第38个 | 耗时0.1011688709259秒 | 状态码200",
    "第37个 | 耗时0.20793986320496秒 | 状态码200",
    "第36个 | 耗时0.1089551448822秒 | 状态码200",
    "第35个 | 耗时0.092885971069336秒 | 状态码200",
    "第34个 | 耗时0.10161209106445秒 | 状态码200",
    "第33个 | 耗时0.20717096328735秒 | 状态码200",
    "第32个 | 耗时0.20546984672546秒 | 状态码200",
    "第31个 | 耗时0.11044192314148秒 | 状态码200",
    "第30个 | 耗时0.12123489379883秒 | 状态码200",
    "第29个 | 耗时0.11858606338501秒 | 状态码200",
    "第28个 | 耗时0.17020511627197秒 | 状态码200",
    "第27个 | 耗时0.095601081848145秒 | 状态码200",
    "第26个 | 耗时0.11254286766052秒 | 状态码200",
    "第25个 | 耗时0.19883704185486秒 | 状态码200",
    "第24个 | 耗时0.20402407646179秒 | 状态码200",
    "第23个 | 耗时0.10713791847229秒 | 状态码200",
    "第22个 | 耗时0.11914396286011秒 | 状态码200",
    "第21个 | 耗时0.094994068145752秒 | 状态码200",
    "第20个 | 耗时0.10224294662476秒 | 状态码200",
    "第19个 | 耗时0.11380887031555秒 | 状态码200",
    "第18个 | 耗时0.10260701179504秒 | 状态码200",
    "第17个 | 耗时0.28102612495422秒 | 状态码200",
    "第16个 | 耗时0.10411977767944秒 | 状态码200",
    "第15个 | 耗时0.10007786750793秒 | 状态码200",
    "第14个 | 耗时0.095911979675293秒 | 状态码200",
    "第13个 | 耗时0.094711065292358秒 | 状态码200",
    "第12个 | 耗时0.09196400642395秒 | 状态码200",
    "第11个 | 耗时0.10585021972656秒 | 状态码200",
    "第10个 | 耗时0.092756032943726秒 | 状态码200",
    "第9个 | 耗时0.23688101768494秒 | 状态码200",
    "第8个 | 耗时0.20317101478577秒 | 状态码200",
    "第7个 | 耗时0.10062909126282秒 | 状态码200",
    "第6个 | 耗时0.20747685432434秒 | 状态码200",
    "第5个 | 耗时0.11253881454468秒 | 状态码200",
    "第4个 | 耗时0.12536215782166秒 | 状态码200",
    "第3个 | 耗时0.17252016067505秒 | 状态码200",
    "第2个 | 耗时0.12250709533691秒 | 状态码200",
    "第1个 | 耗时0.10875701904297秒 | 状态码200",
    "第0个 | 耗时0.10053586959839秒 | 状态码200"
]

仓库地址:https://github.com/Tinywan/workerman5.x-demo

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2024-04-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 开源技术小栈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 概述
  • 安装
    • workerman 5.0 安装
      • revolt/event-loop 安装
        • workerman/http-client安装
        • 编写代码
        • 启动服务
        • http-client 协程异步并发
        相关产品与服务
        数据库专家服务
        数据库专家服务(Database Expert Service,DBexpert)为您提供专业化的数据库服务。仅需提交您的具体问题和需求,即可获得腾讯云数据库专家的专业支持,助您解决各类专业化问题。腾讯云数据库专家服务团队均有10年以上的 DBA 经验,拥有亿级用户产品的数据库管理经验,以及丰富的服务经验。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档