Рубрики
Uncategorized

Вводный урок Swoole 3.0 (thinkphp 6.0) анализ архитектуры 1

Автор оригинала: David Wong.

ThinkPHP собирается приветствовать последнюю версию 6.0, в ответ на текущую все более популярную Swoole, ThinkPHP также запустил последнее расширение think – swoole 3.0

Анализ архитектуры

Архитектура Tp-swoole3.0 отличается от архитектуры 2.0. (структура каталогов показана ниже)

Tp в основном ориентирован на нерезидентную память. Хотя он был оптимизирован для совместимости со swoole, он все еще не может быть похож на swift, sd и другие фреймворки, разработанные для swoole. Под другим я не имею в виду, что tp плох, но что необходимо найти компромиссы, потому что оба режима совместимы.

запрос

Анализ механизма работы фреймворка, по сути, в основном анализ функции swool по запросу, распределение маршрутизации, обработка данных и так далее обрабатываются в функции.

Свул. php

public function onRequest($req, $res)
    {
        $this->app->event->trigger('swoole.request');

        $this->resetOnRequest();

        /** @var Sandbox $sandbox */
        $sandbox = $this->app->make(Sandbox::class);
        $request = $this->prepareRequest($req);

        try {
            $sandbox->setRequest($request);

            $sandbox->init();

            $response = $sandbox->run($request);

            $this->sendResponse($sandbox, $response, $res);
        } catch (Throwable $e) {
            try {
                $exceptionResponse = $this->app
                    ->make(Handle::class)
                    ->render($request, $e);

                $this->sendResponse($sandbox, $exceptionResponse, $res);
            } catch (Throwable $e) {
                $this->logServerError($e);
            }
        } finally {
            $sandbox->clear();
        }
    }

В начале функции запускается событие запроса. Пользователю удобно настроить запрос и выполнить некоторые настройки

$this->app->event->trigger('swoole.request');

Запрос на сброс, сброс этого класса, когда это веб-сайт, почему именно? Мы объясним это в следующий раз, когда будем анализировать Websocket

$this->resetOnRequest();

protected function resetOnRequest()
    {
        // Reset websocket data
        if ($this->isServerWebsocket) {
            $this->app->make(Websocket::class)->reset(true);
        }
    }

Следующий шаг-пропустить песочницу через контейнер, что также является ключевым. В структуре нерезидентной памяти для удобства существуют некоторые способы записи, которые не позволят легко освободить память в режиме резидентной памяти, небольшая утечка памяти, большая путаница в данных. Песочница может очень хорошо решить эту проблему. (статья заканчивается случаем утечки памяти и повреждения данных.)

$sandbox = $this->app->make(Sandbox::class);

Запросы предварительно обрабатываются, и в данном случае это преобразование запроса из запроса свула по запросу tp

$request = $this->prepareRequest($req);

$header = $req->header ?: [];
        $server = $req->server ?: [];

        if (isset($header['x-requested-with'])) {
            $server['HTTP_X_REQUESTED_WITH'] = $header['x-requested-with'];
        }

        if (isset($header['referer'])) {
            $server['http_referer'] = $header['referer'];
        }

        if (isset($header['host'])) {
            $server['http_host'] = $header['host'];
        }

        // re-instantiate the request object to handle swoole request data
        /** @var \think\Request $request */
        $request = $this->app->make('request', [], true);

        return $request->withHeader($header)
            ->withServer($server)
            ->withGet($req->get ?: [])
            ->withPost($req->post ?: [])
            ->withCookie($req->cookie ?: [])
            ->withInput($req->rawContent())
            ->withFiles($req->files ?: [])
            ->setBaseUrl($req->server['request_uri'])
            ->setUrl($req->server['request_uri'] . (!empty($req->server['query_string']) ? '&' . $req->server['query_string'] : ''))
            ->setPathinfo(ltrim($req->server['path_info'], '/'));

Песочница настроена и инициализирована

$sandbox->setRequest($request);
$sandbox->init();            

Запустите песочницу

$response = $sandbox->run($request);

Если возникает исключение, информация об исключении обрабатывается и отправляется

try {
    $exceptionResponse = $this->app
        ->make(Handle::class)
        ->render($request, $e);

    $this->sendResponse($sandbox, $exceptionResponse, $res);
} catch (Throwable $e) {
    $this->logServerError($e);
}

В конце концов вам нужно очистить песочницу

$sandbox->clear();

Вот как tp-swoole обрабатывает HTTP и многое другое о том, как работает песочница

Набор фигур

Резидентную память можно легко игнорировать

class A{
    private static $intance=null;
    public static function getInstance(){
        if (!empty(self::$intance)){
            return self::$intance;
        }
        self::$intance = new static();
        return self::$intance;
    }
    public static function clear(){
        self::$intance=null;
    }

    public function echo(){
        echo "echo";
    }
    
}

$b = A::getInstance();
A::clear();
print_r($b->echo());

Будет ли приведенный выше код сообщать об ошибке?

Не. Он все еще печатает эхо, а теперь давайте проведем еще один эксперимент

class A
{
    private static $intance = null;
    private $echo = 'echo';
    public static function getInstance()
    {
        if (!empty(self::$intance)) {
            return self::$intance;
        }
        self::$intance = new static();
        return self::$intance;
    }
    public static function clear()
    {
        self::$intance = null;
    }

    public function echo()
    {
        echo $this->echo;
    }


    public function setEcho($echo)
    {
        $this->echo = $echo;
    }
}

$b = A::getInstance();
$a = A::getInstance();
$a->setEcho("b");
print_r($b->echo());
A::clear();
print_r($b->echo());
$a->setEcho("a");
print_r($b->echo());

Что выводит приведенный выше код? Ответ:bba. Так почему бы просто не сообщить об ошибке, а напечатать ответ, подобный тому, что импорт объекта переменной PHP-это ссылка на адрес. Когда назначены $a и $b, все они хранят одно и то же содержимое, и только одна копия хранится в расположении экземпляра self::$. Изменение $a или $b изменит экземпляр self::$, так почему же $a и $b все еще работают, когда экземпляр self::$очищен? Скопируйте во время написания на PHP. Когда экземпляр self::$очищен, создается копия для $a и $b.

Когда мы разрабатывали в режиме без памяти, нам не нужно было обращать на это внимание, потому что каждый запрос был эквивалентен отдельному потоку, инициализирующему все данные и, наконец, уничтожающему все данные, и все данные выполнялись по порядку. Да здравствует память, вам нужно обратить внимание на эти проблемы, иначе возникнут аналогичные проблемы с безопасностью потоков. Почему это так, обсуждается ниже.

Оригинал: “https://developpaper.com/swoole-3-0-introductory-tutorial-thinkphp-6-0-architecture-analysis-1/”