SyncInvoker

场景

Swoole4.x后,提供了非常强大的协程能力,让我们可以更好的压榨服务器性能,提高并发。然而,目前PHP在swoole协程生态上,并不是很完善,比如没有协程版本的monogodb客户端,而为了避免在worker中调用了同步阻塞的Api,例如在Http回调中使用了同步的芒果客户端,导致worker退化为同步阻塞,导致没办法完全的发挥协程的优势, EasySwoole 提供了一个同步程序协程调用转化驱动。

原理

启动自定义进程监听UnixSocket,然后worker端调用协程客户端发送命令到自定义进程并处理,然后吧处理结果返回给worker的协程客户端。

安装

  1. composer require easyswoole/sync-invoker

使用

定义一个驱动工作实例(可以定义多个)

  1. namespace App;
  2. use EasySwoole\SyncInvoker\AbstractInvoker;
  3. use EasySwoole\SyncInvoker\SyncInvoker;
  4. use EasySwoole\Component\Singleton;
  5. class MyInvokerDriver extends AbstractInvoker{
  6. private $stdclass;
  7. function __construct()
  8. {
  9. $this->stdclass = new \stdClass();
  10. parent::__construct();
  11. }
  12. public function test($a,$b)
  13. {
  14. return $a+$b;
  15. }
  16. public function a()
  17. {
  18. return 'this is a';
  19. }
  20. public function getStdClass()
  21. {
  22. return $this->stdclass;
  23. }
  24. }
  25. //注册一个对应的调用器
  26. class MyInvoker extends SyncInvoker
  27. {
  28. use Singleton;
  29. }

EasySwoole 全局事件中的mainServerCreate 进行注册

  1. MyInvoker::getInstance(new MyInvokerDriver())->attachServer(ServerManager::getInstance()->getSwooleServer());

服务启动后,即可在任意位置调用

  1. $ret = MyInvoker::getInstance()->client()->test(1,2);
  2. var_dump($ret);
  3. var_dump(MyInvoker::getInstance()->client()->a());
  4. var_dump(MyInvoker::getInstance()->client()->a(1));
  5. var_dump(MyInvoker::getInstance()->client()->fuck());
  6. $ret = MyInvoker::getInstance()->client()->callback(function (MyInvokerDriver $driver){
  7. $std = $driver->getStdClass();
  8. if(isset($std->time)){
  9. return $std->time;
  10. }else{
  11. $std->time = time();
  12. return 'new set time';
  13. }
  14. });

注意事项

  • 尽量使用函数名调用方式,闭包方式调用会存在部分闭包函数序列化失败问题
  • 传递参数,返回结果尽量用数组或者字符串传递,资源对象无法序列化