前言ThinkPHP即将迎来最新的6.0版本。鉴于Swoole越来越流行,thinkphp也推出了最新的扩展think-swoole3.0sandbox。本文主要介绍ThinkPHP-swoole3.0中使用的Sandbox技术。沙盒——顾名思义,所有程序都运行在一个封闭的容器中。得益于更完备的容器技术,沙箱可以在3.0扩展中使用。首先,检查沙箱的使用方式。检查扩展中的Swoole.php,其中OnRequest函数publicfunctiononRequest($req,$res){$this->app->event->trigger('swoole.request');$this->resetOnRequest();/**@varSandbox$sandbox*/$sandbox=$this->app->make(Sandbox::class);$request=$this->prepareRequest($req);尝试{$sandbox->setRequest($request);$沙盒->初始化();$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);}}最后{$sandbox->clear();}}在代码中,从容器中取出沙箱,然后将请求注入沙箱,在沙箱中计算并返回结果,最后清空沙箱,那么Sandbox是如何起到沙箱作用的呢?//$sandbox->setRequest($request);publicfunctionsetRequest(Request$request){Context::setData('_request',$request);返回$这个;上面的代码将请求注入到沙箱中,这里又多了一个Context,那么这个类是做什么的呢?为什么不将整个属性存储在沙盒中?我们在文章的最后介绍这个,我会介绍沙箱。//$sandbox->init();publicfunctioninit(){if(!$this->configinstanceofConfig){thrownewRuntimeException('请在设置基础应用程序后初始化。');}$this->setInstance($app=$this->getApplication());$this->resetApp($app);最重要的链接在这里。看到这里就明白沙箱为什么叫沙箱了。由于tp6是基于容器来创建和销毁资源的,所以每个容器都是相对隔离的。接下来看代码//$this->setInstance($app=$this->getApplication());公共功能getApplication(){$snapshot=$this->getSnapshot();如果($snapshotinstanceofContainer){return$snapshot;}$snapshot=clone$this->getBaseApp();$this->setSnapshot($snapshot);返回$快照;看到什么了吗?克隆,复制。这里复制了容器对象,即原容器有的对象,新容??器也有。也就是说,每个请求都会创建一个新的执行和解析环境。由于容器的隔离性,每个请求都不会干扰其他请求。至于下面这段代码,看到这里,我想你已经明白了。$this->resetApp($app);最后$sandbox->clear(),清除当前协程保存在Context类中的数据,并初始化当前沙箱的容器publicfunctionclear(){Context::clear();$this->setInstance($this->getBaseApp());为什么我们需要额外沙盒中的Context类?看到这个类你就会明白static::getCoroutineId()是获取当前协程ID,每个协程都会有一个唯一的ID,这样通过Context存储一些特殊的数据或对象就不会造成数据混乱。因为只有当前协程才能读取数据。
