WebSocketController.php 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. <?php
  2. namespace common\controllers;
  3. use yii\console\Controller;
  4. use common\components\WebSocketServer;
  5. use common\helpers\FileHelper;
  6. /**
  7. * WebSocket 启动方式
  8. *
  9. * 启动 php ./yii websocket/start
  10. * 停止 php ./yii websocket/stop
  11. * 重启 php ./yii websocket/restart
  12. *
  13. * Class WebSocketController
  14. * @package console\controllers
  15. * @author qimall
  16. */
  17. class WebSocketController extends Controller
  18. {
  19. /**
  20. * 实例化服务
  21. *
  22. * @var WebSocketServer
  23. */
  24. public $server;
  25. /**
  26. * 监听地址
  27. *
  28. * @var string
  29. */
  30. public $host = '0.0.0.0';
  31. /**
  32. * 监听端口
  33. *
  34. * @var string
  35. */
  36. public $port = 9501;
  37. /**
  38. * 运行模式
  39. *
  40. * @var int
  41. */
  42. public $mode;
  43. /**
  44. * 传输协议
  45. *
  46. * @var int
  47. */
  48. public $socket_type;
  49. /**
  50. * 长连接方式
  51. *
  52. * @var string
  53. */
  54. public $type = 'ws';
  55. /**
  56. * swoole 配置
  57. *
  58. * @var array
  59. */
  60. public $config = [
  61. 'daemonize' => false, // 守护进程执行
  62. 'task_worker_num' => 4,//task进程的数量
  63. 'ssl_cert_file' => '',
  64. 'ssl_key_file' => '',
  65. 'pid_file' => '',
  66. 'buffer_output_size' => 2 * 1024 * 1024, //配置发送输出缓存区内存尺寸
  67. 'heartbeat_check_interval' => 60,// 心跳检测秒数
  68. 'heartbeat_idle_time' => 600,// 检查最近一次发送数据的时间和当前时间的差,大于则强行关闭
  69. ];
  70. /**
  71. * 启动
  72. *
  73. * @throws \yii\base\Exception
  74. */
  75. public function actionStart()
  76. {
  77. if ($this->getPid() !== false) {
  78. $this->stderr("服务已经启动...");
  79. exit(1);
  80. }
  81. // 写入进程
  82. $this->setPid();
  83. /** @var WebSocketServer $websocket 运行 */
  84. $websocket = new $this->server(
  85. $this->host,
  86. $this->port,
  87. $this->mode ?? SWOOLE_BASE,
  88. $this->socket_type ?? SWOOLE_SOCK_TCP,
  89. $this->type,
  90. $this->config
  91. );
  92. $websocket->run();
  93. $this->stdout("服务正在运行,监听 {$this->host}:{$this->port}" . PHP_EOL);
  94. }
  95. /**
  96. * 关闭进程
  97. */
  98. public function actionStop()
  99. {
  100. $this->sendSignal(SIGTERM);
  101. $this->stdout("服务已经停止, 停止监听 {$this->host}:{$this->port}" . PHP_EOL);
  102. }
  103. /**
  104. * 重启进程
  105. *
  106. * @throws \yii\base\Exception
  107. */
  108. public function actionRestart()
  109. {
  110. $this->sendSignal(SIGTERM);
  111. $time = 0;
  112. while (posix_getpgid($this->getPid()) && $time <= 10) {
  113. usleep(100000);
  114. $time++;
  115. }
  116. if ($time > 100) {
  117. $this->stderr("服务停止超时..." . PHP_EOL);
  118. exit(1);
  119. }
  120. if ($this->getPid() === false) {
  121. $this->stdout("服务重启成功..." . PHP_EOL);
  122. } else {
  123. $this->stderr("服务停止错误, 请手动处理杀死进程..." . PHP_EOL);
  124. }
  125. $this->actionStart();
  126. }
  127. /**
  128. * 发送信号
  129. *
  130. * @param $sig
  131. */
  132. private function sendSignal($sig)
  133. {
  134. if ($pid = $this->getPid()) {
  135. posix_kill($pid, $sig);
  136. } else {
  137. $this->stdout("服务未运行..." . PHP_EOL);
  138. }
  139. }
  140. /**
  141. * 获取pid进程
  142. *
  143. * @return bool|string
  144. */
  145. private function getPid()
  146. {
  147. $pid_file = $this->config['pid_file'];
  148. if (file_exists($pid_file)) {
  149. $pid = file_get_contents($pid_file);
  150. if (posix_getpgid($pid)) {
  151. return $pid;
  152. } else {
  153. unlink($pid_file);
  154. }
  155. }
  156. return false;
  157. }
  158. /**
  159. * 写入pid进程
  160. *
  161. * @throws \yii\base\Exception
  162. */
  163. private function setPid()
  164. {
  165. $parentPid = getmypid();
  166. $pidDir = dirname($this->config['pid_file']);
  167. if (!file_exists($pidDir)) {
  168. FileHelper::createDirectory($pidDir);
  169. }
  170. file_put_contents($this->config['pid_file'], $parentPid + 1);
  171. }
  172. }