例如:我和她假期去旅游。
这句话我们可以引出三个问题。她是指的谁?假期是哪个假期?去哪里旅游?贸然的给我们一句话我们不知道这段话说的意思。由于这段话没有上文也没有下文,我们不知道说的她是谁;还有这个假期是过去式还是将来时;如果这句话改一改,把高下文带进来。
下面是小明和小强的对白:

小明:小强不好意思啊。我假期没空和你一起加班了。
小强:为什么啊?
小明:我和她假期去旅游。
小强:和谁去哪呢?
小明:小红啊,她说五一有空,我和她一起出去三亚下海。
小强:滚吧,重色轻友的忘八。
这样就有了高下文,我们就知道这个她是谁,假期是什么时候,目的地是哪里。这便是语文里面理解的高下文的旁边。
高下文没有详细的阐明,也没有某一个详细的实例来阐明,高下文会根据运用程序的生命周期而变革。也便是说同样的一句话在不同的高下文环境中,所表示的意思不一样。
为什么利用高下文?我们理解了什么是高下文,那么我们说说编程里面的高下文,说白了编程里面的高下文便是一个环境。跟前面理解的情形一下,没有高下文我们不知道某一个变量处于某一个时候或者某一进程,线程代表什么意思。因此高下文便是见告这些变量所处的位置,例如一个进程切换的时候须要保存进程的状态,资源保护好现场,等到再次切换回来的时候从中断的地方规复。
如图所示,我们在每一个要求都有变量、数据库资源、文件资源等等。在不同的高下文环境中,这些要求的值所表示不一样的内容。例如在要求1中userid是1002,在要求2中userid是999。
在利用常驻内存框架的时候很多时候为了性能,掌握器会弄成单例的,以是我们在利用的时候不能像以往在fpm模式下开拓一样,利用基类来继续属性在掌握器利用共同属性;例如我们在中间件做授权验证,如果想要把这个用户id连续传到掌握器利用,怎么办呢?我们又不能通过基类的办法来继续,这时候可以把这个id挂载到高下文中。
最直不雅观的理解便是每一次要求都会有一个高下文来管理这个要求的所有产生的内容,做到每一个要求的变量和资源达到隔离状态,避免了不同的要求会涌现数据污染的情形。
为什么在php-fpm不须要高下文?
其实在php-fpm模式开拓我们常常不须要管理高下文,由于在php-fpm模式开拓不是常驻内存的,并且php-fpm帮我们管理了高下文,不须要开拓者自己管理,而在常驻内存开拓中须要掩护每个要求的环境。
常驻内存没有高下文隔离产生的问题
常驻内存下采取单例的掌握器,不会由于每次要求都new一次掌握器。
BaseController.php
class BaseController{ protected $num = 0;}
Controller.php
class Controller extends BaseController{ public function index(){ $this->num++; return "index:".$this->num; } public function test(){ $this->num++; return "test:".$this->num; }}
Server.php
include './BaseController.php';include './Controller.php';class Server{ private $server; private $controller; public function __construct(){ $this->controller = new Controller(); $this->server = new Swoole\Http\Server("127.0.0.1", 9501); $this->server->on('request', function ($request, $response){ $c = $request->get['c']??'index'; $res = call_user_func([$this->controller,$c]); $response->end($res); }); $this->server->start(); }}new Server();
分别要求一下:
http://127.0.0.1:9501/http://127.0.0.1:9501?c=test实战:手写swoole框架高下文管理通过高下文隔离每一个要求的信息,避免数据污染。
Context.php
use Swoole\Coroutine;class Context{ private static $context = []; public static function get($key = null){ $tid = Coroutine::getCid(); if ($key == null){ return self::$context[$tid] ?? null; }else{ return self::$context[$tid][$key] ?? null; } } / Set context @param $key @param $context / public static function set($key,$context){ $tid = Coroutine::getCid(); self::$context[$tid][$key] = $context; } public static function destroy(){ $tid = Coroutine::getCid(); unset(self::$context[$tid]); } public static function printContext(){ print_r(self::$context); }}
Controller.php
class Controller{ public function index(){ $num = Context::get("num"); $num++; return "index:".$num; } public function test(){ $num = Context::get("num"); $num++; return "test:".$num; }}
Server.php
include './Context.php';include './Controller.php';class Server{ private $server; private $controller; public function __construct(){ $this->controller = new Controller(); $this->server = new Swoole\Http\Server("127.0.0.1", 9501); $this->server->on('request', function ($request, $response){ defer(function(){ Context::destroy(); }); Context::set('num',0); Context::printContext(); $c = $request->get['c']??'index'; $res = call_user_func([$this->controller,$c]); $response->end($res); }); $this->server->start(); }}new Server();
可以通过协程id获取当前要求的高下文环境,并且可以在任意地方只要得到协程id就可以获取高下文,可以把一些和当前要求关联的数据通过高下文通报。