yii2利用swoole的http服務器提供高性能接口

先說一下流程:

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參數

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章