业务场景:webman开发,提供一个给用户端调用的api接口,实现逻辑如下:
1、把用户提交的数据处理下,然后请求若干个三方系统的http接口
2、根据这些三方接口返回的内容,来生成api接口响应数据
比如,有3个三方接口A、B、C,都有可能返回我想要的数据
如果A响应最快,返回了['IS_A'=> true, 'A DATA' => '...'],那么就直接拿'A DATA'处理下生成接口响应数据。B、C的响应结果直接丢弃不用
如果A响应最快,但是返回了['IS_A' => false],那么就继续等待下一个最先响应、并且'IS_X'是true的三方接口
现在要求就是这个api接口,性能要高,速度要快(假设这些三方接口本身响应都足够快)
然后搜了下站内很多帖子,都是推荐用workerman/http-client
但是我不太清楚,怎么才能最好的实现我想要的效果
已经用了workermanV5、http-client2.0、revolt/event-loop
<?php
namespace app\controller;
use support\Request;
class ApiController
{
public function index(Request $request)
{
$http = new \Workerman\Http\Client();
// 怎么实现下面代码的业务
// 但是三方接口1,和三方接口2能同时请求,节省时间
// 哪个先返回我想要的结果,接口就响应哪个数据
$resp1 = $http->get('三方接口1');
$data1 = json_decode($resp1->getBody(), true);
if ($data1['success']) {
return json(['data' => $data1['data']]);
}
$resp2 = $http->get('三方接口2');
$data2 = json_decode($resp2->getBody(), true);
if ($data2['success']) {
return json(['data' => $data2['data']]);
}
return json(['data' => null]);
}
}
这种情况用curl_multi就可以,下面代码是让webman AI的gpt4生成的,你试下
谢谢解答,我先试下。
请问我的这种需求,没必要用workerman/http-client么?
搜了站内一些帖子,感觉我的需求跟这个好像差不多,不是用异步协程http可以提高性能么
https://www.workerman.net/q/11997
异步或者协程性能好一些,但是要求业务不能使用全局变量(包括静态成员)存储请求相关的状态数据,否则会导致逻辑错乱。
下面是webman协程用法
Error: Must call suspend() before calling resume() in /home/web/webman-co/vendor/revolt/event-loop/src/EventLoop/Internal/DriverSuspension.php:52
Stack trace:
0 /home/web/webman-co/app/controller/ApiController.php(60): Revolt\EventLoop\Internal\DriverSuspension->resume()
1 [internal function]: app\controller\ApiController->app\controller{closure}()
2 /home/web/webman-co/vendor/workerman/http-client/src/Client.php(181): call_user_func()
3 [internal function]: Workerman\Http\Client->Workerman\Http{closure}()
4 /home/web/webman-co/vendor/workerman/http-client/src/Emitter.php(120): call_user_func_array()
5 [internal function]: Workerman\Http\Emitter->emit()
6 /home/web/webman-co/vendor/workerman/http-client/src/Request.php(130): call_user_func_array()
7 /home/web/webman-co/vendor/workerman/http-client/src/Request.php(449): Workerman\Http\Request->emit()
8 /home/web/webman-co/vendor/workerman/http-client/src/Request.php(376): Workerman\Http\Request->emitSuccess()
9 /home/web/webman-co/vendor/workerman/http-client/src/Request.php(360): Workerman\Http\Request->handleData()
10 /home/web/webman-co/vendor/workerman/http-client/src/Request.php(327): Workerman\Http\Request->checkComplete()
11 /home/web/webman-co/vendor/workerman/workerman/src/Connection/TcpConnection.php(725): Workerman\Http\Request->onMessage()
12 /home/web/webman-co/vendor/workerman/workerman/src/Events/Revolt.php(146): Workerman\Connection\TcpConnection->baseRead()
13 /home/web/webman-co/vendor/revolt/event-loop/src/EventLoop/Internal/AbstractDriver.php(589): Workerman\Events\Revolt->Workerman\Events{closure}()
14 [internal function]: Revolt\EventLoop\Internal\AbstractDriver->Revolt\EventLoop\Internal{closure}()
15 /home/web/webman-co/vendor/revolt/event-loop/src/EventLoop/Internal/AbstractDriver.php(497): Fiber->resume()
16 /home/web/webman-co/vendor/revolt/event-loop/src/EventLoop/Internal/AbstractDriver.php(553): Revolt\EventLoop\Internal\AbstractDriver->invokeCallbacks()
17 [internal function]: Revolt\EventLoop\Internal\AbstractDriver->Revolt\EventLoop\Internal{closure}()
18 /home/web/webman-co/vendor/revolt/event-loop/src/EventLoop/Internal/AbstractDriver.php(113): Fiber->start()
19 /home/web/webman-co/vendor/revolt/event-loop/src/EventLoop/Driver/EventDriver.php(119): Revolt\EventLoop\Internal\AbstractDriver->run()
20 /home/web/webman-co/vendor/workerman/workerman/src/Events/Revolt.php(88): Revolt\EventLoop\Driver\EventDriver->run()
21 /home/web/webman-co/vendor/workerman/workerman/src/Worker.php(1594): Workerman\Events\Revolt->run()
22 /home/web/webman-co/vendor/workerman/workerman/src/Worker.php(1394): Workerman\Worker::forkOneWorkerForLinux()
23 /home/web/webman-co/vendor/workerman/workerman/src/Worker.php(1368): Workerman\Worker::forkWorkersForLinux()
24 /home/web/webman-co/vendor/workerman/workerman/src/Worker.php(572): Workerman\Worker::forkWorkers()
25 /home/web/webman-co/vendor/workerman/webman-framework/src/support/App.php(131): Workerman\Worker::runAll()
26 /home/web/webman-co/start.php(4): support\App::run()
27 {main}
worker[webman:9729] exit with status 64000
这样运行之后会报错。
guzzle 万能
Must call suspend() before calling resume() 意思是你必须在resume()被调用之前调用suspend(),你检查下你的代码。
如果搞不懂就用curl_multi
guzzle 更方便