压测背景:
系统上线,需要得到服务器的真实tps 用于计算服务器成本和后期扩容需求。
目的:
通过压力测试找出lumen框架在真实环境中最高tps,找出影响tps的点,想办法进行优化。
环境准备:
操作系统: centos 7.6、nginx、php7.3.10 、mysql5.7.26、redis5.0哨兵。
Web服务器硬件配置: 阿里云 2cpu 8g 100g硬盘。
压测发起服务器:2cpu 4g 。
压测工具:apache-jmeter-5.1.zip ,上传到发起压测的服务器(/data/soft/)并解压。
PHP配置:开启opcache。
opcache.enable=1
opcache.max_accelerated_files=800000
opcache.validate_timestamps=1
opcache.revalidate_freq=600。
Jmeter配置:
设置jmeter配置参数:
在windows上设置好jmeter参数,然后将配置导出,上传到压测发起服务器
cd /data/soft/apache-jmeter-5.1/bin。
mkdir jmx
mkdir jtl
mkdir html
jmx :存放压测配置脚本。
jtl : 存放压测结果。
html : 存放压测html结果。
cd /data/soft/apache-jmeter-5.1/bin
./jmeter.sh -n –t /data/soft/apache-jmeter-5.1/bin/jmx/xiaoub.jmx -l /data/soft/apache-jmeter-5.1/bin/jtl/test2.jtl -e -o /data/soft/apache-jmeter-5.1/bin/html/
开始压测:
/**
* tps测试
* @param Request $request
* @return mixed
*/
public function tps(Request $request)
{
return $this->success('OK');
}
第一阶段:测试控制器返回的tps(未开启路由缓存)。
1. 300用户访问 tps接口,只做登录鉴权(redis),然后直接返回success。不处理业务。cpu占用88%,内存消耗500mb。
2. 300用户访问 tps接口,不做登录鉴权,直接返回success。不处理业务。cpu占用87%,内存消耗450mb。
3. 1200用户直接访问入口index.php 文件,直接返回成功,tps达到2702。Cpu利用率43%,内存消耗200mb。
初步结论:
加载lumen路由、配置、服务提供者、控制器处理逻辑 后,tps下降9倍。
我们需要优化路由和控制器看是否能提高tps。
第二阶段:加载路由文件的测试。
1. 不加载路由文件,300用户,持续5分钟,tps结果676。
exit(json_encode(['code' => success]));
$app->router->group([
'namespace' => 'App\Http\Controllers',
], function ($router) {
require __DIR__ . '/../routes/web.php';
require __DIR__ . '/../routes/exam.php';
require __DIR__ . '/../routes/classes.php';
require __DIR__ . '/../routes/api.php';
});
2. 加载路由 300用户,持续5分钟,tps 562, lumen路由导致平均响应时间增加87ms,tps降低114。
exit(json_encode(['code' => success]));
return $app;
3. 开启lumen路由缓存 (300用户,持续5分钟,tps 655)。
先引入扩展 lumen-cache。
composer require mowangjuanzi/lumen-cache
if (file_exists($app->basePath("bootstrap/cache/router.php"))) {
require_once $app->basePath("bootstrap/cache/router.php");
} else {
$app->router->group([
'namespace' => 'App\Http\Controllers',
], function ($router) {
require __DIR__ . '/../routes/web.php';
require __DIR__ . '/../routes/exam.php';
require __DIR__ . '/../routes/classes.php';
require __DIR__ . '/../routes/api.php';
});
}
exit(json_encode(['code' => success]));
结论:
不开启路由缓存会导致tps下降100多。建议开启lumen路由缓存。
第三阶段:从路由到控制器执行处的压力测试。
vendor/laravel/lumen-framework/src/Concerns/RoutesRequests.php 310行
protected function callControllerAction($routeInfo)
{
$uses = $routeInfo[1]['uses'];
if (is_string($uses) && ! Str::contains($uses, '@')) {
$uses .= '@__invoke';
}
[$controller, $method] = explode('@', $uses);
//此处断点测试
exit(json_encode(['controller' => $controller, 'method' => $method]));
if (! method_exists($instance = $this->make($controller), $method)) {
throw new NotFoundHttpException;
}
if ($instance instanceof LumenController) {
return $this->callLumenController($instance, $method, $routeInfo);
} else {
return $this->callControllerCallable(
[$instance, $method], $routeInfo[2]
);
}
}
1. 300用户,持续5分钟,不开启路由缓存,tps 360, 与第二阶段第3点相比,lumen路由平均响应时间增加290,tps降低302。
2. 300用户,持续5分钟,开启路由缓存,tps为398。
第四阶段:处理业务逻辑(开启路由缓存)
1 . 处理业务逻辑,访问数据库。执行多次查询,tps 降低为207。
/**
* tps测试
* @param Request $request
* @return mixed
*/
public function tps(Request $request)
{
$res = Student::query()->where(['classes_id' => 1001])->get()->toArray();
return $this->success($res);
}
2. 处理业务逻辑,访问redis。执行多次查询,tps 降低为315。
/**
* tps测试
* @param Request $request
* @return mixed
*/
public function tps(Request $request)
{
//$res = Student::query()->where(['classes_id' => 1001])->get()->toArray();
$res = Redis::get("xyz");
return $this->success($res);
}
优化方向:
从上述压力测试分析到,tps降低的主要原因是 执行服务提供者和控制器时,初始化很多类。
需要考虑从这方面去优化lumen。