This commit is contained in:
2021-11-17 16:39:12 +08:00
parent 34432225c4
commit adc63be3e4
8 changed files with 75 additions and 340 deletions
-27
View File
@@ -1,27 +0,0 @@
<?php
namespace Server\Abstracts;
use Kiri\Exception\ConfigException;
use Kiri\Kiri;
use Psr\EventDispatcher\EventDispatcherInterface;
use ReflectionException;
use Server\ServerManager;
/**
*
*/
class OnTaskerStart extends WorkerStart implements EventDispatcherInterface
{
/**
*/
public function dispatch(object $event)
{
ServerManager::setEnv('environmental', Kiri::TASK);
}
}
-31
View File
@@ -1,31 +0,0 @@
<?php
namespace Server\Abstracts;
use Annotation\Annotation;
use Annotation\Inject;
use Exception;
use Http\Handler\Router;
use Kiri\Abstracts\Config;
use Kiri\Di\NoteManager;
use Kiri\Exception\ConfigException;
use Kiri\Kiri;
use Psr\EventDispatcher\EventDispatcherInterface;
use ReflectionException;
use Server\ServerManager;
class OnWorkerStart extends WorkerStart implements EventDispatcherInterface
{
/**
* @param object $event
* @return void
* @throws Exception
*/
public function dispatch(object $event)
{
ServerManager::setEnv('environmental', Kiri::WORKER);
}
}
-47
View File
@@ -1,47 +0,0 @@
<?php
namespace Server\Abstracts;
use Annotation\Annotation;
use Annotation\Inject;
use Http\Handler\Router;
use Kiri\Abstracts\Config;
use Kiri\Di\NoteManager;
use Kiri\Exception\ConfigException;
use Kiri\Kiri;
class WorkerStart
{
/**
* @var Annotation
*/
#[Inject(Annotation::class)]
public Annotation $annotation;
/**
* @var Router
*/
#[Inject(Router::class)]
public Router $router;
/**
* @param $prefix
* @throws ConfigException
*/
protected function setProcessName($prefix)
{
if (Kiri::getPlatform()->isMac()) {
return;
}
$name = Config::get('id', 'system-service');
if (!empty($prefix)) {
$name .= '.' . $prefix;
}
swoole_set_process_name($name);
}
}
+4 -15
View File
@@ -7,6 +7,7 @@ use Exception;
use Kiri\Abstracts\Config; use Kiri\Abstracts\Config;
use Kiri\Core\Help; use Kiri\Core\Help;
use Kiri\Events\EventDispatch; use Kiri\Events\EventDispatch;
use Kiri\Kiri;
use Kiri\Runtime; use Kiri\Runtime;
use Server\Events\OnAfterWorkerStart; use Server\Events\OnAfterWorkerStart;
use Server\Events\OnBeforeWorkerStart; use Server\Events\OnBeforeWorkerStart;
@@ -46,28 +47,16 @@ class OnServerWorker extends \Server\Abstracts\Server
if ($workerId < $server->setting['worker_num']) { if ($workerId < $server->setting['worker_num']) {
$this->eventDispatch->dispatch(new OnWorkerStart($server, $workerId)); $this->eventDispatch->dispatch(new OnWorkerStart($server, $workerId));
$this->setProcessName(sprintf('Worker[%d].%d', $server->worker_pid, $workerId)); $this->setProcessName(sprintf('Worker[%d].%d', $server->worker_pid, $workerId));
set_env('environmental', Kiri::WORKER);
} else { } else {
$this->eventDispatch->dispatch(new OnTaskStart($server, $workerId)); $this->eventDispatch->dispatch(new OnTaskStart($server, $workerId));
$this->setProcessName(sprintf('Tasker[%d].%d', $server->worker_pid, $workerId)); $this->setProcessName(sprintf('Tasker[%d].%d', $server->worker_pid, $workerId));
set_env('environmental', Kiri::TASK);
} }
$this->eventDispatch->dispatch(new OnAfterWorkerStart()); $this->eventDispatch->dispatch(new OnAfterWorkerStart());
} }
/**
* @param OnBeforeWorkerStart $worker
* @throws Exception
*/
public function setConfigure(OnBeforeWorkerStart $worker)
{
ServerManager::setEnv('worker', $worker->workerId);
$serialize = file_get_contents(storage(Runtime::CONFIG_NAME));
if (!empty($serialize)) {
Config::sets(unserialize($serialize));
}
}
/** /**
* @param Server $server * @param Server $server
* @param int $workerId * @param int $workerId
@@ -87,7 +76,7 @@ class OnServerWorker extends \Server\Abstracts\Server
*/ */
public function onWorkerExit(Server $server, int $workerId) public function onWorkerExit(Server $server, int $workerId)
{ {
ServerManager::setEnv('state', 'exit'); set_env('state', 'exit');
$this->eventDispatch->dispatch(new OnWorkerExit($server, $workerId)); $this->eventDispatch->dispatch(new OnWorkerExit($server, $workerId));
} }
+19 -31
View File
@@ -10,12 +10,6 @@ use Kiri\Abstracts\Config;
use Kiri\Events\EventProvider; use Kiri\Events\EventProvider;
use Kiri\Exception\ConfigException; use Kiri\Exception\ConfigException;
use Kiri\Kiri; use Kiri\Kiri;
use Server\Abstracts\OnTaskerStart as TaskerDispatch;
use Server\Abstracts\OnWorkerStart as WorkerDispatch;
use Server\Events\OnBeforeWorkerStart;
use Server\Events\OnTaskerStart;
use Server\Events\OnWorkerStart;
use Server\Handler\OnServerWorker;
use Swoole\Coroutine; use Swoole\Coroutine;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
@@ -61,28 +55,22 @@ class ServerCommand extends Command
*/ */
public function execute(InputInterface $input, OutputInterface $output): int public function execute(InputInterface $input, OutputInterface $output): int
{ {
try { $manager = Kiri::app()->getServer();
$manager = Kiri::app()->getServer(); $manager->setDaemon((int)!is_null($input->getOption('daemon')));
$manager->setDaemon((int)!is_null($input->getOption('daemon'))); if (is_null($input->getArgument('action'))) {
if (is_null($input->getArgument('action'))) { $input->setArgument('action', 'restart');
$input->setArgument('action', 'restart');
}
if (!in_array($input->getArgument('action'), self::ACTIONS)) {
throw new Exception('I don\'t know what I want to do.');
}
if ($manager->isRunner() && $input->getArgument('action') == 'start') {
throw new Exception('Service is running. Please use restart.');
}
$manager->shutdown();
if ($input->getArgument('action') == 'stop') {
throw new Exception('shutdown success');
}
$this->generate_runtime_builder($manager);
} catch (\Throwable $throwable) {
$output->write(jTraceEx($throwable));
} finally {
return 1;
} }
if (!in_array($input->getArgument('action'), self::ACTIONS)) {
throw new Exception('I don\'t know what I want to do.');
}
if ($manager->isRunner() && $input->getArgument('action') == 'start') {
throw new Exception('Service is running. Please use restart.');
}
$manager->shutdown();
if ($input->getArgument('action') == 'stop') {
throw new Exception('shutdown success');
}
return $this->generate_runtime_builder($manager);
} }
@@ -107,19 +95,19 @@ class ServerCommand extends Command
/** /**
* @param $manager * @param $manager
* @return int
* @throws ConfigException * @throws ConfigException
* @throws Exception * @throws Exception
*/ */
private function generate_runtime_builder($manager): void private function generate_runtime_builder($manager): int
{ {
$this->configure_set(); $this->configure_set();
Kiri::app()->getRouter()->read_files(); Kiri::app()->getRouter()->read_files();
$this->eventProvider->on(OnBeforeWorkerStart::class, [di(OnServerWorker::class), 'setConfigure']);
$this->eventProvider->on(OnWorkerStart::class, [di(WorkerDispatch::class), 'dispatch']);
$this->eventProvider->on(OnTaskerStart::class, [di(TaskerDispatch::class), 'dispatch']);
$manager->start(); $manager->start();
return 1;
} }
} }
+20 -80
View File
@@ -7,6 +7,7 @@ use Closure;
use Exception; use Exception;
use Kiri\Abstracts\Config; use Kiri\Abstracts\Config;
use Kiri\Di\ContainerInterface; use Kiri\Di\ContainerInterface;
use Kiri\Error\Logger;
use Kiri\Exception\ConfigException; use Kiri\Exception\ConfigException;
use Kiri\Kiri; use Kiri\Kiri;
use ReflectionException; use ReflectionException;
@@ -40,12 +41,19 @@ use Swoole\WebSocket\Server as WServer;
class ServerManager class ServerManager
{ {
use TraitServer;
/** @var string */ /** @var string */
public string $host = ''; public string $host = '';
public int $port = 0; public int $port = 0;
#[Inject(Logger::class)]
public Logger $logger;
/** @var array<string,Port> */ /** @var array<string,Port> */
public array $ports = []; public array $ports = [];
@@ -109,7 +117,6 @@ class ServerManager
*/ */
public function addListener(string $type, string $host, int $port, int $mode, array $settings = []) public function addListener(string $type, string $host, int $port, int $mode, array $settings = [])
{ {
if ($this->checkPortIsAlready($port)) $this->stopServer($port);
if (!$this->server) { if (!$this->server) {
$this->createBaseServer($type, $host, $port, $mode, $settings); $this->createBaseServer($type, $host, $port, $mode, $settings);
} else { } else {
@@ -131,8 +138,7 @@ class ServerManager
foreach ($this->sortService($configs['ports']) as $config) { foreach ($this->sortService($configs['ports']) as $config) {
$this->startListenerHandler($context, $config, $daemon); $this->startListenerHandler($context, $config, $daemon);
} }
$this->bindCallback($this->server, [Constant::PIPE_MESSAGE => [OnPipeMessage::class, 'onPipeMessage']]); $this->bindCallback([Constant::PIPE_MESSAGE => [OnPipeMessage::class, 'onPipeMessage']]);
// $this->bindCallback($this->server, $this->getSystemEvents($configs));
} }
@@ -145,7 +151,7 @@ class ServerManager
{ {
$configs = Config::get('server', [], true); $configs = Config::get('server', [], true);
foreach ($this->sortService($configs['ports']) as $config) { foreach ($this->sortService($configs['ports']) as $config) {
if ($this->checkPortIsAlready($config['port'])) { if (checkPortIsAlready($config['port'])) {
return true; return true;
} }
} }
@@ -167,7 +173,7 @@ class ServerManager
if (Kiri::getPlatform()->isLinux()) { if (Kiri::getPlatform()->isLinux()) {
$soloProcess->name($system . '(' . $customProcess->getName() . ')'); $soloProcess->name($system . '(' . $customProcess->getName() . ')');
} }
echo "\033[36m[" . date('Y-m-d H:i:s') . "]\033[0m " . $system . $customProcess->getName() . ' start.' . PHP_EOL; $this->logger->debug($system . $customProcess->getName() . ' start.');
$customProcess->signListen($soloProcess); $customProcess->signListen($soloProcess);
$customProcess->onHandler($soloProcess); $customProcess->onHandler($soloProcess);
}, },
@@ -175,7 +181,7 @@ class ServerManager
$customProcess->getPipeType(), $customProcess->getPipeType(),
$customProcess->isEnableCoroutine() $customProcess->isEnableCoroutine()
); );
// $this->container->setBindings($customProcess::class, $process); $this->container->setBindings($customProcess->getName(), $process);
$this->server->addProcess($process); $this->server->addProcess($process);
} }
@@ -189,30 +195,6 @@ class ServerManager
} }
/**
* @param array $ports
* @return array
*/
public function sortService(array $ports): array
{
$array = [];
foreach ($ports as $port) {
if ($port['type'] == Constant::SERVER_TYPE_WEBSOCKET) {
array_unshift($array, $port);
} else if ($port['type'] == Constant::SERVER_TYPE_HTTP) {
if (!empty($array) && $array[0]['type'] == Constant::SERVER_TYPE_WEBSOCKET) {
$array[] = $port;
} else {
array_unshift($array, $port);
}
} else {
$array[] = $port;
}
}
return $array;
}
/** /**
* @param string $key * @param string $key
* @param string|int $value * @param string|int $value
@@ -273,7 +255,8 @@ class ServerManager
{ {
$id = Config::get('id', 'system-service'); $id = Config::get('id', 'system-service');
echo sprintf("\033[36m[" . date('Y-m-d H:i:s') . "]\033[0m [%s]$type service %s::%d start.", $id, $host, $port) . PHP_EOL; $this->logger->debug(sprintf('[%s]' . $type . ' service %s::%d start', $id, $host, $port));
/** @var Server\Port $service */ /** @var Server\Port $service */
$this->ports[$port] = $this->server->addlistener($host, $port, $mode); $this->ports[$port] = $this->server->addlistener($host, $port, $mode);
if ($this->ports[$port] === false) { if ($this->ports[$port] === false) {
@@ -293,22 +276,6 @@ class ServerManager
} }
/**
* @param int $port
* @param string $event
* @return Closure|array|null
*/
public function getPortCallback(int $port, string $event): Closure|array|null
{
/** @var Server\Port $_port */
$_port = $this->ports[$port] ?? null;
if (is_null($_port)) {
return null;
}
return $_port->getCallback($event);
}
/** /**
* @param string $type * @param string $type
* @param string $host * @param string $host
@@ -317,6 +284,7 @@ class ServerManager
* @param array $settings * @param array $settings
* @throws ReflectionException * @throws ReflectionException
* @throws ConfigException * @throws ConfigException
* @throws Exception
*/ */
private function createBaseServer(string $type, string $host, int $port, int $mode, array $settings = []) private function createBaseServer(string $type, string $host, int $port, int $mode, array $settings = [])
{ {
@@ -331,7 +299,7 @@ class ServerManager
$id = Config::get('id', 'system-service'); $id = Config::get('id', 'system-service');
echo sprintf("\033[36m[" . date('Y-m-d H:i:s') . "]\033[0m [%s]$type service %s::%d start.", $id, $host, $port) . PHP_EOL; $this->logger->debug(sprintf('[%s]' . $type . ' service %s::%d start', $id, $host, $port));
$this->addDefaultListener($settings); $this->addDefaultListener($settings);
} }
@@ -343,43 +311,16 @@ class ServerManager
*/ */
public function stopServer(int $port) public function stopServer(int $port)
{ {
if (!($pid = $this->checkPortIsAlready($port))) { if (!($pid = checkPortIsAlready($port))) {
return; return;
} }
while ($this->checkPortIsAlready($port)) { while (checkPortIsAlready($port)) {
Process::kill($pid, SIGTERM); Process::kill($pid, SIGTERM);
usleep(300); usleep(300);
} }
} }
/**
* @param $port
* @return bool|string
* @throws Exception
*/
private function checkPortIsAlready($port): bool|string
{
if (!Kiri::getPlatform()->isLinux()) {
exec("lsof -i :" . $port . " | grep -i 'LISTEN' | awk '{print $2}'", $output);
if (empty($output)) return false;
$output = explode(PHP_EOL, $output[0]);
return $output[0];
}
$serverPid = file_get_contents(storage('.swoole.pid'));
if (!empty($serverPid) && shell_exec('ps -ef | grep ' . $serverPid . ' | grep -v grep')) {
Process::kill($serverPid, SIGTERM);
}
exec('netstat -lnp | grep ' . $port . ' | grep "LISTEN" | awk \'{print $7}\'', $output);
if (empty($output)) {
return false;
}
return explode('/', $output[0])[0];
}
/** /**
* @param array $settings * @param array $settings
* @throws ReflectionException * @throws ReflectionException
@@ -475,20 +416,19 @@ class ServerManager
{ {
$task_use_object = $this->server->setting['task_object'] ?? $this->server->setting['task_use_object'] ?? false; $task_use_object = $this->server->setting['task_object'] ?? $this->server->setting['task_use_object'] ?? false;
$reflect = $this->container->getReflect(OnServerTask::class)?->newInstance(); $reflect = $this->container->getReflect(OnServerTask::class)?->newInstance();
$this->server->on('finish', $events[Constant::FINISH] ?? [$reflect, 'onFinish']);
if ($task_use_object || $this->server->setting['task_enable_coroutine']) { if ($task_use_object || $this->server->setting['task_enable_coroutine']) {
$this->server->on('task', $events[Constant::TASK] ?? [$reflect, 'onCoroutineTask']); $this->server->on('task', $events[Constant::TASK] ?? [$reflect, 'onCoroutineTask']);
} else { } else {
$this->server->on('task', $events[Constant::TASK] ?? [$reflect, 'onTask']); $this->server->on('task', $events[Constant::TASK] ?? [$reflect, 'onTask']);
} }
$this->server->on('finish', $events[Constant::FINISH] ?? [$reflect, 'onFinish']);
} }
/** /**
* @param Port|Server $server
* @param array|null $settings * @param array|null $settings
*/ */
public function bindCallback(Port|Server $server, ?array $settings = []) public function bindCallback(?array $settings = [])
{ {
// TODO: Implement bindCallback() method. // TODO: Implement bindCallback() method.
if (count($settings) < 1) { if (count($settings) < 1) {
+32
View File
@@ -0,0 +1,32 @@
<?php
namespace Server;
trait TraitServer
{
/**
* @param array $ports
* @return array
*/
public function sortService(array $ports): array
{
$array = [];
foreach ($ports as $port) {
if ($port['type'] == Constant::SERVER_TYPE_WEBSOCKET) {
array_unshift($array, $port);
} else if ($port['type'] == Constant::SERVER_TYPE_HTTP) {
if (!empty($array) && $array[0]['type'] == Constant::SERVER_TYPE_WEBSOCKET) {
$array[] = $port;
} else {
array_unshift($array, $port);
}
} else {
$array[] = $port;
}
}
return $array;
}
}
-109
View File
@@ -1,109 +0,0 @@
<?php
namespace Server\Websocket;
use Annotation\Inject;
use Exception;
use Http\Handler\Router;
use Kiri\Error\Logger;
use Kiri\Kiri;
use Server\SInterface\OnCloseInterface;
use Swoole\Coroutine\Http\Server as CoroutineServer;
use Swoole\Http\Request;
use Swoole\Http\Response;
use Swoole\WebSocket\CloseFrame;
class Server
{
private CoroutineServer $server;
/**
* @var Router
*/
#[Inject(Router::class)]
public Router $router;
public function start()
{
$this->server->start();
}
/**
* @param string $Host
* @param int $Port
* @param bool $isSsl
* @param array $settings
*/
public function initCore(string $Host, int $Port, bool $isSsl, array $settings)
{
$this->server = new CoroutineServer($Host, $Port, $isSsl);
$this->server->set($settings['setting'] ?? []);
$this->server->handle('/', function (Request $request, Response $response) {
$class = new \stdClass();
if ($class instanceof OnHandshakeInterface) {
$class->onHandshake($request, $response);
} else if ($class instanceof OnOpenInterface) {
$response->upgrade();
$class->onOpen($this->server, $request);
}
if (!($class instanceof OnMessageInterface)) {
$response->setStatusCode(200);
$response->end();
} else {
$this->recover($class, $response);
}
});
}
/**
* @param OnCloseInterface|OnMessageInterface $class
* @param Response $response
* @return bool
* @throws Exception
*/
private function recover(OnCloseInterface|OnMessageInterface $class, Response $response): bool
{
$frame = $response->recv();
if ($frame === '' || $frame === FALSE) {
return $this->onClose($class, $response);
}
if ($frame->data == 'close' || get_class($frame) === CloseFrame::class) {
return $this->onClose($class, $response);
}
$class->onMessage($this->server, $frame);
return $this->recover($class, $response);
}
/**
* @param OnCloseInterface|OnMessageInterface $class
* @param Response $response
* @return bool
* @throws Exception
*/
private function onClose(OnCloseInterface|OnMessageInterface $class, Response $response): bool
{
if (!($close = $response->close())) {
Kiri::getDi()->get(Logger::class)->warning('close websocket fail.');
}
$class->onClose($this->server, $response->fd);
return $close;
}
/**
* @return CoroutineServer
*/
public function getServer(): CoroutineServer
{
return $this->server;
}
}