update to 2.2.11 verion

add build version (start from 384)
make 启动中 log as verbose
remove console input
fix pure http server bug
add error handler for zm_timer_tick and zm_timer_after
This commit is contained in:
jerry 2021-03-13 15:16:10 +08:00
parent b0be53554d
commit 7dc39e6ada
11 changed files with 74 additions and 47 deletions

View File

@ -21,9 +21,9 @@ function generate($argv) {
$s .= "\nGroup=" . exec("groups | awk '{print $1}'");
$s .= "\nWorkingDirectory=" . getcwd();
if ($argv[0] == "systemd" && !file_exists(getcwd() . '/systemd'))
$s .= "\nExecStart=" . getcwd() . "/vendor/bin/start server --disable-console-input";
$s .= "\nExecStart=" . getcwd() . "/vendor/bin/start server";
else
$s .= "\nExecStart=" . getcwd() . "/bin/start server --disable-console-input";
$s .= "\nExecStart=" . getcwd() . "/bin/start server";
$s .= "\nRestart=always\n\n[Install]\nWantedBy=multi-user.target\n";
@mkdir(getcwd() . "/resources/");
file_put_contents(getcwd() . "/resources/zhamao.service", $s);

View File

@ -3,7 +3,6 @@
"description": "High performance chat robot and web server development framework",
"minimum-stability": "stable",
"license": "Apache-2.0",
"version": "2.2.10",
"extra": {
"exclude_annotate": [
"src/ZM"

View File

@ -85,7 +85,6 @@ bin/start server # 通过源码模式启动框架
- `--debug-mode`:启用调试模式,调试模式的作用是关闭一键协程化和终端交互,减少 Swoole 本身对代码逻辑的干扰(比如执行 `shell_exec()` 报错的话可以开启这个进行调试)。
- `--log-{mode}`:设置 log 等级。支持 `--log-debug``--log-verbose``--log-info``--log-warning``--log-error`
- `--log-theme`:设置终端信息的主题。这个选项适用于多种终端信息显示的兼容,例如白色终端和不支持颜色的终端。详见 [Console - 主题设置](/component/console/#_2)。
- `--disable-console-input`:关闭终端交互,如果你使用的不是 tmux、screen 而是直接将进程使用 systemd 等方式运行到 init 守护进程下,则需要关闭终端交互输入,关闭后不可以使用 `stop, reload, logtest` 等交互命令。
- `--disable-coroutine`:关闭一键协程化。
- `--daemon`:以守护进程方式运行框架,此参数将直接在输出 motd 后将进程挂到 init 下运行,后台常驻。
- `--watch`:监控 `src/` 目录下的文件变化,有变化则自动重新载入代码。开启监控需要安装 PHP 扩展inotify。使用 pecl 就可以安装:`pecl install inotify`

View File

@ -17,7 +17,9 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use ZM\Config\ZMConfig;
use ZM\Console\Console;
use ZM\Framework;
use ZM\Store\ZMAtomic;
use ZM\Utils\DataProvider;
use ZM\Utils\HttpUtil;
class PureHttpCommand extends Command
@ -40,17 +42,26 @@ class PureHttpCommand extends Command
$output->writeln("<error>Directory error(" . ($input->getArgument('dir') ?? '.') . "): no such file or directory.</error>");
return self::FAILURE;
}
ZMConfig::setDirectory(DataProvider::getWorkingDir() . '/config');
$global = ZMConfig::get("global");
$host = $input->getOption("host") ?? $global["host"];
$port = $input->getOption("port") ?? $global["port"];
$index = ["index.html", "index.htm"];
$out = [
"listen" => $host.":".$port,
"version" => ZM_VERSION,
"web_root" => realpath($input->getArgument('dir') ?? '.'),
"index" => implode(",", $index)
];
Framework::printProps($out, $tty_width);
$server = new Server($host, $port);
$server->set(ZMConfig::get("global", "swoole"));
Console::init(0, $server);
Console::init(2, $server);
ZMAtomic::$atomics["request"] = [];
for ($i = 0; $i < 32; ++$i) {
ZMAtomic::$atomics["request"][$i] = new Atomic(0);
}
$index = ["index.html", "index.htm"];
$server->on("request", function (Request $request, Response $response) use ($input, $index, $server) {
ZMAtomic::$atomics["request"][$server->worker_id]->add(1);
HttpUtil::handleStaticPage(
@ -60,10 +71,11 @@ class PureHttpCommand extends Command
"document_root" => realpath($input->getArgument('dir') ?? '.'),
"document_index" => $index
]);
echo "\r" . Coroutine::stats()["coroutine_peak_num"];
//echo "\r" . Coroutine::stats()["coroutine_peak_num"];
});
$server->on("start", function ($server) {
Process::signal(SIGINT, function () use ($server) {
echo "\r";
Console::warning("Server interrupted by keyboard.");
for ($i = 0; $i < 32; ++$i) {
$num = ZMAtomic::$atomics["request"][$i]->get();
@ -75,13 +87,6 @@ class PureHttpCommand extends Command
});
Console::success("Server started. Use Ctrl+C to stop.");
});
$out = [
"host" => $host,
"port" => $port,
"document_root" => realpath($input->getArgument('dir') ?? '.'),
"document_index" => implode(", ", $index)
];
Console::printProps($out, $tty_width);
$server->start();
// return this if there was no problem running the command
// (it's equivalent to returning int(0))

View File

@ -22,11 +22,11 @@ class RunServerCommand extends Command
new InputOption("log-warning", null, null, "调整消息等级到warning (log-level=1)"),
new InputOption("log-error", null, null, "调整消息等级到error (log-level=0)"),
new InputOption("log-theme", null, InputOption::VALUE_REQUIRED, "改变终端的主题配色"),
new InputOption("disable-console-input", null, null, "禁止终端输入内容 (后台服务时需要)"),
new InputOption("disable-console-input", null, null, "禁止终端输入内容 (废弃)"),
new InputOption("disable-coroutine", null, null, "关闭协程Hook"),
new InputOption("daemon", null, null, "以守护进程的方式运行框架"),
new InputOption("watch", null, null, "监听 src/ 目录的文件变化并热更新"),
new InputOption("show-php-ver", null, null, "启动时显示PHP版本"),
new InputOption("show-php-ver", null, null, "启动时显示PHP和Swoole版本"),
new InputOption("env", null, InputOption::VALUE_REQUIRED, "设置环境类型 (production, development, staging)"),
]);
$this->setDescription("Run zhamao-framework | 启动框架");

View File

@ -18,9 +18,13 @@ use ZM\Utils\DataProvider;
class ConsoleApplication extends Application
{
const VERSION_ID = 384;
const VERSION = "2.2.11";
public function __construct(string $name = 'UNKNOWN') {
$version = json_decode(file_get_contents(__DIR__ . "/../../composer.json"), true)["version"] ?? "UNKNOWN";
parent::__construct($name, $version);
define("ZM_VERSION_ID", self::VERSION_ID);
define("ZM_VERSION", self::VERSION);
parent::__construct($name, ZM_VERSION);
}
public function initEnv() {

View File

@ -47,10 +47,8 @@ use ZM\Store\LightCacheInside;
use ZM\Store\MySQL\SqlPoolStorage;
use ZM\Store\Redis\ZMRedisPool;
use ZM\Store\WorkerCache;
use ZM\Store\ZMBuf;
use ZM\Utils\DataProvider;
use ZM\Utils\HttpUtil;
use ZM\Utils\Terminal;
use ZM\Utils\ZMUtil;
class ServerEventHandler
@ -59,9 +57,9 @@ class ServerEventHandler
* @SwooleHandler("start")
*/
public function onStart() {
global $terminal_id;
//global $terminal_id;
$r = null;
if ($terminal_id !== null) {
/*if ($terminal_id !== null) {
ZMBuf::$terminal = $r = STDIN;
Event::add($r, function () use ($r) {
$fget = fgets($r);
@ -78,7 +76,7 @@ class ServerEventHandler
Console::error("Uncaught error " . get_class($e) . ": " . $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")");
}
});
}
}*/
Process::signal(SIGINT, function () use ($r) {
if (zm_atomic("_int_is_reload")->get() === 1) {
zm_atomic("_int_is_reload")->set(0);
@ -159,7 +157,7 @@ class ServerEventHandler
else server()->shutdown();
});
Console::info("Worker #{$server->worker_id} 启动中");
Console::verbose("Worker #{$server->worker_id} 启动中");
Framework::$server = $server;
//ZMBuf::resetCache(); //清空变量缓存
//ZMBuf::set("wait_start", []); //添加队列在workerStart运行完成前先让其他协程等待执行
@ -233,7 +231,7 @@ class ServerEventHandler
$this->loadAnnotations(); //加载composer资源、phar外置包、注解解析注册等
//echo json_encode(debug_backtrace(), 128|256);
Console::success("Worker #" . $worker_id . " 已启动");
EventManager::registerTimerTick(); //启动计时器
//ZMBuf::unsetCache("wait_start");
set_coroutine_params(["server" => $server, "worker_id" => $worker_id]);
@ -244,6 +242,7 @@ class ServerEventHandler
$dispatcher->dispatchEvents($server, $worker_id);
if ($dispatcher->status === EventDispatcher::STATUS_NORMAL) Console::debug("@OnStart 执行完毕");
else Console::warning("@OnStart 执行异常!");
Console::success("Worker #" . $worker_id . " 已启动");
} catch (Exception $e) {
Console::error("Worker加载出错停止服务");
Console::error($e->getMessage() . "\n" . $e->getTraceAsString());
@ -316,7 +315,7 @@ class ServerEventHandler
Console::trace();
} catch (Error $e) {
$error_msg = $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")";
Console::error("Uncaught Error " . get_class($e) . " when calling \"message\": " . $error_msg);
Console::error("Uncaught " . get_class($e) . " when calling \"message\": " . $error_msg);
Console::trace();
}
@ -466,7 +465,7 @@ class ServerEventHandler
Console::trace();
} catch (Error $e) {
$error_msg = $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")";
Console::error("Uncaught Error " . get_class($e) . " when calling \"open\": " . $error_msg);
Console::error("Uncaught " . get_class($e) . " when calling \"open\": " . $error_msg);
Console::trace();
}
//EventHandler::callSwooleEvent("open", $server, $request);
@ -513,7 +512,7 @@ class ServerEventHandler
Console::trace();
} catch (Error $e) {
$error_msg = $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")";
Console::error("Uncaught Error " . get_class($e) . " when calling \"close\": " . $error_msg);
Console::error("Uncaught " . get_class($e) . " when calling \"close\": " . $error_msg);
Console::trace();
}
ManagerGM::popConnect($fd);
@ -641,7 +640,8 @@ class ServerEventHandler
$composer = json_decode(file_get_contents(DataProvider::getWorkingDir() . "/composer.json"), true);
foreach ($dir as $v) {
if (is_dir($path . "/" . $v) && isset($composer["autoload"]["psr-4"][$v . "\\"]) && !in_array($composer["autoload"]["psr-4"][$v . "\\"], $composer["extra"]["exclude_annotate"] ?? [])) {
Console::verbose("Add " . $v . " to register path");
if (\server()->worker_id == 0)
Console::verbose("Add " . $v . " to register path");
$parser->addRegisterPath(DataProvider::getWorkingDir() . "/src/" . $v . "/", $v);
}
}

View File

@ -94,7 +94,7 @@ class Framework
else $out["worker"] = ZMConfig::get("global", "swoole")["worker_num"];
$out["environment"] = $args["env"] === null ? "default" : $args["env"];
$out["log_level"] = Console::getLevel();
$out["version"] = ZM_VERSION;
$out["version"] = ZM_VERSION . (LOAD_MODE == 0 ? (" (build " . ZM_VERSION_ID . ")") : "");
if (APP_VERSION !== "unknown") $out["app_version"] = APP_VERSION;
if (isset(ZMConfig::get("global", "swoole")["task_worker_num"])) {
$out["task_worker"] = ZMConfig::get("global", "swoole")["task_worker_num"];
@ -112,6 +112,7 @@ class Framework
}
if (self::$argv["show-php-ver"] !== false) {
$out["php_version"] = PHP_VERSION;
$out["swoole_version"] = SWOOLE_VERSION;
}
$out["working_dir"] = DataProvider::getWorkingDir();
@ -120,7 +121,7 @@ class Framework
self::$server = new Server(ZMConfig::get("global", "host"), ZMConfig::get("global", "port"));
self::$server->set($this->server_set);
Console::setServer(self::$server);
self::printMotd($tty_width);
global $asd;

View File

@ -16,17 +16,10 @@ class LightCacheInside
public static $last_error = '';
public static function init() {
self::$kv_table["wait_api"] = new Table(3, 0);
self::$kv_table["wait_api"]->column("value", Table::TYPE_STRING, 65536);
self::$kv_table["connect"] = new Table(8, 0);
self::$kv_table["connect"]->column("value", Table::TYPE_STRING, 256);
$result = self::$kv_table["wait_api"]->create() && self::$kv_table["connect"]->create();
if ($result === false) {
self::$last_error = '系统内存不足,申请失败';
return false;
} else {
return true;
}
self::createTable("wait_api", 3, 65536); //用于存协程等待的状态内容的
self::createTable("connect", 3, 64); //用于存单机器人模式下的机器人fd的
//self::createTable("worker_start", 2, 1024);//用于存启动服务器时的状态的
return true;
}
/**
@ -62,4 +55,17 @@ class LightCacheInside
public static function unset(string $table, string $key) {
return self::$kv_table[$table]->del($key);
}
/**
* @param $name
* @param $size
* @param $str_size
* @throws ZMException
*/
private static function createTable($name, $size, $str_size) {
self::$kv_table[$name] = new Table($size, 0);
self::$kv_table[$name]->column("value", Table::TYPE_STRING, $str_size);
$r = self::$kv_table[$name]->create();
if ($r === false) throw new ZMException("内存不足,创建静态表失败!");
}
}

View File

@ -5,7 +5,6 @@ use ZM\Utils\DataProvider;
define("ZM_START_TIME", microtime(true));
define("ZM_DATA", ZMConfig::get("global", "zm_data"));
define("ZM_VERSION", json_decode(file_get_contents(__DIR__ . "/../../composer.json"), true)["version"] ?? "unknown");
define("APP_VERSION", LOAD_MODE == 1 ? (json_decode(file_get_contents(DataProvider::getWorkingDir() . "/composer.json"), true)["version"] ?? "unknown") : "unknown");
define("CRASH_DIR", ZMConfig::get("global", "crash_dir"));
@mkdir(ZM_DATA);

View File

@ -261,19 +261,33 @@ function zm_yield() { Co::yield(); }
function zm_resume(int $cid) { Co::resume($cid); }
function zm_timer_after($ms, callable $callable) {
go(function () use ($ms, $callable) {
Swoole\Timer::after($ms, $callable);
Swoole\Timer::after($ms, function () use ($callable) {
call_with_catch($callable);
});
}
function call_with_catch($callable) {
try {
$callable();
} catch (Exception $e) {
$error_msg = $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")";
Console::error("Uncaught exception " . get_class($e) . " when calling \"message\": " . $error_msg);
Console::trace();
} catch (Error $e) {
$error_msg = $e->getMessage() . " at " . $e->getFile() . "(" . $e->getLine() . ")";
Console::error("Uncaught " . get_class($e) . " when calling \"message\": " . $error_msg);
Console::trace();
}
}
function zm_timer_tick($ms, callable $callable) {
if (zm_cid() === -1) {
return go(function () use ($ms, $callable) {
Console::debug("Adding extra timer tick of " . $ms . " ms");
Swoole\Timer::tick($ms, $callable);
Swoole\Timer::tick($ms, function () use ($callable) {call_with_catch($callable);});
});
} else {
return Swoole\Timer::tick($ms, $callable);
return Swoole\Timer::tick($ms, function () use ($callable) {call_with_catch($callable);});
}
}