内容简介:ThinkPHP即将迎来最新版本6.0,针对目前越来越流行Swoole,thinkphp也推出了最新的扩展think-swoole 3.0tp-swoole3.0不同于2.0版本,采用了全新的架构。(如下图目录结构)
前言
ThinkPHP即将迎来最新版本6.0,针对目前越来越流行Swoole,thinkphp也推出了最新的扩展think-swoole 3.0
架构分析
tp-swoole3.0不同于2.0版本,采用了全新的架构。(如下图目录结构)
tp主要针对的是非常驻内存方式运行,为了兼容swoole,虽然做了很多优化,但是仍然无法像swoft,sd等一些针对swoole开发的框架一样。这里所说的不同,不是指tp不好,而是因为两种模式都要兼容,不得不做出一些取舍。
请求
分析该框架的运行机制,其实主要分析swoole的OnRequest函数即可,路由分发,数据处理等都是在函数处进行处理的。
Swoole.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();
}
}
函数初始处,触发了一个request事件,这里方便用户自定义处理请求,进行一些定制化处理
$this->app->event->trigger('swoole.request');
重置请求,当是Websocket的时候,重置该类,具体为什么,下次我们分析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);
请求进行预处理,这里进行的是request的转换,从swoole的request转换到tp的request
$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'];
}
// 重新实例化请求对象 处理swoole请求数据
/** @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());
以上代码会报错吗?
不会。仍然会输出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::$intance位置所存放的内容。修改$a或$b都会修改self::$intance,那么为何当self::$intance为清除后,$a和$b仍然正常?基于 PHP 写时复制,当self::$intance被清空,就会复制出来一份给$a和$b来使用。
当我们在非常住内存方式开发时,这些都不需要注意,因为每次请求都相当于一个单独的线程,初始化所有数据,最后在将所有数据销毁,且所有数据都是按照顺序执行的。长住内存方式,就需要注意这些问题,不然会出现类似线程安全的问题。至于为何会出现这样的问题,下文再叙。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Book of CSS3
Peter Gasston / No Starch Press / 2011-5-13 / USD 34.95
CSS3 is the technology behind most of the eye-catching visuals on the Web today, but the official documentation can be dry and hard to follow. Luckily, The Book of CSS3 distills the heady technical la......一起来看看 《The Book of CSS3》 这本书的介绍吧!