It is well known that Curl is not recommended in SWOLE applications because it blocks processes.
This article will use actual code and data, in the most intuitive way, to let you understand why.
Finally, Curl's solution in Swoole will be given. If you don't want to see the analysis, you can go straight to the end.
Routine comparison
Yu Run doesn't like the empty articles, so she writes them by herself, so she can run the code directly, and use the data to see why Curl is not recommended in Swoole.
In order to be lazy, I used it directly. YurunHttp Surl and Swolle Handler, instead of the long, stinky Curl code.
Code
composer.json
{ "require": { "yurunsoft/yurun-http": "~3.0" } }
server.php
<?php $http = new Swoole\Http\Server('127.0.0.1', 9501); $http->on('workerstart', function(){ \Swoole\Runtime::enableCoroutine(); }); $http->on('request', function ($request, $response) { sleep(1); // Assuming that various processes take 1 second $response->end($request->get['id'] . ': ' . date('Y-m-d H:i:s')); }); $http->start();
test.php
<?php use Yurun\Util\YurunHttp; use Yurun\Util\HttpRequest; require __DIR__ . '/vendor/autoload.php'; define('REQUEST_COUNT', 3); go(function(){ // Collaborative Client echo 'coroutine http client:', PHP_EOL, PHP_EOL; $time = microtime(true); YurunHttp::setDefaultHandler(\Yurun\Util\YurunHttp\Handler\Swoole::class); // Switch to Swoole Handler $channel = new \Swoole\Coroutine\Channel; for($i = 0; $i < REQUEST_COUNT; ++$i) { go(function() use($channel, $i){ $http = new HttpRequest; $response = $http->get('http://127.0.0.1:9501/? Id='. $i); //request address var_dump($response->body()); $channel->push(1); }); } for($i = 0; $i < REQUEST_COUNT; ++$i) { $channel->pop(); } $channel->close(); echo 'coroutine http client time: ', (microtime(true) - $time) . 's', PHP_EOL, PHP_EOL; // curl echo 'curl:', PHP_EOL, PHP_EOL; $time = microtime(true); YurunHttp::setDefaultHandler(\Yurun\Util\YurunHttp\Handler\Curl::class); // Switch to Curl Handler $channel = new \Swoole\Coroutine\Channel; for($i = 0; $i < REQUEST_COUNT; ++$i) { go(function() use($channel, $i){ $http = new HttpRequest; $response = $http->get('http://127.0.0.1:9501/? Id='. $i); //request address var_dump($response->body()); $channel->push(1); }); } for($i = 0; $i < REQUEST_COUNT; ++$i) { $channel->pop(); } $channel->close(); echo 'curl time: ', (microtime(true) - $time) . 's', PHP_EOL, PHP_EOL; });
Function
First run requires composer update installation dependencies
- Run php server.php to start the server
- Run php test.php to start the client
Operation result
coroutine http client: string(22) "1: 2019-09-11 08:35:54" string(22) "0: 2019-09-11 08:35:54" string(22) "2: 2019-09-11 08:35:54" coroutine http client time: 1.0845630168915s curl: string(22) "0: 2019-09-11 08:35:55" string(22) "1: 2019-09-11 08:35:56" string(22) "2: 2019-09-11 08:35:57" curl time: 3.0139901638031s
Result analysis
The above code returns the result after a second delay at the server, simulating the time-consuming of the actual business.
As can be seen from the client's time-consuming, Curl's three requests took more than three seconds in total, while the co-op client only took more than one second.
Because in the previous request, Curl waited for the time to return the content to do nothing else. While the client of the protocol waits for the content to be returned, it suspends the current protocol and then executes the code in other protocols.
Solution
Coroutine\Http\Client
Swoole's built-in protocol client implementation is suitable for developers with a certain foundation.
File: https://wiki.swoole.com/wiki/page/p-coroutine_http_client.html
Guzzle-Swoole
We may seldom write curl directly in our projects, but many third-party libraries (such as SDK for a cloud) will be useful.
These third-party libraries usually use Guzzle as the Http client, and the underlying Guzzle is implemented using Curl.
Yurun developed this scenario Guzzle-Swoole Packages are introduced to make it easy for these SDK s to support collaborations without modifying a single line of code.
Usage method
Execution command direct installation dependency: composer require yurunsoft/guzzle-swoole~1.1
Global Setting Processor:
<?php require dirname(__DIR__) . '/vendor/autoload.php'; use GuzzleHttp\Client; use Yurun\Util\Swoole\Guzzle\SwooleHandler; use GuzzleHttp\DefaultHandler; DefaultHandler::setDefaultHandler(SwooleHandler::class); go(function(){ $client = new Client(); $response = $client->request('GET', 'http://www.baidu.com', [ 'verify' => false, ]); var_dump($response->getStatusCode()); });
Manually specify the Swoole processor:
use GuzzleHttp\Client; use GuzzleHttp\HandlerStack; use Yurun\Util\Swoole\Guzzle\SwooleHandler; go(function(){ $handler = new SwooleHandler(); $stack = HandlerStack::create($handler); $client = new Client(['handler' => $stack]); $response = $client->request('GET', 'http://www.baidu.com', [ 'verify' => false, ]); var_dump($response->getBody()->__toString(), $response->getHeaders()); });
YurunHttp
YurunHttp It is an open source PHP HTTP class library. It supports chain operation and is easy to use.
Support all common GET, POST, PUT, DELETE, UPDATE and other requests, support browser-level Cookies management, upload and download, set and read header, Cookie, request parameters, failure retry, speed limit, proxy, certificate and so on.
Version 3.0 perfectly supports Curl and Swoole protocols; Version 3.2 supports Swoole WebSocket clients.
Usage method
Execution command direct installation dependency: composer require yurunsoft/yurun-http~3.2
<?php use Yurun\Util\YurunHttp; use Yurun\Util\HttpRequest; // Set the default request processor to Swoole YurunHttp::setDefaultHandler(\Yurun\Util\YurunHttp\Handler\Swoole::class); // Swoole processors must be invoked in a coroutine go('test'); function test() { $http = new HttpRequest; $response = $http->get('http://www.baidu.com'); echo 'html:', PHP_EOL, $response->body(); }
By the time of publication, Swoole 4.4's new hook Curl is still an experimental feature. Although Yurun has contributed a part of the code to this function, I personally do not recommend hook Curl for the time being because of the huge workload of compatibility and too many OPTION s that are not supported.
Use Guzzle-Swoole and YurunHttp When you have any questions, you can ask me in the group (QQ group: 17916227).