• 总体思路
  • 以swoft为例

    总体思路

    • 在框架启动成功的时候,上报服务存活。
    • 使用框架的或者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的包,以及打包命令。
    1. {
    2. "require": {
    3. ...
    4. "phptars/tars-server": "~0.1",
    5. "phptars/tars-deploy": "~0.1",
    6. "phptars/tars2php": "~0.1",
    7. "phptars/tars-log": "~0.1",
    8. "ext-zip" : ">=0.0.1"
    9. ...
    10. },
    11. "scripts": {
    12. ...
    13. "deploy": "\\Tars\\deploy\\Deploy::run"
    14. ...
    15. }
    16. }
    • 写一个用于调用Tars平台各种接口的class (src/app/Tars/Manage.php)

      1. namespace App\Tars;
      2. use \Tars\report\ServerFSync;
      3. use \Tars\report\ServerFAsync;
      4. use \Tars\report\ServerInfo;
      5. use \Tars\Utils;
      6. class Manage
      7. {
      8. public function getNodeInfo(){
      9. $conf = $this->getTarsConf();
      10. if( !empty($conf) ){
      11. $node = $conf['tars']['application']['server']['node'];
      12. $nodeInfo = Utils::parseNodeInfo($node);
      13. return $nodeInfo;
      14. }else{
      15. return [];
      16. }
      17. }
      18. public function getTarsConf(){
      19. $tars_conf = dirname(BASE_PATH,2).'/conf/'.env('PNAME').'.config.conf';
      20. if( is_file($tars_conf) ){
      21. $conf = Utils::parseFile($tars_conf);
      22. return $conf;
      23. }else{
      24. var_dump('get tars_conf file error : '.$tars_conf);
      25. return [];
      26. }
      27. }
      28. public function keepAlive()
      29. {
      30. $pname = env('PNAME');
      31. $pname = explode('.',$pname);
      32. $adapter = env('PNAME').'.objAdapter';
      33. $application = $pname[0];
      34. $serverName = $pname[1];
      35. $masterPid = getmypid();
      36. $nodeInfo = $this->getNodeInfo();
      37. if( empty($nodeInfo) ){
      38. var_dump('keepAlive getNodeInfo fail');
      39. return null;
      40. }
      41. $host = $nodeInfo['host'];
      42. $port = $nodeInfo['port'];
      43. $objName = $nodeInfo['objName'];
      44. $serverInfo = new ServerInfo();
      45. $serverInfo->adapter = $adapter;
      46. $serverInfo->application = $application;
      47. $serverInfo->serverName = $serverName;
      48. $serverInfo->pid = $masterPid;
      49. $serverF = new ServerFSync($host, $port, $objName);
      50. $serverF->keepAlive($serverInfo);
      51. $adminServerInfo = new ServerInfo();
      52. $adminServerInfo->adapter = 'AdminAdapter';
      53. $adminServerInfo->application = $application;
      54. $adminServerInfo->serverName = $serverName;
      55. $adminServerInfo->pid = $masterPid;
      56. $serverF->keepAlive($adminServerInfo);
      57. var_dump(' keepalive ');
      58. }
      59. }
    • 在框架启动成功的时候,上报服务存活,这使用的swoft的框架的事件监听。 (src/app/Listener/APPStart.php)

      1. namespace App\Listener;
      2. use Swoft\Bean\Annotation\Listener;
      3. use Swoft\Event\EventHandlerInterface;
      4. use Swoft\Event\EventInterface;
      5. use Swoft\Task\Event\TaskEvent;
      6. use Swoft\Event\AppEvent;
      7. use App\Tars\Manage;
      8. use Swoft\Memory\Table;
      9. /**
      10. * Task finish handler
      11. *
      12. * @Listener(AppEvent::APPLICATION_LOADER)
      13. */
      14. class APPStart implements EventHandlerInterface
      15. {
      16. public static $num = 0;
      17. /**
      18. * @param \Swoft\Event\EventInterface $event
      19. */
      20. public function handle(EventInterface $event)
      21. {
      22. //服务启动 只上报一次 TODO
      23. $manage = new Manage();
      24. $manage->keepAlive();
      25. }
      26. }
    • 每隔30s上报一次存活,这里使用swoft框架注解试的定时任务。 (src/app/Tasks/TarsKeepAliveTask.php)

      1. namespace App\Tasks;
      2. use App\Lib\DemoInterface;
      3. use App\Models\Entity\User;
      4. use Swoft\App;
      5. use Swoft\Bean\Annotation\Inject;
      6. use Swoft\HttpClient\Client;
      7. use Swoft\Redis\Redis;
      8. use Swoft\Rpc\Client\Bean\Annotation\Reference;
      9. use Swoft\Task\Bean\Annotation\Scheduled;
      10. use Swoft\Task\Bean\Annotation\Task;
      11. use App\Tars\Manage;
      12. /**
      13. * TarsKeepAlive task
      14. *
      15. * @Task("tarsKeepAlive")
      16. */
      17. class TarsKeepAliveTask
      18. {
      19. /**
      20. *
      21. * @Scheduled(cron="*\/30 * * * * *")
      22. */
      23. public function cronkeepAliveTask()
      24. {
      25. $manage = new Manage();
      26. $manage->keepAlive();
      27. return 'cron';
      28. }
      29. }
    • 写一个入口文件,来控制swoft框架的启停。 (src/index.php)

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

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