Swoole2.0内置协程并发测试

Easter79
• 阅读 753

Swoole2.0是一个革命性的版本,它内置了协程的支持。与Go语言协程不同,Swoole协程完全不需要开发者添加任何额外的关键词,直接以过去最传统的同步阻塞模式编写代码,底层自动进行协程调度实现异步IO。使并发编程变得非常简单。

最新的版本中,内置协程已支持PHP7,同时兼具了性能和并发能力,Swoole的强大超乎想象。

本文基于Github最新的Swoole2.0.3版本进行了并发压力测试,来验证Swoole内置协程的并发能力。

测试环境

  • 操作系统:Ubuntu 16.04
  • 软件版本:PHP-7.0.14 Swoole-2.0.3
  • 硬件环境:酷睿I5+8G内存

测试代码

$server = new Swoole\Http\Server('127.0.0.1', 9501, SWOOLE_BASE);

$server->set(array('worker_num' => 1));

$server->on('Request', function($request, $response) {

    $mysql = new Swoole\Coroutine\MySQL();
    $res = $mysql->connect(['host' => '127.0.0.1', 'user' => 'root', 'password' => 'root', 'database' => 'test']);
    if ($res == false) {
        $response->end("MySQL connect fail!");
        return;
    }
    $ret = $mysql->query('select sleep(1)');
    $response->end("swoole response is ok, result=".var_export($ret, true));
});

$server->start();

代码非常简单,使用BASE模式创建一个Http服务器,并且设置进程为1,收到Http请求后执行一条select sleep(1) 语句,这条SQL模拟了阻塞IO,MySQL的服务器在1秒后返回结果。传统的同步阻塞程序,启动1个进程,毫无疑问只能提供1QPS的处理能力。而Swoole2.0协程不同,它虽然使用同步阻塞方式编写代码,但是底层确是异步IO,即使SQL语言执行时间很长,也可以提供很大的并发能力。

启动程序

php server.php
ps aux|grep server.php
htf      13142  0.6  0.2 328480 42268 pts/24   S+   10:17   0:00 php server.php

并发100测试

ab -c 100 -n 1000 http://127.0.0.1:9501/
This is ApacheBench, Version 2.3 <$Revision: 1706008 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 127.0.0.1 (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests


Server Software:        swoole-http-server
Server Hostname:        127.0.0.1
Server Port:            9501

Document Path:          /
Document Length:        85 bytes

Concurrency Level:      100
Time taken for tests:   10.061 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      233000 bytes
HTML transferred:       85000 bytes
Requests per second:    99.39 [#/sec] (mean)
Time per request:       1006.092 [ms] (mean)
Time per request:       10.061 [ms] (mean, across all concurrent requests)
Transfer rate:          22.62 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   1.3      0       7
Processing:  1000 1004   4.7   1002    1020
Waiting:     1000 1004   4.7   1002    1020
Total:       1000 1005   5.8   1003    1026

Percentage of the requests served within a certain time (ms)
  50%   1003
  66%   1004
  75%   1005
  80%   1006
  90%   1016
  95%   1020
  98%   1022
  99%   1022
 100%   1026 (longest request)

并发1000测试

ab -c 1000 -n 2000 http://127.0.0.1:9501/
This is ApacheBench, Version 2.3 <$Revision: 1706008 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 127.0.0.1 (be patient)
Completed 200 requests
Completed 400 requests
Completed 600 requests
Completed 800 requests
Completed 1000 requests
Completed 1200 requests
Completed 1400 requests
Completed 1600 requests
Completed 1800 requests
Completed 2000 requests
Finished 2000 requests


Server Software:        swoole-http-server
Server Hostname:        127.0.0.1
Server Port:            9501

Document Path:          /
Document Length:        19 bytes

Concurrency Level:      1000
Time taken for tests:   2.025 seconds
Complete requests:      2000
Failed requests:        153
   (Connect: 0, Receive: 0, Length: 153, Exceptions: 0)
Total transferred:      344098 bytes
HTML transferred:       48098 bytes
Requests per second:    987.66 [#/sec] (mean)
Time per request:       1012.493 [ms] (mean)
Time per request:       1.012 [ms] (mean, across all concurrent requests)
Transfer rate:          165.94 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    6   6.6      8      18
Processing:     8  166 336.4     68    2006
Waiting:        8  166 336.4     68    2006
Total:          8  173 340.6     83    2022

Percentage of the requests served within a certain time (ms)
  50%     83
  66%     87
  75%     89
  80%     90
  90%   1021
  95%   1087
  98%   1092
  99%   1093
 100%   2022 (longest request)

Length: 153 错误是因为MySQL服务器已经无法支持这么大并发了,拒绝了swoole的连接,因此会抛出错误。

php-fpm测试

为了进行对比,本文还做了php-fpm的测试。同样使用PHP7,修改php-fpm.conf将php-fpm进程设置为1。测试的代码与Swoole的完全一致,也是执行同一个sleep的SQL语句。 因为php-fpm是真正的同步阻塞,耗时太长,因此只能使用并发10请求100的方式测试。

测试代码:

$db = new mysqli;
$db->connect('127.0.0.1', 'root', 'root', 'test');
$result = $db->query("select sleep(1)");

if ($result) 
{
    print_r($result->fetch_all());
}
else die(sprintf("MySQLi Error: %s", mysqli_error($link)));


ab -c 10 -n 100 http://127.0.0.1/mysql.php
This is ApacheBench, Version 2.3 <$Revision: 1706008 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 127.0.0.1 (be patient).....done


Server Software:        nginx/1.10.0
Server Hostname:        127.0.0.1
Server Port:            80

Document Path:          /mysql.php
Document Length:        69 bytes

Concurrency Level:      10
Time taken for tests:   100.086 seconds
Complete requests:      100
Failed requests:        0
Total transferred:      24100 bytes
HTML transferred:       6900 bytes
Requests per second:    1.00 [#/sec] (mean)
Time per request:       10008.594 [ms] (mean)
Time per request:       1000.859 [ms] (mean, across all concurrent requests)
Transfer rate:          0.24 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.1      0       0
Processing:  1002 9558 1636.0  10008   10011
Waiting:     1002 9558 1636.0  10008   10011
Total:       1002 9558 1636.0  10008   10011

Percentage of the requests served within a certain time (ms)
  50%  10008
  66%  10009
  75%  10009
  80%  10009
  90%  10009
  95%  10010
  98%  10010
  99%  10011
 100%  10011 (longest request)

结果评价

可以看到Swoole服务器,即使SQL语句要执行1秒才返回结果,并发100的测试中也提供了100qps的能力,并发1000的测试中QPS为987,但MySQL服务器已经无法提供服务了。而同步阻塞的php-fpm处理并发10请求100的测试花费了100秒才完成,QPS为1。

Swoole2.0的内置协程未来可能会颠覆现代软件的开发模式。

点赞
收藏
评论区
推荐文章
HelloWorld官方 HelloWorld官方
4年前
Go Context 并发编程简明教程
1为什么需要ContextWaitGroup和信道(channel)是常见的2种并发控制的方式。如果并发启动了多个子协程,需要等待所有的子协程完成任务,WaitGroup非常适合于这类场景,例如下面的例子:varwgsync.WaitGroupfuncdoTask(nint){time.Sleep(time.Durat
GO语言协程的理解
以下内容大部分摘自许世伟的《GO语言核心编程》最近面试,在自己的简历上写了简单会一些GO语言。结果被面试官问了GO语言goroutine的原理。自己看倒是看过,时间长了又给忘了。特此写下此文以长记性。协程:协程本质上是一种用户态线程,不需要操作系统来进行抢占式调度,并且在真正的实现中寄存于线程中,因此系统开销极小,可以有效的提高线程任务的并发性,而避
Stella981 Stella981
3年前
Gevent简明教程
1、前述进程线程协程异步并发编程(不是并行)目前有四种方式:多进程、多线程、协程和异步。多进程编程在python中有类似C的os.fork,更高层封装的有multiprocessing标准库多线程编程python中有Thread和threading异步编程在linux下主要有三种实现selec
Stella981 Stella981
3年前
Goroutine(协程)为何能处理大并发?
简单来说:协程十分轻量,可以在一个进程中执行有数以十万计的协程,依旧保持高性能。进程、线程、协程的关系和区别:进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度。线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度(标准线程是的)。协程和线程一样共享堆
Stella981 Stella981
3年前
Go并发(五):WaitGroup
本篇其实是Go并发编程的补充篇章,只是用来介绍WaitGroup的使用介绍。对于Go的并发编程来说,主协程需要知道其他的协程何时结束。通常我们的做法是采用channel的方式来控制,这种做法很好,可以参见我的另外一个帖子(Go并发之channel篇:https://mp.weixin.qq.com/s/PIbgGBootc6581pHhi5ew(h
Wesley13 Wesley13
3年前
Go 并发
Go并发并发指的是同时处理多个任务的能力。并行指的是并行处理多个任务的能力。并行不一定加快运行速度,因为并行组件之间可能需要互相通信。Go中使用协程,信道来处理并发。协程Go中主要通过协程实现并发。协程是与其他函数或方法一起并发运行的函数或方法,协程可以看作是轻量级线程,但是创建成本更小,我们经常
Stella981 Stella981
3年前
Python 协程与 Go 协程的区别(二)
👆“Python猫”,一个值得加星标的公众号花下猫语:今天继续分享协程系列的第二篇。万字长文,收藏起来慢慢读吧。PS:原文中有挺多参考链接,微信不能很好保留。故建议阅读原文。作者:lgj\_bky(经作者授权转载)原文:https://www.cnblogs.com/lgjbky/p/10838035.html写在前面
Android Kotlin 协程初探 | 京东物流技术团队
1它是什么(协程和Kotlin协程)1.1协程是什么维基百科:协程,英文Coroutine\2为什么选择它(协程解决什么问题)异步场景举例:1.第一步:接口获取当前用户token及用户信息2.第二步:将用户的昵称展示界面上3.第三步:然后再通过这个toke
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k