Context上下文管理器

Swoole中,由于多个协程是并发执行的,因此不能使用类静态变量/全局变量保存协程上下文内容。使用局部变量是安全的,因为局部变量的值会自动保存在协程栈中,其他协程访问不到协程的局部变量。

Swoole属于常驻内存,在特殊情况下声明变量,需要进行手动释放,释放不及时,会导致非常大的内存开销,使服务宕掉。

ContextManager上下文管理器存储变量会自动释放内存,避免开发者不小心而导致的内存增长。

原理

  • 通过当前协程idkey来存储该变量。
  • 注册defer函数。
  • 协程退出时,底层自动触发defer进行回收。

安装

EasySwoole默认加载该组件,无须开发者引入。在非EasySwoole框架中使用,开发者可自行引入。

composer require easyswoole/component

基础例子

  1. use EasySwoole\Component\Context\ContextManager;
  2. go(function (){
  3. ContextManager::getInstance()->set('key','key in parent');
  4. go(function (){
  5. ContextManager::getInstance()->set('key','key in sub');
  6. var_dump(ContextManager::getInstance()->get('key')." in");
  7. });
  8. \co::sleep(1);
  9. var_dump(ContextManager::getInstance()->get('key')." out");
  10. });

以上利用上下文管理器来实现协程上下文的隔离。

自定义处理项

例如,当有一个key,希望在协程环境中,get的时候执行一次创建,在协程退出的时候可以进行回收,就可以注册一个上下文处理项来实现。该场景可以用于协程内数据库短连接管理。

  1. use EasySwoole\Component\Context\ContextManager;
  2. use EasySwoole\Component\Context\ContextItemHandlerInterface;
  3. class Handler implements ContextItemHandlerInterface
  4. {
  5. function onContextCreate()
  6. {
  7. $class = new \stdClass();
  8. $class->time = time();
  9. return $class;
  10. }
  11. function onDestroy($context)
  12. {
  13. var_dump($context);
  14. }
  15. }
  16. ContextManager::getInstance()->registerItemHandler('key',new Handler());
  17. go(function (){
  18. go(function (){
  19. ContextManager::getInstance()->get('key');
  20. });
  21. \co::sleep(1);
  22. ContextManager::getInstance()->get('key');
  23. });