先說一下流程:
1.編寫代碼,開啓http服務器
2.http服務器通過請求過來的url來分發到yii的不同模塊的不同控制器的不同方法來處理業務
3.進行壓測
1.新建一個php文件HttpController,代碼裏面用來統一分發請求
代碼:
<?php
namespace console\controllers;
use yii\console\Controller;
use Yii;
class HttpController extends Controller
{
public function actionIndex()
{
Yii::getLogger()->flushInterval = 1;
if (!extension_loaded('swoole')) {
$this->stderr('Swoole is not installed');
}
$this->stdout('Yii2版本:' . Yii::getVersion() . PHP_EOL);
$this->stdout('Swoole版本:' . SWOOLE_VERSION . PHP_EOL);
$this->stdout('PHP版本:' . PHP_VERSION . PHP_EOL);
$this->setProcessName(sprintf('php-swoole:%s', 'http-master'));
$http = new \Swoole\Http\Server("0.0.0.0", 9501);
$http->set([
'worker_num' => 4,
'request_max' => 1000
]);
$http->on('start', function ($server) {
echo 'HTTP服務器已經開啓' . PHP_EOL;
});
$http->on('request', function (\swoole_http_request $request, \swoole_http_response $response) {
list($controller, $action) = explode('/', trim($request->server['request_uri'], '/'));
$ReflectionController = '\\api\\controllers\\' . ucfirst($controller) . 'Controller';
$responseData = (new $ReflectionController($this->id, $this->module))->runAction($action, ['data' => $request->rawContent()]);
$response->end($responseData);
});
$http->start();
}
/**
* 設置進程名
* @param $name
*/
public function setProcessName($name)
{
if (function_exists('cli_set_process_title')) {
cli_set_process_title($name);
} else {
swoole_set_process_name($name);
}
}
}
開啓服務:
2.測試url是否進行分發,這裏的分發控制器爲api\controllers\processController,方法爲tasks方法
<?php
namespace api\controllers;
use common\models\Task;
use Yii;
class ProcessController extends AppController
{
public $enableCsrfValidation = false;
public function actionCreate($data)
{
try {
while (true) {
$isLock = Yii::$app->redis->setnx('TASK_LOCK', mt_rand(10000, 99999));
if ($isLock) {
$lpushResult = Yii::$app->redis->lpush('TASK:TASK_MSG', $data);
if ($lpushResult) {
Yii::$app->redis->del('TASK_LOCK');
return json_encode(['status' => 200, 'description' => '存入redis成功']);
}
} else {
usleep(200);
}
}
} catch (\Exception $exception) {
Yii::$app->redis->del('TASK_LOCK');
Yii::error($exception->__toString());
throw $exception;
}
}
public function actionTasks()
{
return Task::getTasks();
}
}
這裏的Task模型中的getTasks方法爲:
<?php
namespace common\models;
use yii\db\ActiveRecord;
use Yii;
class Task extends ActiveRecord
{
public static function tableName()
{
return '{{%task}}';
}
public static function getTasks()
{
$result = Yii::$app->redis->get('TASK:INFO');
if ($result) {
return $result;
}
return json_encode(self::find()->where(['type' => 'ok'])->asArray()->all());
}
}
下面進行postman請求:
我們可以看到已經查詢到消息了,說明已經分發到不同模塊的不同控制器的不同方法去了
下面進行開啓了swoole的http服務壓測:進行1000次請求,100次併發,我們開了4個worker進程,壓測結果如果:
qps大概爲1316左右
然後我們再用php-fpm來進行同樣的壓測
結果發現qps只有10左右
相對比一下,可以發現性能提升了差不多130倍
當然實際效果和機器配置有關,這裏只是做一個參考。
註釋:可能需要修改網站的nginx配置:
如圖參考:
如果需要開啓swoole的http服務器,這裏還需要先配置nginx參數