添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
魁梧的羊肉串  ·  【Azure ...·  1 周前    · 
强悍的梨子  ·  python ...·  1 周前    · 
性感的鸵鸟  ·  curl命令 CURL命令 测试 ...·  1 周前    · 
伤情的柿子  ·  ABAP CDS - cast_expr ...·  5 月前    · 
逃跑的棒棒糖  ·  Dymola Dynamic Ing ...·  6 月前    · 

如题,业务需要同一时间请求多个第三方,abc
1> 如果a先返回,判断结果,正确的话,就将结果返回下游。业务结束。
2> 如果a返回错误,就看第二快返回的结果,如果c第二快返回,结果正确,就把c结果返回下游。业务结束。

之前使用 curl_multi 由于这函数本身的bug,一直循环,导致 超时。
理论上说,有几个第三方,就发送几次请求,而这个函数,会重复多次。

只能选天然支持并发的语言。比如go。

但依然不甘心,这些好用的框架,为啥不出个这种功能,类似go的协程呢??

期待大佬解决。

2574 2 0 foreach ($urls as $i => $url) { $conn[$i] = curl_init($url); curl_setopt($conn[$i], CURLOPT_RETURNTRANSFER, 1); curl_multi_add_handle($mh, $conn[$i]); $result = ''; $status = curl_multi_exec($mh, $active); curl_multi_select($mh); $info = curl_multi_info_read($mh); if (false !== $info) { $result = curl_multi_getcontent($info['handle']); // 这里获得某个curl的结果,如果结果ok就break,不ok就等下一个结果 //$is_ok = your_check($result); $is_ok = 1; if ($is_ok) { break; } while ($status === CURLM_CALL_MULTI_PERFORM || $active); foreach ($urls as $i => $url) { curl_close($conn[$i]); // 最快的正确结果 echo $result; foreach ($urls as $i => $url) { $conn[$i] = curl_init($url); curl_setopt($conn[$i], CURLOPT_RETURNTRANSFER, 1); curl_multi_add_handle($mh, $conn[$i]); $result = ''; $status = curl_multi_exec($mh, $active); curl_multi_select($mh); $info = curl_multi_info_read($mh); if (false !== $info) { $result = curl_multi_getcontent($info['handle']); // 这里获得某个curl的结果,如果结果ok就break,不ok就等下一个结果 //$is_ok = your_check($result); $is_ok = 1; if ($is_ok) { break; } while ($status === CURLM_CALL_MULTI_PERFORM || $active); foreach ($urls as $i => $url) { curl_close($conn[$i]); // 最快的正确结果 echo $result;

加上 curl_multi_select($mh); 按道理不会消耗太多cpu才对。

https://www.workerman.net/page/update
webman 1.2.5 有 event-loop设置,config/server.php 里设置成设置'event_loop' => Workerman\Events\Swoole::class 则是用swoole作为底层,可以使用swoole的协程。我对swoole不熟悉,不清楚怎么和webman配合做的你的需求。

你这个接口可能要用worekrman来做了。

嗯,其实需求就是 同一时间请求多个上游,看谁先返回,判断返回结果。

由于整个过程需要300毫秒之内完成。所以 需要根据上游的数量来 同时发出 curl 动作。然后对比结果。

如果for循环的话,需要等待全部上游都返回结果值。这样就超时了。

我对swool协程也不是很清楚。不确定能不能实现这个需求??

curl_multi 原本是最适合的。但可能是本身存在的bug,导致 cpu 一直100% 。

中间用usleep(1)来释放CPU, curl_multi这个不是BUG,官方有说明,是本身执行逻辑就如此

https://bugs.php.net/bug.php?id=61240
https://bugs.php.net/bug.php?id=61141

如果我对swool和协程也不熟悉,不确定能不能实现。

反正现在的curl_multi 坑很多。

1是使用usleep, 本来就要求实效性很紧张的,有些需要200毫秒之内返回,还要减掉处理其他逻辑的时间,所以留给curl的时间就不多了。

2 do { 循环内,会有几千次的无效循环,才会为true,才会进行下一步},这就造成无谓的浪费了。

3 按理说,几个上游url,就请求几次。

4 这属于函数本身的bug了。

use Workerman\Connection\TcpConnection; use Workerman\Protocols\Http\Request; use Workerman\Psr7\Response; class Api * @var \Workerman\Http\Client protected $http; public function __construct() $this->http = new \Workerman\Http\Client(); public function onMessage(TcpConnection $connection, Request $request) $connection->sended = false; $urls = array( "http://lxr.php.net/", "http://www.php.net/", foreach ($urls as $url) { $this->http->get($url, function(Response $response) use ($connection) { $body = (string)$response->getBody(); $is_ok = 1; // 根据body判断是否ok if (!$is_ok) return; // 不ok就return if (!$connection->sended) { // 已经发送过结果了,不用再发了 $connection->sended = true; $connection->send($body); // 给客户端发送结果

配置 config/process.php

return [
    // 这里省略了其它配置...
    'my_api' => [
        'handler' => \process\Api::class,
        'listen' => 'http://0.0.0.0:1234',
        'count' => cpu_count(),

重启webman

在nginx里加一个转发配置

nginx加一个配置,将原有api请求路径的转发到 1234 端口

location /your/api/path {
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header Host $host;
      proxy_pass http://127.0.0.1:1234;
                                                                        

http-client没有设置post数据大小的地方。post数据大小你可以自己计算,用 strlen(http_build_query($post))。

$options = [
    'connect_timeout'   =>0.26, // 单位秒,0.26就是260毫秒
    'timeout'           => 0.26,
$this->http = new \Workerman\Http\Client($options );

设置超时这么设置