Swoole2.0内置协程并发测试

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内存

测试代码

1$server = new Swoole\Http\Server('127.0.0.1', 9501, SWOOLE_BASE); 2 3$server->set(array('worker_num' => 1)); 4 5$server->on('Request', function($request, $response) { 6 7 $mysql = new Swoole\Coroutine\MySQL(); 8 $res = $mysql->connect(['host' => '127.0.0.1', 'user' => 'root', 'password' => 'root', 'database' => 'test']); 9 if ($res == false) { 10 $response->end("MySQL connect fail!"); 11 return; 12 } 13 $ret = $mysql->query('select sleep(1)'); 14 $response->end("swoole response is ok, result=".var_export($ret, true)); 15}); 16 17$server->start();

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

启动程序

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

并发100测试

1ab -c 100 -n 1000 http://127.0.0.1:9501/ 2This is ApacheBench, Version 2.3 <$Revision: 1706008 $> 3Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ 4Licensed to The Apache Software Foundation, http://www.apache.org/ 5 6Benchmarking 127.0.0.1 (be patient) 7Completed 100 requests 8Completed 200 requests 9Completed 300 requests 10Completed 400 requests 11Completed 500 requests 12Completed 600 requests 13Completed 700 requests 14Completed 800 requests 15Completed 900 requests 16Completed 1000 requests 17Finished 1000 requests 18 19 20Server Software: swoole-http-server 21Server Hostname: 127.0.0.1 22Server Port: 9501 23 24Document Path: / 25Document Length: 85 bytes 26 27Concurrency Level: 100 28Time taken for tests: 10.061 seconds 29Complete requests: 1000 30Failed requests: 0 31Total transferred: 233000 bytes 32HTML transferred: 85000 bytes 33Requests per second: 99.39 [#/sec] (mean) 34Time per request: 1006.092 [ms] (mean) 35Time per request: 10.061 [ms] (mean, across all concurrent requests) 36Transfer rate: 22.62 [Kbytes/sec] received 37 38Connection Times (ms) 39 min mean[+/-sd] median max 40Connect: 0 0 1.3 0 7 41Processing: 1000 1004 4.7 1002 1020 42Waiting: 1000 1004 4.7 1002 1020 43Total: 1000 1005 5.8 1003 1026 44 45Percentage of the requests served within a certain time (ms) 46 50% 1003 47 66% 1004 48 75% 1005 49 80% 1006 50 90% 1016 51 95% 1020 52 98% 1022 53 99% 1022 54 100% 1026 (longest request)

并发1000测试

1ab -c 1000 -n 2000 http://127.0.0.1:9501/ 2This is ApacheBench, Version 2.3 <$Revision: 1706008 $> 3Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ 4Licensed to The Apache Software Foundation, http://www.apache.org/ 5 6Benchmarking 127.0.0.1 (be patient) 7Completed 200 requests 8Completed 400 requests 9Completed 600 requests 10Completed 800 requests 11Completed 1000 requests 12Completed 1200 requests 13Completed 1400 requests 14Completed 1600 requests 15Completed 1800 requests 16Completed 2000 requests 17Finished 2000 requests 18 19 20Server Software: swoole-http-server 21Server Hostname: 127.0.0.1 22Server Port: 9501 23 24Document Path: / 25Document Length: 19 bytes 26 27Concurrency Level: 1000 28Time taken for tests: 2.025 seconds 29Complete requests: 2000 30Failed requests: 153 31 (Connect: 0, Receive: 0, Length: 153, Exceptions: 0) 32Total transferred: 344098 bytes 33HTML transferred: 48098 bytes 34Requests per second: 987.66 [#/sec] (mean) 35Time per request: 1012.493 [ms] (mean) 36Time per request: 1.012 [ms] (mean, across all concurrent requests) 37Transfer rate: 165.94 [Kbytes/sec] received 38 39Connection Times (ms) 40 min mean[+/-sd] median max 41Connect: 0 6 6.6 8 18 42Processing: 8 166 336.4 68 2006 43Waiting: 8 166 336.4 68 2006 44Total: 8 173 340.6 83 2022 45 46Percentage of the requests served within a certain time (ms) 47 50% 83 48 66% 87 49 75% 89 50 80% 90 51 90% 1021 52 95% 1087 53 98% 1092 54 99% 1093 55 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的方式测试。

测试代码:

1$db = new mysqli; 2$db->connect('127.0.0.1', 'root', 'root', 'test'); 3$result = $db->query("select sleep(1)"); 4 5if ($result) 6{ 7 print_r($result->fetch_all()); 8} 9else die(sprintf("MySQLi Error: %s", mysqli_error($link))); 10 11 12ab -c 10 -n 100 http://127.0.0.1/mysql.php 13This is ApacheBench, Version 2.3 <$Revision: 1706008 $> 14Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ 15Licensed to The Apache Software Foundation, http://www.apache.org/ 16 17Benchmarking 127.0.0.1 (be patient).....done 18 19 20Server Software: nginx/1.10.0 21Server Hostname: 127.0.0.1 22Server Port: 80 23 24Document Path: /mysql.php 25Document Length: 69 bytes 26 27Concurrency Level: 10 28Time taken for tests: 100.086 seconds 29Complete requests: 100 30Failed requests: 0 31Total transferred: 24100 bytes 32HTML transferred: 6900 bytes 33Requests per second: 1.00 [#/sec] (mean) 34Time per request: 10008.594 [ms] (mean) 35Time per request: 1000.859 [ms] (mean, across all concurrent requests) 36Transfer rate: 0.24 [Kbytes/sec] received 37 38Connection Times (ms) 39 min mean[+/-sd] median max 40Connect: 0 0 0.1 0 0 41Processing: 1002 9558 1636.0 10008 10011 42Waiting: 1002 9558 1636.0 10008 10011 43Total: 1002 9558 1636.0 10008 10011 44 45Percentage of the requests served within a certain time (ms) 46 50% 10008 47 66% 10009 48 75% 10009 49 80% 10009 50 90% 10009 51 95% 10010 52 98% 10010 53 99% 10011 54 100% 10011 (longest request) 55

结果评价

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

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

点赞
收藏

评论区

加载中...

相关推荐

Go Context 并发编程简明教程

1为什么需要ContextWaitGroup和信道(channel)是常见的2种并发控制的方式。如果并发启动了多个子协程,需要等待所有的子协程完成任务,WaitGroup非常适合于这类场景,例如下面的例子:varwgsync.WaitGroupfuncdoTask(nint){time.Sleep(time.Durat

GO语言协程的理解

以下内容大部分摘自许世伟的《GO语言核心编程》最近面试,在自己的简历上写了简单会一些GO语言。结果被面试官问了GO语言goroutine的原理。自己看倒是看过,时间长了又给忘了。特此写下此文以长记性。协程:协程本质上是一种用户态线程,不需要操作系统来进行抢占式调度,并且在真正的实现中寄存于线程中,因此系统开销极小,可以有效的提高线程任务的并发性,而避

Gevent简明教程

1、前述进程线程协程异步并发编程(不是并行)目前有四种方式:多进程、多线程、协程和异步。多进程编程在python中有类似C的os.fork,更高层封装的有multiprocessing标准库多线程编程python中有Thread和threading异步编程在linux下主要有三种实现selec

Goroutine(协程)为何能处理大并发?

简单来说:协程十分轻量,可以在一个进程中执行有数以十万计的协程,依旧保持高性能。进程、线程、协程的关系和区别:进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度。线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度(标准线程是的)。协程和线程一样共享堆

Go并发(五):WaitGroup

本篇其实是Go并发编程的补充篇章,只是用来介绍WaitGroup的使用介绍。对于Go的并发编程来说,主协程需要知道其他的协程何时结束。通常我们的做法是采用channel的方式来控制,这种做法很好,可以参见我的另外一个帖子(Go并发之channel篇:https://mp.weixin.qq.com/s/PIbgGBootc6581pHhi5ew(h

Go 并发

Go并发并发指的是同时处理多个任务的能力。并行指的是并行处理多个任务的能力。并行不一定加快运行速度,因为并行组件之间可能需要互相通信。Go中使用协程,信道来处理并发。协程Go中主要通过协程实现并发。协程是与其他函数或方法一起并发运行的函数或方法,协程可以看作是轻量级线程,但是创建成本更小,我们经常