Swoole2.0内置协程并发测试

来源:https://my.oschina.net/matyhtf/blog/806196
【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内存
测试代码
$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 htf131420.60.2 328480 42268 pts/24S+10:170: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 requestsServer Software:swoole-http-server Server Hostname:127.0.0.1 Server Port:9501Document Path:/ Document Length:85 bytesConcurrency 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] receivedConnection Times (ms) minmean[+/-sd] medianmax Connect:001.307 Processing:1000 10044.710021020 Waiting:1000 10044.710021020 Total:1000 10055.810031026Percentage 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 requestsServer Software:swoole-http-server Server Hostname:127.0.0.1 Server Port:9501Document Path:/ Document Length:19 bytesConcurrency 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] receivedConnection Times (ms) minmean[+/-sd] medianmax Connect:066.6818 Processing:8166 336.4682006 Waiting:8166 336.4682006 Total:8173 340.6832022Percentage 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).....doneServer Software:nginx/1.10.0 Server Hostname:127.0.0.1 Server Port:80Document Path:/mysql.php Document Length:69 bytesConcurrency 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] receivedConnection Times (ms) minmean[+/-sd] medianmax Connect:000.100 Processing:1002 9558 1636.01000810011 Waiting:1002 9558 1636.01000810011 Total:1002 9558 1636.01000810011Percentage 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的内置协程未来可能会颠覆现代软件的开发模式。



    推荐阅读