swoole-suport-tars

总体思路

  • 在框架启动成功的时候,上报服务存活。

  • 使用框架的或者swoole的定时器,实现每隔30s上报一次存活,可以在worker里面上报,也可以在task里面上报(注意可能worker都挂了,task还在)。

  • 写一个入口文件(如index.php),根据Tars平台生成的PHP服务启停脚本,以及Tars平台下发的conf配置文件,完成PHP框架的配置转换(端口号、worker数量)和启停命令控制。

  • 对于HTTP的服务,实现上面3步就可以跑着Tars里面了。对于其他各种功能(查看框架简介),可以根据实际情况自行引入Tarsphp的composer扩展。

  • 对于tars或者pb等RPC协议的服务,需要解决网络协议与业务协议的打包解包(可以参照tarsphp tcpserver),如果能实现定制的代码自动生成,就更好了。

以swoft为例

  • 修改composer.json,加入phptars的包,以及打包命令。

{
    "require": {
        ...
        "phptars/tars-server": "~0.1",
        "phptars/tars-deploy": "~0.1",
        "phptars/tars2php": "~0.1",
        "phptars/tars-log": "~0.1",
        "ext-zip" : ">=0.0.1"
        ...
    },
    "scripts": {
        ...
        "deploy": "\\Tars\\deploy\\Deploy::run"
        ...
    }
}
  • 写一个用于调用Tars平台各种接口的class (src/app/Tars/Manage.php)

    namespace App\Tars;
    use \Tars\report\ServerFSync;
    use \Tars\report\ServerFAsync;
    use \Tars\report\ServerInfo;
    use \Tars\Utils;
    class Manage
    {
    
      public function getNodeInfo(){
          $conf = $this->getTarsConf();
          if( !empty($conf) ){
              $node = $conf['tars']['application']['server']['node'];
              $nodeInfo = Utils::parseNodeInfo($node);
              return $nodeInfo;
          }else{
              return [];
          }
      }
    
      public function getTarsConf(){
          $tars_conf = dirname(BASE_PATH,2).'/conf/'.env('PNAME').'.config.conf';
    
          if( is_file($tars_conf) ){
              $conf = Utils::parseFile($tars_conf);
              return $conf;
          }else{
              var_dump('get tars_conf file error : '.$tars_conf);
              return [];
          }
      }
    
      public function keepAlive()
      {
          $pname = env('PNAME');
          $pname = explode('.',$pname);
    
          $adapter = env('PNAME').'.objAdapter';
          $application = $pname[0];
          $serverName = $pname[1];
          $masterPid = getmypid();
    
          $nodeInfo = $this->getNodeInfo();
          if( empty($nodeInfo) ){
              var_dump('keepAlive getNodeInfo fail');
              return null;
          }
          $host = $nodeInfo['host'];
          $port = $nodeInfo['port'];
          $objName = $nodeInfo['objName'];
    
          $serverInfo = new ServerInfo();
          $serverInfo->adapter = $adapter;
          $serverInfo->application = $application;
          $serverInfo->serverName = $serverName;
          $serverInfo->pid = $masterPid;
    
          $serverF = new ServerFSync($host, $port, $objName);
          $serverF->keepAlive($serverInfo);
    
          $adminServerInfo = new ServerInfo();
          $adminServerInfo->adapter = 'AdminAdapter';
          $adminServerInfo->application = $application;
          $adminServerInfo->serverName = $serverName;
          $adminServerInfo->pid = $masterPid;
          $serverF->keepAlive($adminServerInfo);
    
          var_dump(' keepalive ');
      }
    }
  • 在框架启动成功的时候,上报服务存活,这使用的swoft的框架的事件监听。 (src/app/Listener/APPStart.php)

    namespace App\Listener;
    use Swoft\Bean\Annotation\Listener;
    use Swoft\Event\EventHandlerInterface;
    use Swoft\Event\EventInterface;
    use Swoft\Task\Event\TaskEvent;
    use Swoft\Event\AppEvent;
    use App\Tars\Manage;
    use Swoft\Memory\Table;
    /**
    * Task finish handler
    *
    * @Listener(AppEvent::APPLICATION_LOADER)
    */
    class APPStart implements EventHandlerInterface
    {
      public static $num = 0;
      /**
       * @param \Swoft\Event\EventInterface $event
       */
      public function handle(EventInterface $event)
      {
          //服务启动  只上报一次 TODO
          $manage = new Manage();
          $manage->keepAlive();
      }
    }
  • 每隔30s上报一次存活,这里使用swoft框架注解试的定时任务。 (src/app/Tasks/TarsKeepAliveTask.php)

    namespace App\Tasks;
    use App\Lib\DemoInterface;
    use App\Models\Entity\User;
    use Swoft\App;
    use Swoft\Bean\Annotation\Inject;
    use Swoft\HttpClient\Client;
    use Swoft\Redis\Redis;
    use Swoft\Rpc\Client\Bean\Annotation\Reference;
    use Swoft\Task\Bean\Annotation\Scheduled;
    use Swoft\Task\Bean\Annotation\Task;
    use App\Tars\Manage;
    /**
    * TarsKeepAlive task
    *
    * @Task("tarsKeepAlive")
    */
    class TarsKeepAliveTask
    {
      /**
       *
       * @Scheduled(cron="*\/30 * * * * *")
       */
      public function cronkeepAliveTask()
      {
          $manage = new Manage();
          $manage->keepAlive();
          return 'cron';
      }
    }
  • 写一个入口文件,来控制swoft框架的启停。 (src/index.php)

    // tars 平台然后文件
    // 读取tars conf配置
    // 处理合成 env文件
    $args = $_SERVER['argv'];
    $swoft_bin = dirname(__FILE__).'/bin/swoft ';
    $arg_cmd = $args[2]=='start' ? 'start -d' : $args[2] ;
    $cmd = "/usr/bin/php " . $swoft_bin . $arg_cmd;
    exec($cmd, $output, $r);

ps:可以参考下面的提交记录 https://github.com/dpp2009/swoftInTars/commit/97459b5012f9d7542a2a31d936c65ad8637ee1a0#diff-efc7d6cbd3cc43b894698099b51a99ab

Last updated