早闻Swoole因其持久化的特性有高性能高并发和语法简单的特点,突发奇想试着把汇率API项目的API部分用Swoole处理,在这里对比一下两者的性能差异
服务器配置:
E5 2650V2 4核心 KVM虚拟化无超开
8G内存
程序代码和运行在SATA SSD内进行
系统:CentOS 7.9
PHP版本:8.1开启JIT,FPM使用opache
压测机配置:

i5 10400F+16G内存,好吧其实就是我自己的电脑。
压测程序:https://github.com/link1st/go-stress-testing
首先是php内置函数1w发测试:
FPM代码:
<?php
echo 'use PHP-FPM.#'.mt_rand(1000,9999);
Swoole代码在异步模式下的代码:
<?php
$http = new Swoole\Http\Server('0.0.0.0', 9501);
$http->on('Request', function ($request, $response) {
$response->header('Content-Type', 'text/html; charset=utf-8');
$response->end('<h1>Hello Swoole. #' . mt_rand(1000, 9999) . '</h1>');}
);
$http->start();
FPM测试结果:

Swoole异步测试结果:

Swoole异步下tp99对比FPM有了三倍的性能提升
接下来是Swoole协程模式下,下面是代码:
<?php
use Swoole\Coroutine\Http\Server;
use function Swoole\Coroutine\run;
run(function () {
$server = new Server('127.0.0.1', 9502, false);
$server->handle('/', function ($request, $response) {
$response->end('<h1>Hello Swoole. #' . rand(1000, 9999) . '</h1>');
});
$server->start();
});
测试结果:

和异步模式下几乎无差别。
接下来是redis取值+循环输出数组,PHP-FPM代码如下:
<?php
$redis_config=array(
'host' => "127.0.0.1", //数据库服务器
'port' => 6379, //数据库端口
);
$arraylist = array("GBP", "HKD", "USD", "CHF", "DEM", "FRF", "SGD", "SEK", "DKK", "NOK", "JPY", "CAD", "AUD", "EUR", "MOP", "PHP", "THB", "NZD", "KRW", "RUB", "MYR", "TWD", "ESP", "ITL", "NLG", "BEF", "FIM", "INR", "IDR", "BRL", "AED", "ZAR", "SAR", "TRY", "time");
$redis = new Redis();
$redis->pconnect($redis_config['host'],$redis_config['port']);
$arList = $redis->mget($arraylist);
$array_result=array();
foreach($arList as $k => $v){
$currency = $arraylist["$k"];
$array_result[$currency] = $v;
}
print_r(json_encode($array_result));
Swoole:
httpServer.php:
PHP
<?php
use Swoole\Coroutine;
$http = new Swoole\Http\Server('0.0.0.0', 9501);
Coroutine::set(['hook_flags'=> SWOOLE_HOOK_ALL]);
ini_set('memory_limit','-1');
include_once('api/autoload.php');
$http->set([
'buffer_output_size' => 128 * 1024 * 1024, //必须为数字
]);
$http->on('Request', function ($request, $response) {
if ($request->server['path_info'] == '/favicon.ico' || $request->server['request_uri'] == '/favicon.ico') {
$response->end();
return;
}
list($controller, $action) = explode('/', trim($request->server['request_uri'], '/'));
//根据 $controller, $action 映射到不同的控制器类和方法。
if (method_exists($controller,$action)){
$result_route = (new $controller)->$action($request, $response);
$response->end($result_route);
}else{
$response->header('Content-Type', 'text/html; charset=utf-8');
$response->end("API服务正常,请求内容不存在");
}
});
$http->start();
/api/autoload.php
<?php
// API自动加载器
spl_autoload_register(function ($class) {
include $class.'.php';
},false);
/api/exchangeRate.php
<?php
/**
* 汇率操作功能类
*/
include(dirname(__DIR__).'/db/db.php');
class exchangeRate{
public function index($request, $response){
$arraylist = array("GBP", "HKD", "USD", "CHF", "DEM", "FRF", "SGD", "SEK", "DKK", "NOK", "JPY", "CAD", "AUD", "EUR", "MOP", "PHP", "THB", "NZD", "KRW", "RUB", "MYR", "TWD", "ESP", "ITL", "NLG", "BEF", "FIM", "INR", "IDR", "BRL", "AED", "ZAR", "SAR", "TRY", "time");
$redis = new redisController();
$arList = $redis->mget($arraylist);
$array_result=array();
foreach($arList as $k => $v){
$currency = $arraylist["$k"];
$array_result[$currency] = $v;
}
return json_encode($array_result);
}
/db/db.php
<?php
include_once(dirname(__DIR__).'/db/redisController.php');
/db/redisController.php
<?php
/**
* Redis操作类
*/
class redisController{
public function mget($keys){
include('config.php');
$redis = new Redis();
$redis->pconnect($redis_config['host'],$redis_config['port']);
$value = $redis->mget($keys);
return $value;
}
}
测试结果:
FPM:

tp99:6.1s 但是已经出现502了(意味着有部分请求FPM是无响应的)

tp99:3s,无502,4s处理完所有请求
Swoole原理:
php中用swoole框架写好代码,在cli模式下启动后swoole会常驻后台,这样就达到了持久化,性能天生就比fpm高……
同时启动的时候就将php代码加载完毕转为机器码,对比fpm处理一次请求就要加载一次代码然后再处理的效率要高。
Swoole使用C++编写,支持一键协程化,自然效率高于FPM
文章评论