webman中,v5 http-client 协程与guzzlehttp异步并发请求对比

xiaopi

问题描述

webman中,【workerman v5 http-client 协程】与【guzzlehttp/guzzle 异步并发请求】对比优势,似乎并不明显。

这几天研究workerman v5的http-client协程的,目的是提高程序中IO请求的性能。发现协程的方式并不能减少请求时间,而且对并发提升也不多。

  • 安装http-client

    php8.1 /usr/local/bin/composer require workerman/workerman v5.0.0-beta.5 revolt/event-loop ^1.0.0 workerman/http-client ^2.0.0
  • 安装Http客户端

    php8.1 /usr/local/bin/composer require yzh52521/easyhttp
测试数据
  • 对同一post接口连续请求2次,分别使用http-client协程、easyhttp同步、easyhttp异步并发的方式,并使用ab压测。
http-client协程方式代码

app\controller\IndexController::demo1()
执行时间:163ms

$start = Carbon::now();

$http = new Client();

$response1 = $http->request('http://服务iP:8002/search', [
    'method' => 'POST',
    'headers' => [
        'Content-Type' => 'application/json',
    ],
    'data' => json_encode([
    'query' => '我是谁',
    'limit' => 5
    ])

]);

$response2 = $http->request('http://服务iP:8002/search', [
    'method' => 'POST',
    'headers' => [
        'Content-Type' => 'application/json',
    ],
    'data' => json_encode([
        'query' => '我不知道',
        'limit' => 5
    ])

]);

$response = array_merge(json_decode($response1->getBody(), true),
json_decode($response2->getBody(), true)
);

$runtime = Carbon::now()->diffInMilliseconds($start);

return json([
'runtime' => $runtime . 'ms',
'data' => $response
]);

压测结果
ab -n 1000 -c 50 http://192.168.10.10:5001/index/demo1

Server Software:        workerman
Server Hostname:        192.168.10.10
Server Port:            5001

Document Path:          /index/demo1
Document Length:        2867 bytes

Concurrency Level:      50
Time taken for tests:   33.856 seconds
Complete requests:      1000
Failed requests:        999
   (Connect: 0, Receive: 0, Length: 999, Exceptions: 0)
Total transferred:      2983999 bytes
HTML transferred:       2867999 bytes
Requests per second:    29.54 [#/sec] (mean)
Time per request:       1692.787 [ms] (mean)
Time per request:       33.856 [ms] (mean, across all concurrent requests)
Transfer rate:          86.07 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   1.2      0      16
Processing:   987 1670 196.8   1689    2228
Waiting:      987 1670 196.8   1689    2228
Total:        991 1670 196.6   1690    2228

Percentage of the requests served within a certain time (ms)
  50%   1690
  66%   1756
  75%   1777
  80%   1801
  90%   1900
  95%   2033
  98%   2082
  99%   2104
 100%   2228 (longest request)
easyhttp同步

app\controller\IndexController::demo2()
执行时间:168ms

$start = Carbon::now();

$response1 = Http::asJson()->post('http://服务iP:8002/search', [
    'query' => '我不知道',
    'limit' => 5
]);
$response2 = Http::asJson()->post('http://服务iP:8002/search', [
    'query' => '我不知道',
    'limit' => 5
]);

$response = array_merge($response1->json(), $response2->json());

$runtime = Carbon::now()->diffInMilliseconds($start);

return json([
    'runtime' => $runtime . 'ms',
    'data' => $response
]);

压测结果
ab -n 1000 -c 50 http://192.168.10.10:5001/index/demo2

Server Software:        workerman
Server Hostname:        192.168.10.10
Server Port:            5001

Document Path:          /index/demo2
Document Length:        3008 bytes

Concurrency Level:      50
Time taken for tests:   35.976 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      3124000 bytes
HTML transferred:       3008000 bytes
Requests per second:    27.80 [#/sec] (mean)
Time per request:       1798.794 [ms] (mean)
Time per request:       35.976 [ms] (mean, across all concurrent requests)
Transfer rate:          84.80 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.5      0       3
Processing:   189 1758 1414.9   1747   13011
Waiting:      189 1758 1414.9   1747   13011
Total:        192 1758 1415.1   1747   13012

Percentage of the requests served within a certain time (ms)
  50%   1747
  66%   1780
  75%   1803
  80%   1856
  90%   1913
  95%   1960
  98%   7578
  99%  10454
 100%  13012 (longest request)
easyhttp异步并发

app\controller\IndexController::demo3()
执行时间:167ms

$aa = [];
$start = Carbon::now();

$promises = [
    Http::asJson()->postAsync('http://服务iP:8002/search', [
        'query' => '我不知道',
        'limit' => 5
    ]),
    Http::asJson()->postAsync('http://服务iP:8002/search', [
        'query' => '我不知道',
        'limit' => 5
    ])
];
$pool = Http::multiAsync($promises, function (Response $response, $index) use (&$aa) {
    $aa[] = $response->json();
    echo "发起第 $index 个异步请求" . PHP_EOL;
});

$pool->promise()->wait();
$runtime = Carbon::now()->diffInMilliseconds($start);
return json([
    'runtime' => $runtime . 'ms',
    'data' => $aa
]);

压测结果
ab -n 1000 -c 50 http://192.168.10.10:5001/index/demo3

Server Software:        workerman
Server Hostname:        192.168.10.10
Server Port:            5001

Document Path:          /index/demo3
Document Length:        3012 bytes

Concurrency Level:      50
Time taken for tests:   36.145 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      3128000 bytes
HTML transferred:       3012000 bytes
Requests per second:    27.67 [#/sec] (mean)
Time per request:       1807.252 [ms] (mean)
Time per request:       36.145 [ms] (mean, across all concurrent requests)
Transfer rate:          84.51 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.6      0       4
Processing:   170 1767 862.1   1775    9789
Waiting:      170 1767 862.1   1775    9789
Total:        174 1767 862.3   1776    9790

Percentage of the requests served within a certain time (ms)
  50%   1776
  66%   1800
  75%   1816
  80%   1834
  90%   1871
  95%   1912
  98%   4249
  99%   7172
 100%   9790 (longest request)

结论:

使用http-client协程客户端的方式,相对比guzzlehttp同步、异步并发,似乎并不能提高多少性能,而且单次消耗时间是差不多的,是我用法有问题吗?

后面发现是因为第三方接口成为瓶颈,在第三方接口不是瓶颈的情况下,webman协程http-client方式性能提升非常明显

2240 5 9
5个回答

six

会不会 http://服务iP:8002/search 这个接口是瓶颈,只能支持这些并发?直接压测这个接口试下

  • xiaopi 2023-05-23

    直接压测服务ip:8002/search接口,Requests per second: 58.77 所以应该不是这个问题,理想情况下,我是想两次请求,消耗一次请求的时间

  • six 2023-05-23

    直接压测服务ip:8002/search接口,Requests per second: 58.77,所以它是瓶颈啊。
    两次请求Requests per second就是29.x

  • xiaopi 2023-05-23

    原来是这么换算的,感谢,那针对这种第三方缓慢的接口,有什么好办法提高请求性能吗

tanhongbin

win10系统,我测试优势很明显,协程主要是进程不阻塞,能够接受多个请求,使用guzzlehttp 不管同步和异步,对于当前进程来说是阻塞的,就是说请求照样排队,协程是能够接收多个请求,同时处理,所以并发很高,我这里有压测数据非常明显!![]截图这两个接口写法是一模一样的,就是一个用的协程,一个用的guzzlehttp同步 都是请求的第三方接口,截图 这是同步的压测,截图 这是协程的压测,性能差距很大

  • xiaopi 2023-05-23

    我的写法有问题么

  • xiaopi 2023-05-23

    我尝试按照你的压测参数,使用ab -n 100 -c 100,并且将程序中的请求由2个变为1个,得到的结果为http协程:57.50 [#/sec] 比较接近单独压测第三方xxx/_search接口。 guzzle同步的结果为: 23.11 [#/sec]。确实提高了很多

  • Tinywan 6天前

    真的吗

xiaopi

测试1

尝试将代码中的2次请求改为1次,并将压测并发改为
使用http协程和guzzle同步的方式结果分为:
http协程:Requests per second: 58.89 [#/sec] ,基本上与直接压测第三方接口一样
guzzle同步:Requests per second: 54 [#/sec],稍微低一些

测试2

依旧是在请求中请求第三方接口两次,
ab -n 1000 -c 100 http://192.168.10.10:5001/index/demo1
ab -n 1000 -c 100 http://192.168.10.10:5001/index/demo2
将第三方接口,换为get百度接口,并压测
http协程:Requests per second: 114.55 [#/sec] (mean)
http同步:Requests per second: 69.84 [#/sec] (mean)

结论

协程请求可有有效的提高并发的性能,但是受第三方接口的影响,极端情况下,若第三方接口缓慢时,协程请求与同步请求几乎差不多

  • six 2023-05-23

    第三方吞吐量只有60QPS,同步和协程大概QPS都在50-60左右。
    如果第三方吞吐量有1000QPS,同步可能QPS有可能还是60左右,但是协程可以达到1000左右。是这个区别。

  • xiaopi 2023-05-24

    感谢,这个表达的清晰了@six

nitron

协程是提高并发处理量,不是降低单个任务的处理时间

一条100m长的路,你多少速度跑都是要跑完100m,这是硬性资源

  • xiaopi 2023-05-23

    好吧,我原先理解的协程应该可以充分利用多核,可以近并发的处理多个IO请求,最终耗时是最长那条路的耗时。不知道golang中的协程,是否可以达到并行的请求。

  • nitron 2023-05-23

    还是以一条100m跑道举例,IO阻塞相当于当前选手受伤了,以前的做法是别人等他在跑道里处理完伤口后跑完全程,下一个选手才能继续跑,协程的做法是直接把受伤的抬出跑道处理伤口,这样可以空出跑道让下一个选手先跑,处理完伤口再把他抬回受伤的地方继续跑,实际上从头到尾只有一条跑道

    你要弄清楚并发和并行的区别
    并发是一个时间段内处理不同的事情,并行是一个时间点处理不同的事情(相当于我有N条100m的跑道)

    golang我不了解

  • nitron 2023-05-23

    我再看了上面的问题,抱歉之前没细看,你这个请求第三方接口,那瓶颈永远取决于第三方,跟你系统没关系,你用c/cpp写都一样,不会因为你用了协程,第三方接口的请求时间就会从1s变成0.1s

  • tanhongbin 2023-05-24

    跑道这个很形象

  • xiaopi 2023-05-24

    感谢

liong

go 的 Goroutine

  • 暂无评论
🔝