| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- <?php
- /**
- * Created by PhpStorm.
- * User: liyunlong
- * Date: 2018-12-22
- * Time: 16:57
- */
- namespace common\libs\swoole;
- class RPCService
- {
- /**
- * 配置对象
- * @var array
- */
- protected $settings = [];
- /**
- * Yii::$app
- * @var null
- */
- private $app = null;
- private $swooleContorller = null;
- function __construct($settings,$app, &$swooleContorller){
- $this->check();
- $this->settings = $settings;
- $this->app = $app;
- $this->swooleContorller = $swooleContorller;
- }
- /**
- * [check description]
- */
- private function check(){
- /**
- * 检测 PDO_MYSQL
- */
- if (!extension_loaded('pdo_mysql')) {
- exit('error:请安装PDO_MYSQL扩展' . PHP_EOL);
- }
- /**
- * 检查exec 函数是否启用
- */
- if (!function_exists('exec')) {
- exit('error:exec函数不可用' . PHP_EOL);
- }
- /**
- * 检查命令 lsof 命令是否存在
- */
- exec("whereis lsof", $out);
- if (strpos($out[0], "/usr/sbin/lsof") === false ) {
- exit('error:找不到lsof命令,请确保lsof在/usr/sbin下' . PHP_EOL);
- }
- }
- /**
- * 获取指定端口的服务占用列表
- * @param $port
- * @return array
- */
- private function bindPort($port) {
- $res = [];
- $cmd = "/usr/sbin/lsof -i :{$port}|awk '$1 != \"COMMAND\" {print $1, $2, $9}'";
- exec($cmd, $out);
- if ($out) {
- foreach ($out as $v) {
- $a = explode(' ', $v);
- list($ip, $p) = explode(':', $a[2]);
- $res[$a[1]] = [
- 'cmd' => $a[0],
- 'ip' => $ip,
- 'port' => $p,
- ];
- }
- }
- return $res;
- }
- /**
- * 启动服务
- * @throws \yii\base\Exception
- */
- public function serviceStart(){
- $pidfile = $this->settings['pidfile'];
- $host = $this->settings['host'];
- $port = $this->settings['port'];
- $this->msg("服务正在启动...");
- if (!is_writable(dirname($pidfile))) {
- $this->error("pid文件需要写入权限");
- }
- if (file_exists($pidfile)) {
- $pid = explode("\n", file_get_contents($pidfile));
- $cmd = "ps ax | awk '{ print $1 }' | grep -e \"^{$pid[0]}$\"";
- exec($cmd, $out);
- if (!empty($out)) {
- $this->msg("[warning]:pid文件已存在,服务已经启动,进程id为:{$pid[0]}",true);
- } else {
- $this->msg("[warning]:pid文件已存在,可能是服务上次异常退出");
- unlink($pidfile);
- }
- }
- $bind = $this->bindPort($port);
- if ($bind) {
- foreach ($bind as $k => $v) {
- if ($v['ip'] == '*' || $v['ip'] == $host) {
- $this->error("服务启动失败,{$host}:{$port}端口已经被进程ID:{$k}占用");
- }
- }
- }
- //启动
- $server = new RPCServer($this->settings,$this->app,$this->swooleContorller);
- foreach($this->settings['ipWhiteList'] as $ip){
- $server->addAllowIP($ip);
- }
- $server->addAllowUser($this->settings['username'], $this->settings['password']);
- $server->run();
- }
- /**
- * 查看服务状态
- */
- public function serviceStats(){
- $client = new \swoole_http_client($this->settings['host'], $this->settings['port']);
- // if (!$client->connect($this->settings['host'], $this->settings['port'], $this->settings['client_timeout'])){
- // exit("Error: connect server failed. code[{$client->errCode}]\n");
- // }
- // $client->send('stats');
- //
- // echo $client->recv();
- $client->on('message', function ($cli, $frame){
- var_dump($frame);
- echo(PHP_EOL);
- $cli->close();
- });
- $client->upgrade('/', function ($cli){
- $cli->push('stats');
- // $cli->close();
- });
- }
- /**
- * 查看进程列表
- */
- public function serviceList(){
- $cmd = "ps aux|grep " . $this->settings['process_name'] . "|grep -v grep|awk '{print $1, $2, $6, $8, $9, $11}'";
- exec($cmd, $out);
- if (empty($out)) {
- $this->msg("没有发现正在运行服务",true);
- }
- $this->msg("本机运行的服务进程列表:");
- $this->msg("USER PID RSS(kb) STAT START COMMAND");
- foreach ($out as $v) {
- $this->msg($v);
- }
- }
- /**
- * 停止服务
- * @param bool $isForce
- * @param callable|null $callback
- */
- public function serviceStop($isForce = false, callable $callback = null){
- $pidfile = $this->settings['pidfile'];
- $this->msg("正在停止服务...");
- if (!file_exists($pidfile)) {
- $this->msg("pid文件:". $pidfile ."不存在");
- } else {
- $pid = explode("\n", file_get_contents($pidfile));
- if($isForce && !empty($pid)){
- foreach($pid as $id){
- if($id){
- $this->_kill($id);
- }
- }
- }
- if(!$isForce){
- if ($pid[0]) {
- $this->_kill($pid[0]);
- }
- }
- //确保停止服务后swoole-task-pid文件被删除
- if (file_exists($pidfile)) {
- unlink($pidfile);
- }
- $this->msg("服务已停止");
- }
- if($callback !== null) $callback();
- }
- /**
- * 杀进程
- * @param $pid
- */
- private function _kill($pid){
- $cmd = "kill {$pid}";
- exec($cmd, $sign);
- do {
- $out = [];
- $c = "ps ax | awk '{ print $1 }' | grep -e \"^{$pid}$\"";
- exec($c, $out);
- if (empty($out)) {
- break;
- }else{
- exec("kill -9 {$pid}");
- }
- } while (true);
- }
- /**
- * 停止服务
- * @param $msg
- * @param bool $exit
- */
- private function msg($msg,$exit=false){
- if($exit){
- exit($msg . PHP_EOL);
- }else{
- echo $msg . PHP_EOL;
- }
- }
- /**
- * 停止服务
- * @param $msg
- */
- private function error($msg){
- exit("[error]:".$msg . PHP_EOL);
- }
- }
|