Guzzle
Guzzle
Guzzle教程或者说笔记。
性能:该框架确实能提升性能,测试windows平台上,使用Pool的方式来批量请求,性能只能提升不到1倍。1000次请求,由普通代码17秒提升至12秒左右,而且设置了不10、30、50、100的并发,但是时间上并没有太大的改变。另外,使用js来进行请求,反而时间能提升至1秒左右。大概提升到了10倍的性能。所以,我在想,这个库的实现原理是啥?如何做到异步请求的?待研究。相关测试,在Guzzle示例.zip。
资源
手册地址
https://guzzle-cn.readthedocs.io/zh_CN/latest/psr7.html#requests
相关概念
Request
请求。参见例子3中,yield的请求,应该来说,这个对象,并未真正发送请求,只是包装了一下请求的参数。待执行
Promise对象
$client->postAsync 这些异步请求,会产生这样的对象。
Response
响应,常用方法。$results[‘image1’]->getBody()
使用例子
例子1
<?php
include "vendor/autoload.php";
use GuzzleHttp\Client;
use Psr\Http\Message\ResponseInterface;
use GuzzleHttp\Exception\RequestException;
$t0=microtime(true);
$client = new Client([
'base_uri' => 'http://10.20.24.165',
'timeout' => 10.0,
]);
try{
$promise = $client->requestAsync('GET','demo.php');
}catch(\Exception $e){
echo $e->getMessage();
}
$spend = microtime(true) - $t0;
echo "done:$spend s\n";
$promise->then(
function (ResponseInterface $res) {
echo 'suchuanchao####';
echo $res->getStatusCode() . "\n";
},
function (RequestException $e) {
echo $e->getMessage() . "\n";
echo $e->getRequest()->getMethod();
}
);
$spend = microtime(true) - $t0;
echo "done:$spend s\n";
sleep(8);
例子2
<?php
include "vendor/autoload.php";
use GuzzleHttp\Client;
use GuzzleHttp\Promise;
use Psr\Http\Message\ResponseInterface;
use GuzzleHttp\Exception\RequestException;
$t0=microtime(true);
$client = new Client([
'base_uri' => 'http://10.20.24.165',
'timeout' => 10.0,
]);
$promises = [
'image1' => $client->getAsync('demo.php'),
'image2' => $client->getAsync('demo.php'),
'image3' => $client->getAsync('demo.php'),
'image4' => $client->getAsync('demo.php'),
'image5' => $client->getAsync('demo.php'),
'image6' => $client->getAsync('demo.php'),
'image7' => $client->getAsync('demo.php'),
'image8' => $client->getAsync('demo.php'),
'image9' => $client->getAsync('demo.php'),
'image10' => $client->getAsync('demo.php'),
];
//好像是将上面数组的整体请求完。
$results = Promise\unwrap($promises);
// var_dump($results['image1']->getHeader('Content-Length'));
// var_dump($results['image2']->getHeader('Content-Length'));
// var_dump($results['image3']->getHeader('Content-Length'));
// var_dump($results['image4']->getHeader('Content-Length'));
// var_dump($results['image5']->getHeader('Content-Length'));
// var_dump($results['image6']->getHeader('Content-Length'));
// var_dump($results['image7']->getHeader('Content-Length'));
// var_dump($results['image8']->getHeader('Content-Length'));
// var_dump($results['image9']->getHeader('Content-Length'));
// var_dump($results['image10']->getHeader('Content-Length'));
// var_dump($results['image1']->getStatusCode());
// var_dump($results['image2']->getStatusCode());
// var_dump($results['image3']->getStatusCode());
// var_dump($results['image4']->getStatusCode());
// var_dump($results['image5']->getStatusCode());
// var_dump($results['image6']->getStatusCode());
// var_dump($results['image7']->getStatusCode());
// var_dump($results['image8']->getStatusCode());
// var_dump($results['image9']->getStatusCode());
// var_dump($results['image10']->getStatusCode());
// var_dump($results['image1']->getBody());
// var_dump($results['image2']->getBody());
// var_dump($results['image3']->getBody());
// var_dump($results['image4']->getBody());
// var_dump($results['image5']->getBody());
// var_dump($results['image6']->getBody());
// var_dump($results['image7']->getBody());
// var_dump($results['image8']->getBody());
// var_dump($results['image9']->getBody());
// var_dump($results['image10']->getBody());
echo $results['image1']->getBody();
echo $results['image2']->getBody();
echo $results['image3']->getBody();
echo $results['image4']->getBody();
echo $results['image5']->getBody();
echo $results['image6']->getBody();
echo $results['image7']->getBody();
echo $results['image8']->getBody();
echo $results['image9']->getBody();
echo $results['image10']->getBody();
$spend = microtime(true) - $t0;
echo "done:$spend s\n";
sleep(8);
例子3
请求池Pool
<?php
include "vendor/autoload.php";
use GuzzleHttp\Client;
use GuzzleHttp\Promise;
use GuzzleHttp\Pool;
use GuzzleHttp\Psr7\Request;
use Psr\Http\Message\ResponseInterface;
use GuzzleHttp\Exception\RequestException;
$t0=microtime(true);
//客户端也不能少
$client = new Client([
// Base URI is used with relative requests
'base_uri' => 'http://10.20.24.165',
// You can set any number of default request options.
'timeout' => 10.0,
]);
$requests = function ($total) {
$uri = 'http://localhost/demo.php';
for ($i = 0; $i < $total; $i++) {
// yield new Request('GET', $uri);
yield new Request('GET', $uri);
}
};
$pool = new Pool($client, $requests(100), [
//并发量,好像每次都一次性返回
'concurrency' => 30,
// 成功的回调
'fulfilled' => function ($response, $index) {
// this is delivered each successful response
echo '#3333' .PHP_EOL;
echo $response->getBody().PHP_EOL;
},
//失败后的回调
'rejected' => function ($reason, $index) {
echo '#22222';
// this is delivered each failed request
},
]);
$promise = $pool->promise();
$promise->wait();
$spend = microtime(true) - $t0;
echo "done:$spend s\n";
sleep(8);
例子4
Post请求。aplication-json格式的请求。
function getPhoneNum($mail_no){
global $client;
$url = 'http://10.19.160.165:29010/order/phone';
$params = [
'json'=>[
'shipId'=>$mail_no,
'systemId' => 'yunchou'
]
];
$response = $client->post($url,$params);
$data = json_decode($response->getBody(),true);
var_dump($data);
}
对应普通的curl代码的相似功能:
/**
* 发送json格式的数据到服务器。
* @return mixed $result 接口调用返回结果。
*/
public static function postJson($url, array $post = NULL, array $options = array())
{
$jsonStr = \json_encode($post);
$defaults = array(
CURLOPT_POST => 1,
CURLOPT_HEADER => 0,
CURLOPT_URL => $url,
CURLOPT_FRESH_CONNECT => 1,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_FORBID_REUSE => 1,
CURLOPT_TIMEOUT => 5,
CURLOPT_POSTFIELDS => $jsonStr,
CURLOPT_HTTPHEADER => array(
'Content-Type: application/json; charset=utf-8',
'Content-Length: ' . strlen(json_encode($post))
),
);
$ch = curl_init();
curl_setopt_array($ch, ($options + $defaults));
if( ! $result = curl_exec($ch))
{
throw new \Exception(curl_error($ch));
}
curl_close($ch);
return $result;
}
例子5
卡在$requests = function ($mails) 函数呢。返回
new Request,但是对于提交的请求头,跟上面的弄混淆了,下面的应该是关联数据格式,上面的请求头是普通的数组。因为这一步卡了很久。重点:注意Request对象的headers写法,不同于上面curl格式的请求头。
<?php
include "vendor/autoload.php";
use GuzzleHttp\Client;
use GuzzleHttp\Promise;
use GuzzleHttp\Pool;
use GuzzleHttp\Psr7\Request;
use Psr\Http\Message\ResponseInterface;
use GuzzleHttp\Exception\RequestException;
$t0=microtime(true);
//客户端也不能少
$client = new Client([
'base_uri' => 'http://10.19.160.165:29010',
'timeout' => 10.0,
]);
$requests = function ($mails) {
global $client;
$url = 'http://10.19.160.165:29010/order/phone';
foreach ($mails as $mail_no) {
// yield new Request('GET', $uri);
$params = [
'shipId'=>$mail_no,
'systemId' => 'yunchou'
];
$header = [
'Content-Type'=>'application/json; charset=utf-8',
// 'Content-Length' => ' . strlen(json_encode($params))',
];
// yield new Request('POST', $url,$params);
yield new Request('POST',$url,$header,json_encode($params) );
}
};
$mails = [
'4000148909728',
'4000158397760',
'3189066031209',
];
$pool = new Pool($client, $requests($mails), [
//并发量,好像每次都一次性返回
'concurrency' => 30,
// 成功的回调
'fulfilled' => function ($response, $index) {
// this is delivered each successful response
echo '#3333' .PHP_EOL;
echo $response->getBody().PHP_EOL;
},
//失败后的回调
'rejected' => function ($reason, $index) {
echo '#22222';
// this is delivered each failed request
},
]);
function getPhoneNum($mail_no){
global $client;
$url = 'http://10.19.160.165:29010/order/phone';
$response = $client->post($url,$params);
$data = json_decode($response->getBody(),true);
var_dump($data);
}
$promise = $pool->promise();
$promise->wait();
// getPhoneNum('4000148909728');
// getPhoneNum('4000158397760');
// getPhoneNum('3189066031209');