Автор оригинала: 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/”