PHP HTTP客户端-Guzzle原理解析

本文适合寻找PHP HTTP客户端库,或者对于Guzzle的使用和实现原理比较感兴趣的同学阅读,需要具备一定的PHP基础知识。

一、背景

在PHP后台开发过程中,经常会遇到模块间需要通过HTTP通信的情形。PHP语言本身只提供了socket操作的接口,并未提供HTTP相关操作的接口。许多现有的实现采用curl扩展充当HTTP Client与HTTP Server通信,但仍需自己封装curl的接口。有鉴于此,本文介绍一款流行的PHP HTTP Client客户端---Guzzle(https://github.com/guzzle/guzzle/)的用法,深入分析其底层实现原理。

二、Guzzle用法

例如使用Guzzle访问http://www.baidu.com的代码:

<?php$client = new \GuzzleHttp\Client();
$response = $client->request('GET', 'http://www.baidu.com', ["timeout" => 3000
]);echo $response->getStatusCode(), "\n";
echo $response->getBody();

接口封装是不是十分简单?只需要关心请求方法,目标url和请求的选项即可快速上手。同时,Guzzle还支持异步请求方式:

<?phpuse GuzzleHttp\Exception\RequestException;
use Psr\Http\Message\ResponseInterface;$client = new \GuzzleHttp\Client();
$promise = $client->requestAsync('GET', 'http://www.baidu.com');
$promise->then(function (ResponseInterface $res) {echo $res->getStatusCode() . "\n";echo $res->getBody();return $res;},function (RequestException $e) {echo $e->getMessage() . "\n";echo $e->getRequest()->getMethod();}
)->wait();

基于异步请求,Guzzle还实现了并发请求,关于Guzzle的具体使用方法可以参考其中文文档http://guzzle-cn.readthedocs.io/zh_CN/latest/index.html。

三、Guzzle实现原理

1.client构造

GuzzleHttp\Client类构造函数声明为:

public function __construct(array $config = [])

$config配置使得用户可以根据需要配置一切可以配置的选项,包括allowredirects、auth、connecttimeout、proxy等。除此之外,还可以自定义请求的处理函数handler,方便应用程序扩展,handler接口规范为:

function handler($request, array $options);

处理成功时,接口返回Psr\Http\Message\ResponseInterface;失败时返回GuzzleHttp\Exception\RequestException异常。

默认情形下,GuzzleHttp\HandlerStack::create会创建请求处理函数

public static function create(callable $handler = null)
{$stack = new self($handler ?: choose_handler());$stack->push(Middleware::httpErrors(), 'http_errors');$stack->push(Middleware::redirect(), 'allow_redirects');$stack->push(Middleware::cookies(), 'cookies');$stack->push(Middleware::prepareBody(), 'prepare_body');return $stack;
}

create函数以堆栈的形式创建了一系列的处理函数,包括http异常、重定向、cookie和prepare_body。处理函数返回的函数闭包为:

return function (callable $handler) {return function ($request, array $options) use ($handler) {...};
};

函数入参为handler,返回一个新的handler,这样可以将所有的处理函数链接在一起,最终生成一个符合handler接口规范的函数.

choose_handler函数选择stack中的起始handler,选择策略为:

  • 扩展自带curl_multi_exec和curl_exec函数则根据$options中的synchronous选项决定,empty(synchronous)为false则使用CurlHandler,否则使用CurlMultiHandler

  • 扩展只有curl_exec函数则使用CurlHandler

  • 扩展只有curl_multi_exec函数则使用CurlMultiHandler

最后,如果php.ini中开启了allow_url_fopen,则根据$options中的stream选项决定,empty(stream)为false则使用StreamHandler。

2.client调用request方法

request方法实现为:

public function request($method, $uri = '', array $options = [])
{$options[RequestOptions::SYNCHRONOUS] = true;return $this->requestAsync($method, $uri, $options)->wait();
}

由此可见,request事实上是采用了requestAsync异步方法+wait来完成的,也就是异步转同步。

2.1 requestAsync

requestAsync将请求信息包装成Psr7\Request对象,然后调用

transfer(RequestInterface $request, array $options)

transfer函数最终返回Promise\promise_for($handler($request, $options)); 其中$handler即为构造函数中所设置的stack,stack中存放一系列的请求处理函数。 HandlerStack的处理函数为:

public function __invoke(RequestInterface $request, array $options)
{$handler = $this->resolve();return $handler($request, $options);
}

resolve方法解析整个stack,返回一个包装后的handler,包装策略为按照出栈顺序包装,也就是

foreach (array_reverse($this->stack) as $fn) {$prev = $fn[0]($prev);
}

典型的中间件模型,所有的处理函数串接在一起了。请求经由http_errors、allow_redirects等处理之后到达Curl,执行真正的网络交互。

  • 对于同步的handler如CurlHandler,在此处会执行curl_exec发起请求,最终返回的是FulfilledPromise对象或RejectedPromise对象,代表请求已经处理完毕。

  • 对于异步的handler比如CurlMultiHandler,在此处并不会执行curl_multi_exec,而是返回一个promise对象,里面注册了需要等待执行的curl_multi_exec。

Curl Handler处理完成之后,往上回溯,在Allow_redirects和Http_errors部分会进入then方法,最终返回的结果都是promise对象。

2.2 wait

请求发送完毕,进入promise的wait操作,最终会执行promise的$waitFn函数。

  • 对于CurlMultiHandler,$waitFn即执行curl_multi_exec进行网络交互,然后调用resolve方法将response对象传递到then方法的$onFulfilled函数。

  • 对于CurlHandler,直接利用resolve将response对象传递到$onFulfilled函数。

这样,异步的then方法设置的回调就可以接收到response了。 then方法最终返回response,这个对象又可以作为返回值返回,这样同步的wait就可以通过返回值来获取response对象了。

四、总结

本文重点介绍了Guzzle同步和异步请求的实现原理,除此之外,Guzzle还提供了并行请求,请求pool等实现,读者可以在此基础上继续深入。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/56646.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

客户端日志和异常处理

目录 一. 使用Serilog结构化日志记录日志信息二. 捕获全局异常三. 使用AOP统一处理异常 一. 使用Serilog结构化日志记录日志信息 Serilog包的引用和使用语法都可以在网上找到&#xff08;https://github.com/serilog/serilog/wiki/&#xff09;&#xff0c;不再赘述&#xff0…

深入浅出Transformer

作者&#xff1a;麦克船长 链接&#xff1a;https://www.zhihu.com/question/471328838/answer/2864224369 来源&#xff1a;知乎 著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。 如果说「从浅入深」理解 Transformer&#xff0c;逐渐要到…

自然语言处理 Transformer 模型

一、Transformer 模型出现之前的NLP 语言模型 1、N 元文法语言模型 1.1、马尔科夫假设&#xff08;Markov Assumption&#xff09;与 N 元文法语言模型&#xff08;N-gram Language Model&#xff09; 下一个词出现的概率只依赖于它前面 n-1 个词&#xff0c;这种假设被称为马尔…

一文速览大语言模型在分子领域中的探索

随着 ChatGPT 的快速崛起&#xff0c;大型语言模型&#xff08;LLM&#xff09;已经在人类语言建模领域展示出了其非凡的能力。无论是证明数学公式、编写代码&#xff0c;还是以不同的风格创作诗歌&#xff0c;LLM 都能胜任。然而&#xff0c;尽管 LLM 在人类语言的掌握上已达到…

“AI+教育”:景联文科技高质量教育GPT题库助力教学创新

去年年底&#xff0c;OpenAI推出ChatGPT&#xff0c;掀起AI热潮&#xff0c;教育作为“AI”应用落地的关键场景&#xff0c;再次受到广泛关注。 “AI教育”的快速发展&#xff0c;是受到技术、需求和政策三重因素共同驱动的结果。 在技术方面&#xff0c;随着人工智能技术的不断…

对话系统文献综述

一、简介 论文&#xff1a;https://arxiv.org/pdf/1711.01731.pdf 该论文对对话系统进行了综述&#xff0c;并讨论了今后可能的研究方向。 目前的对话系统大致被分成两类&#xff1a; 1 任务导向的对话系统 任务为导向的对话系统是帮助用户去完成特定任务&#xff0c;比如找…

如何利用大数据分析技术预测员工离职?

为什么我们要对员工离职进行预测&#xff0c;因为它会帮助公司减少员工离职成本的消耗。 本文为美国肯尼索州立大学刘丽媛&#xff08;Lilian&#xff09;在HR成长部落2019年6月23日的线下活动分享文字实录&#xff0c;希望对大家在数据分析在HR领域的应用有所启发。 大家好&am…

Python员工离职数据分析

Python员工离职数据分析 import pandas as pd import seaborn as sns import matplotlib.pyplot as plt import warnings warnings.filterwarnings(ignore)# 数据全显示 pd.set_option(display.max_columns, None) # 颜色 colors sns.color_palette() # 数据精度 pd.set_opti…

从数据分析,看公司员工流失率分析报告

一、概述&#xff1a; 1、员工离职和员工流失率的概念&#xff1a; 员工离职&#xff1a;员工被辞退及辞职、不续签的情况 员工流失率&#xff08;离职率&#xff09;&#xff1a;公司离职的员工人数/&#xff08;入职人数最初原有人数&#xff09;*100% 例如&#xff1a;月…

数据分析——员工离职预测

员工离职预测 一. 题目描述二. 数据说明三. 步骤实现1.导入并查看2.数据探索性分析3.数据处理4.模型分析5.结果分析(1) 可视化的结果分析(2&#xff09;特征选择结果分析(3)多模型交叉验证结果分析 一. 题目描述 员工是否准备离职是困扰用人单位的问题&#xff0c;其关系到单位…

逾2500名选手竞跑乌鲁木齐冰雪马拉松

中新社乌鲁木齐1月13日电(记者 孙亭文) 2019乌鲁木齐丝绸之路冰雪马拉松(简称“冰马”)13日鸣枪开跑&#xff0c;逾2500名跑友在天山山麓的“冰天雪地”中竞跑。 1月13日&#xff0c;2019乌鲁木齐丝绸之路冰雪马拉松在乌鲁木齐市城南的天山脚下鸣枪开跑&#xff0c;逾2500名跑友…

html 跑步比赛小游戏,疯狂趣味跑步竞赛3D

疯狂趣味跑步竞赛3D是一款跑酷类型的休闲游戏&#xff0c;游戏在整体画面上搭配了最新的技术&#xff0c;使得游戏画面看起来非常华丽&#xff0c;人物的建模也很可爱。玩家在游戏中可以在各种风格的跑道上进行比赛&#xff0c;还可以在线跟别的玩家进行匹配。喜欢这款游戏的快…

oracle计算日期倒计时,时间倒算回去到了哪里?│机械倒数计时码表

Laura Lan蓝思晴 《大寫的蘿菈》主笔 华语圈知名钟表珠宝评论家&#xff0c;专精机械钟表赏析&#xff0c;亦对珠宝、生活、文化与艺术等各领域皆有着独到的见解。创办《引想力工作室》从事专业文案、顾问、讲习等工作。 所有不能实现的&#xff0c;制表大师们都曾经挖空心思研…

茂名天源石化等项目开工 石化业高质量发展看广东

目前来看&#xff0c;广东省已经拥有诸多国外化工巨头、大型民营炼化企业和不少国企的炼化项目&#xff0c;成为很多石化企业首选的项目落地基地。“石化业高质量发展看广东”&#xff0c;已经逐渐明朗。今年以来&#xff0c;已有恒力石化(惠州)PTA项目、东华能源(茂名)烷烃资源…

c++并行编程中的“锁”难题

linux服务器开发相关视频解析&#xff1a; 在并行程序中&#xff0c;锁的使用会主要会引发两类难题&#xff1a;一类是诸如死锁、活锁等引起的多线程Bug&#xff1b;另一类是由锁竞争引起的性能瓶颈。本文将介绍并行编程中因为锁引发的这两类难题及其解决方案。 1、用锁来防止…

恒力石化、茂名天源石化等项目开工 2025年广东石化产业营收力争超2万亿

目前来看&#xff0c;广东省已经拥有诸多国外化工巨头、大型民营炼化企业和不少国企的炼化项目&#xff0c;成为很多石化企业首选的项目落地基地。“石化业高质量发展看广东”&#xff0c;已经逐渐明朗。 今年3月31日&#xff0c;广东省发展改革委官网公布《广东省2021年重点建…

Linux中的线程

1.线程的基本概念 2.线程和进程的区别 线程安全 *线程的同步 线程的调度 线程的通信编程思想之多线程与多进程(1)——以操作系统的角度述说线程与进程_阳光日志-CSDN博客_多线程和多进程编程线程是什么&#xff1f;要理解这个概念&#xff0c;须要先了解一下操作系统的一些…

武汉超级计算机中心,加快打造“五个中心” 武汉率先开建人工智能计算中心...

(来源&#xff1a;武汉市发改委) 原标题&#xff1a;加快打造“五个中心” 武汉率先开建人工智能计算中心 从华为东莞松山湖基地运来的预制化模块箱体&#xff0c;正在光谷科学岛起步区被吊装&#xff0c;未来将被“拼装”成武汉重要的人工智能算力基础设施。3月1日&#xff0c…

产业丨国产数据库行业火热,厂商各有各的算盘

前言&#xff1a; 随着数字经济的不断发展&#xff0c;未来数据库发展有着四个趋势&#xff1a;开源、HTAP、云原生以及和大数据技术融合。 如今&#xff0c;随着众多企业入局&#xff0c;国产数据库正在打着一场激烈的翻身仗。 前言&#xff1a; 随着数字经济的不断发展&a…

不到一年涨粉849万,“神级账号”小鱼海棠背后成功的秘诀是什么?

如何能在短时间内精确吸粉百万&#xff0c;快速度过账号冷启动&#xff0c;跻身头部网红的行列&#xff1f;快手视频博主“小鱼海棠”就交出了一份完美的答卷。 凭借牢牢抓住与999个帅哥拍照这一创意点&#xff0c;“小鱼海棠”一战封神&#xff0c;成为网红界一匹飞速狂奔的黑…