update to build 407

change daemon command from system to Process::kill
add master_pid for motd information
add option --preview
delete server_event_handler_class and use process
go-cqhttp-down.sh script add arm64 support
add ./zhamao support
change build-runtime.sh to install-runtime.sh
add option --disable-safe-exit
adjust some Console output
set start script using /bin/sh for supporting auto searching php and framework
This commit is contained in:
2021-05-08 10:02:41 +08:00
parent a80ee902a9
commit 71585ed29d
19 changed files with 248 additions and 394 deletions

View File

@@ -3,7 +3,7 @@
namespace ZM\Command;
use Symfony\Component\Console\Command\Command;
use Swoole\Process;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@@ -17,7 +17,7 @@ class DaemonReloadCommand extends DaemonCommand
protected function execute(InputInterface $input, OutputInterface $output): int {
parent::execute($input, $output);
system("kill -USR1 " . intval($this->daemon_file["pid"]));
Process::kill(intval($this->daemon_file["pid"]), SIGUSR1);
$output->writeln("<info>成功重载!</info>");
return 0;
}

View File

@@ -3,7 +3,6 @@
namespace ZM\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

View File

@@ -3,7 +3,7 @@
namespace ZM\Command;
use Symfony\Component\Console\Command\Command;
use Swoole\Process;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use ZM\Utils\DataProvider;
@@ -18,7 +18,7 @@ class DaemonStopCommand extends DaemonCommand
protected function execute(InputInterface $input, OutputInterface $output): int {
parent::execute($input, $output);
system("kill -INT " . intval($this->daemon_file["pid"]));
Process::kill(intval($this->daemon_file["pid"]), SIGINT);
unlink(DataProvider::getWorkingDir() . "/.daemon_pid");
$output->writeln("<info>成功停止!</info>");
return 0;

View File

@@ -12,6 +12,7 @@ use Symfony\Component\Console\Output\OutputInterface;
class InitCommand extends Command
{
private $extract_files = [
"/zhamao",
"/config/global.php",
"/.gitignore",
"/config/file_header.json",
@@ -50,11 +51,6 @@ class InitCommand extends Command
echo "Skipping " . $file . " , file exists." . PHP_EOL;
}
}
echo "Copying ./zhamao\n";
file_put_contents(
$base_path."/zhamao",
"#!/usr/bin/env php\n<?php require_once \"vendor/autoload.php\";(new ZM\ConsoleApplication(\"zhamao-framework\"))->initEnv(\"server\")->run();"
);
chmod($base_path."/zhamao", 0755);
$autoload = [
"psr-4" => [

View File

@@ -31,6 +31,8 @@ class RunServerCommand extends Command
new InputOption("watch", null, null, "监听 src/ 目录的文件变化并热更新"),
new InputOption("show-php-ver", null, null, "启动时显示PHP和Swoole版本"),
new InputOption("env", null, InputOption::VALUE_REQUIRED, "设置环境类型 (production, development, staging)"),
new InputOption("disable-safe-exit", null, null, "关闭安全退出关闭后按CtrlC时直接杀死进程"),
new InputOption("preview", null, null, "只显示参数,不启动服务器")
]);
$this->setDescription("Run zhamao-framework | 启动框架");
$this->setHelp("直接运行可以启动");

View File

@@ -19,8 +19,8 @@ use ZM\Command\SystemdCommand;
class ConsoleApplication extends Application
{
const VERSION_ID = 406;
const VERSION = "2.4.5";
const VERSION_ID = 407;
const VERSION = "2.5.0";
public function __construct(string $name = 'UNKNOWN') {
define("ZM_VERSION_ID", self::VERSION_ID);

View File

@@ -10,6 +10,7 @@ use Swoole\Server;
use ZM\Annotation\Swoole\SwooleHandler;
use ZM\Console\Console;
use ZM\Event\SwooleEvent;
use ZM\Framework;
/**
* Class OnManagerStart
@@ -19,9 +20,11 @@ use ZM\Event\SwooleEvent;
class OnManagerStart implements SwooleEvent
{
public function onCall(Server $server) {
pcntl_signal(SIGINT, function () {
Console::verbose("Interrupted in manager!");
});
if (!Framework::$argv["disable-safe-exit"]) {
pcntl_signal(SIGINT, function () {
Console::verbose("Interrupted in manager!");
});
}
Console::verbose("进程 Manager 已启动");
}
}

View File

@@ -24,18 +24,20 @@ class OnStart implements SwooleEvent
{
public function onCall(Server $server) {
$r = null;
Process::signal(SIGINT, function () use ($r, $server) {
if (zm_atomic("_int_is_reload")->get() === 1) {
zm_atomic("_int_is_reload")->set(0);
$server->reload();
} else {
echo "\r";
Console::warning("Server interrupted(SIGINT) on Master.");
if ((Framework::$server->inotify ?? null) !== null)
/** @noinspection PhpUndefinedFieldInspection */ Event::del(Framework::$server->inotify);
Process::kill($server->master_pid, SIGTERM);
}
});
if (!Framework::$argv["disable-safe-exit"]) {
Process::signal(SIGINT, function () use ($r, $server) {
if (zm_atomic("_int_is_reload")->get() === 1) {
zm_atomic("_int_is_reload")->set(0);
$server->reload();
} else {
echo "\r";
Console::warning("Server interrupted(SIGINT) on Master.");
if ((Framework::$server->inotify ?? null) !== null)
/** @noinspection PhpUndefinedFieldInspection */ Event::del(Framework::$server->inotify);
Process::kill($server->master_pid, SIGTERM);
}
});
}
if (Framework::$argv["daemon"]) {
$daemon_data = json_encode([
"pid" => $server->master_pid,
@@ -45,13 +47,13 @@ class OnStart implements SwooleEvent
}
if (Framework::$argv["watch"]) {
if (extension_loaded('inotify')) {
Console::warning("Enabled File watcher, do not use in production.");
Console::info("Enabled File watcher, framework will reload automatically.");
/** @noinspection PhpUndefinedFieldInspection */
Framework::$server->inotify = $fd = inotify_init();
$this->addWatcher(DataProvider::getWorkingDir() . "/src", $fd);
Event::add($fd, function () use ($fd) {
$r = inotify_read($fd);
dump($r);
Console::verbose("File updated: ".$r[0]["name"]);
ZMUtil::reload();
});
} else {

View File

@@ -33,7 +33,6 @@ use ZM\Store\MySQL\SqlPoolStorage;
use ZM\Store\Redis\ZMRedisPool;
use ZM\Utils\DataProvider;
use ZM\Utils\ProcessManager;
use ZM\Utils\ZMUtil;
/**
* Class OnWorkerStart
@@ -43,15 +42,19 @@ use ZM\Utils\ZMUtil;
class OnWorkerStart implements SwooleEvent
{
public function onCall(Server $server, $worker_id) {
Process::signal(SIGINT, function () use ($worker_id, $server) {
if (!Framework::$argv["disable-safe-exit"]) {
Process::signal(SIGINT, function () use ($worker_id, $server) {
});
});
}
unset(Context::$context[Coroutine::getCid()]);
if ($server->taskworker === false) {
Process::signal(SIGUSR1, function () use ($worker_id) {
Timer::clearAll();
ProcessManager::resumeAllWorkerCoroutines();
});
if (!Framework::$argv["disable-safe-exit"]) {
Process::signal(SIGUSR1, function () use ($worker_id) {
Timer::clearAll();
ProcessManager::resumeAllWorkerCoroutines();
});
}
zm_atomic("_#worker_" . $worker_id)->set($server->worker_pid);
if (LightCacheInside::get("wait_api", "wait_api") !== null) {
LightCacheInside::unset("wait_api", "wait_api");
@@ -84,7 +87,7 @@ class OnWorkerStart implements SwooleEvent
}
Console::info("新建SQL连接池中");
ob_start();
phpinfo();
phpinfo(); //这个phpinfo是有用的不能删除
$str = ob_get_clean();
$str = explode("\n", $str);
foreach ($str as $k => $v) {
@@ -130,7 +133,7 @@ class OnWorkerStart implements SwooleEvent
$dispatcher->dispatchEvents($server, $worker_id);
if ($dispatcher->status === EventDispatcher::STATUS_NORMAL) Console::debug("@OnStart 执行完毕");
else Console::warning("@OnStart 执行异常!");
Console::success("Worker #" . $worker_id . " 已启动");
Console::success("Worker #" . $worker_id . " started");
} catch (Exception $e) {
Console::error("Worker加载出错停止服务");
Console::error($e->getMessage() . "\n" . $e->getTraceAsString());
@@ -147,7 +150,7 @@ class OnWorkerStart implements SwooleEvent
try {
Framework::$server = $server;
$this->loadAnnotations();
Console::success("TaskWorker #" . $server->worker_id . " 已启动");
Console::success("TaskWorker #" . $server->worker_id . " started");
} catch (Exception $e) {
Console::error("Worker加载出错停止服务");
Console::error($e->getMessage() . "\n" . $e->getTraceAsString());

View File

@@ -7,6 +7,8 @@ namespace ZM;
use Doctrine\Common\Annotations\AnnotationReader;
use Error;
use Exception;
use Swoole\Event;
use Swoole\Process;
use Swoole\Server\Port;
use ZM\Annotation\Swoole\OnSetup;
use ZM\Config\ZMConfig;
@@ -109,6 +111,7 @@ class Framework
$out["environment"] = $args["env"] === null ? "default" : $args["env"];
$out["log_level"] = Console::getLevel();
$out["version"] = ZM_VERSION . (LOAD_MODE == 0 ? (" (build " . ZM_VERSION_ID . ")") : "");
$out["master_pid"] = posix_getpid();
if (APP_VERSION !== "unknown") $out["app_version"] = APP_VERSION;
if (isset($this->server_set["task_worker_num"])) {
$out["task_worker"] = $this->server_set["task_worker_num"];
@@ -135,7 +138,9 @@ class Framework
$out["working_dir"] = DataProvider::getWorkingDir();
self::printProps($out, $tty_width, $args["log-theme"] === null);
if ($args["preview"]) {
exit();
}
self::$server = new Server(ZMConfig::get("global", "host"), ZMConfig::get("global", "port"));
if ($add_port) {
@@ -297,47 +302,88 @@ class Framework
* @throws ReflectionException
*/
private function registerServerEvents() {
$event_list = [];
$reader = new AnnotationReader();
global $master_events;
$master_events = [
"setup" => [],
"event" => []
];
$all = getAllClasses(FRAMEWORK_ROOT_DIR . "/src/ZM/Event/SwooleEvent/", "ZM\\Event\\SwooleEvent");
foreach ($all as $v) {
$class = new $v();
$reflection_class = new ReflectionClass($class);
$anno_class = $reader->getClassAnnotation($reflection_class, SwooleHandler::class);
if ($anno_class !== null) { // 类名形式的注解
$anno_class->class = $v;
$anno_class->method = "onCall";
$event_list[strtolower($anno_class->event)] = $anno_class;
$master_events["event"][]=[
"class" => $v,
"method" => "onCall",
"event" => $anno_class->event
];
}
}
$all_event_class = ZMConfig::get("global", "server_event_handler_class") ?? [];
foreach ($all_event_class as $v) {
$reflection_class = new ReflectionClass($v);
$methods = $reflection_class->getMethods(ReflectionMethod::IS_PUBLIC);
foreach ($methods as $vs) {
$method_annotations = $reader->getMethodAnnotations($vs);
if ($method_annotations != []) {
$annotation = $method_annotations[0];
if ($annotation instanceof SwooleHandler) {
$annotation->class = $v;
$annotation->method = $vs->getName();
$event_list[strtolower($annotation->event)] = $annotation;
} elseif ($annotation instanceof OnSetup) {
$annotation->class = $v;
$annotation->method = $vs->getName();
$c = new $v();
$m = $annotation->method;
$c->$m();
$base_path = DataProvider::getWorkingDir();
$scan_paths = [];
$composer = json_decode(file_get_contents(DataProvider::getWorkingDir() . "/composer.json"), true);
foreach (($composer["autoload"]["psr-4"] ?? []) as $k => $v) {
if (is_dir($base_path."/".$v) && !in_array($v, $composer["extra"]["exclude_annotate"] ?? [])) {
$scan_paths[trim($k, "\\")]=realpath($base_path."/".$v);
}
}
$all_event_class = [];
foreach($scan_paths as $namespace => $autoload_path) {
$all_event_class = array_merge($all_event_class, getAllClasses($autoload_path."/", $namespace));
}
$process = new Process(function(Process $process) use ($all_event_class) {
$reader = new AnnotationReader();
$event_list = [];
$setup_list = [];
foreach ($all_event_class as $v) {
$reflection_class = new ReflectionClass($v);
$methods = $reflection_class->getMethods(ReflectionMethod::IS_PUBLIC);
foreach ($methods as $vs) {
$method_annotations = $reader->getMethodAnnotations($vs);
if ($method_annotations != []) {
$annotation = $method_annotations[0];
if ($annotation instanceof SwooleHandler) {
$event_list[]=[
"class" => $v,
"method" => $vs->getName(),
"event" => $annotation->event
];
} elseif ($annotation instanceof OnSetup) {
$setup_list[]=[
"class" => $v,
"method" => $vs->getName()
];
}
}
}
}
$sock = $process->exportSocket();
$sock->send(json_encode(["setup" => $setup_list, "event" => $event_list]));
});
$process->start();
go(function() use ($process) {
$socket = $process->exportSocket();
global $master_events;
$obj = json_decode($socket->recv(), true);
if ($obj["setup"] != []) $master_events["setup"] = array_merge($master_events["setup"], $obj["setup"]);
if ($obj["event"] != []) $master_events["event"] = array_merge($master_events["event"], $obj["event"]);
});
Process::wait(true);
Event::wait();
foreach($master_events["setup"] as $k => $v) {
$c = ZMUtil::getModInstance($v["class"]);
$method = $v["method"];
$c->$method();
}
foreach ($event_list as $k => $v) {
$c = ZMUtil::getModInstance($v->class);
$m = $v->method;
self::$server->on($k, function (...$param) use ($c, $m) { $c->$m(...$param); });
foreach ($master_events["event"] as $k => $v) {
self::$server->on($v["event"], function (...$param) use ($k, $v) {
ZMUtil::getModInstance($v["class"])->{$v["method"]}(...$param);
});
}
}
@@ -374,7 +420,8 @@ class Framework
case 'debug-mode':
$coroutine_mode = false;
$terminal_id = null;
Console::warning("You are in debug mode, do not use in production!");
self::$argv["watch"] = true;
echo ("* You are in debug mode, do not use in production!\n");
break;
case 'daemon':
$this->server_set["daemonize"] = 1;

5
src/entry.php Normal file
View File

@@ -0,0 +1,5 @@
<?php /** @noinspection PhpIncludeInspection */
require_once ((!is_dir(__DIR__ . '/../vendor')) ? getcwd() : (__DIR__ . "/..")) . "/vendor/autoload.php";
(new ZM\ConsoleApplication("zhamao-framework"))->initEnv()->run();