> For the complete documentation index, see [llms.txt](https://tarsphp.gitbook.io/doc/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tarsphp.gitbook.io/doc/zh/advanced/swoole-suport-tars.md).

# 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）

  ```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）

  ```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）

  ```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）

  ```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>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://tarsphp.gitbook.io/doc/zh/advanced/swoole-suport-tars.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
