Files
zhamao-framework/src/ZM/Framework.php
2020-11-03 21:02:24 +08:00

253 lines
8.9 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace ZM;
use Doctrine\Common\Annotations\AnnotationReader;
use Exception;
use ZM\Annotation\Swoole\SwooleSetup;
use ZM\Config\ZMConfig;
use ZM\ConnectionManager\ManagerGM;
use ZM\Event\ServerEventHandler;
use ZM\Store\LightCache;
use ZM\Store\LightCacheInside;
use ZM\Store\Lock\SpinLock;
use ZM\Store\ZMAtomic;
use ZM\Utils\DataProvider;
use Framework\RemoteShell;
use ReflectionClass;
use ReflectionException;
use ReflectionMethod;
use Swoole\Runtime;
use Swoole\WebSocket\Server;
use ZM\Annotation\Swoole\HandleEvent;
use ZM\Console\Console;
use ZM\Utils\ZMUtil;
class Framework
{
/**
* @var array
*/
public static $argv;
/**
* @var Server
*/
public static $server;
/**
* @var array|bool|mixed|null
*/
private $server_set;
public function __construct($args = []) {
$tty_width = $this->getTtyWidth();
self::$argv = $args;
//定义常量
include_once "global_defines.php";
ZMAtomic::init();
try {
ManagerGM::init(ZMConfig::get("global", "swoole")["max_connection"] ?? 2048, 0.5, [
[
"key" => "connect_id",
"type" => "string",
"size" => 30
],
[
"key" => "type",
"type" => "int"
]
]);
} catch (ConnectionManager\TableException $e) {
die($e->getMessage());
}
try {
self::$server = new Server(ZMConfig::get("global", "host"), ZMConfig::get("global", "port"));
$this->server_set = ZMConfig::get("global", "swoole");
Console::init(
ZMConfig::get("global", "info_level"),
self::$server,
$args["log-theme"] ?? "default",
($o = ZMConfig::get("console_color")) === false ? [] : $o
);
$timezone = ZMConfig::get("global", "timezone") ?? "Asia/Shanghai";
date_default_timezone_set($timezone);
$this->parseCliArgs(self::$argv);
$out = [
"host" => ZMConfig::get("global", "host"),
"port" => ZMConfig::get("global", "port"),
"log_level" => Console::getLevel(),
"version" => ZM_VERSION,
"config" => $args["env"] === null ? 'global.php' : $args["env"]
];
if (isset(ZMConfig::get("global", "swoole")["task_worker_num"])) {
$out["task_worker_num"] = ZMConfig::get("global", "swoole")["task_worker_num"];
}
if (($num = ZMConfig::get("global", "swoole")["worker_num"] ?? swoole_cpu_num()) != 1) {
$out["worker_num"] = $num;
}
$out["working_dir"] = DataProvider::getWorkingDir();
Console::printProps($out, $tty_width);
self::$server->set($this->server_set);
if (file_exists(DataProvider::getWorkingDir() . "/config/motd.txt")) {
$motd = file_get_contents(DataProvider::getWorkingDir() . "/config/motd.txt");
} else {
$motd = file_get_contents(__DIR__ . "/../../config/motd.txt");
}
$motd = explode("\n", $motd);
foreach ($motd as $k => $v) {
$motd[$k] = substr($v, 0, $tty_width);
}
$motd = implode("\n", $motd);
echo $motd;
global $asd;
$asd = get_included_files();
// 注册 Swoole Server 的事件
$this->registerServerEvents();
$r = ZMConfig::get("global", "light_cache") ?? [
"size" => 1024,
"max_strlen" => 8192,
"hash_conflict_proportion" => 0.6,
"persistence_path" => realpath(DataProvider::getDataFolder() . "_cache.json"),
"auto_save_interval" => 900
];
LightCache::init($r);
LightCacheInside::init();
SpinLock::init($r["size"]);
self::$server->start();
} catch (Exception $e) {
Console::error("Framework初始化出现错误请检查");
Console::error($e->getMessage());
die;
}
}
/**
* 从全局配置文件里读取注入系统事件的类
* @throws ReflectionException
* @throws ReflectionException
*/
private function registerServerEvents() {
$all_event_class = ZMConfig::get("global", "server_event_handler_class") ?? [];
if (!in_array(ServerEventHandler::class, $all_event_class)) {
$all_event_class[] = ServerEventHandler::class;
}
$event_list = [];
foreach ($all_event_class as $v) {
$reader = new AnnotationReader();
$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 HandleEvent) {
$annotation->class = $v;
$annotation->method = $vs->getName();
$event_list[strtolower($annotation->event)] = $annotation;
} elseif ($annotation instanceof SwooleSetup) {
$annotation->class = $v;
$annotation->method = $vs->getName();
$c = new $v();
$m = $annotation->method;
$c->$m();
}
}
}
}
foreach ($event_list as $k => $v) {
self::$server->on($k, function (...$param) use ($v) {
$c = ZMUtil::getModInstance($v->class);
$m = $v->method;
$c->$m(...$param);
});
}
}
/**
* 解析命令行的 $argv 参数们
* @param $args
* @throws Exception
*/
private function parseCliArgs($args) {
$coroutine_mode = true;
global $terminal_id;
$terminal_id = call_user_func(function () {
try {
$data = random_bytes(16);
} catch (Exception $e) {
return "";
}
$data[6] = chr(ord($data[6]) & 0x0f | 0x40);
$data[8] = chr(ord($data[8]) & 0x3f | 0x80);
return strtoupper(vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4)));
});
foreach ($args as $x => $y) {
switch ($x) {
case 'disable-coroutine':
if ($y) {
$coroutine_mode = false;
}
break;
case 'debug-mode':
if ($y || ZMConfig::get("global", "debug_mode")) {
$coroutine_mode = false;
$terminal_id = null;
Console::warning("You are in debug mode, do not use in production!");
}
break;
case 'daemon':
if ($y) {
$this->server_set["daemonize"] = 1;
Console::log("已启用守护进程,输出重定向到 " . $this->server_set["log_file"]);
$terminal_id = null;
}
break;
case 'disable-console-input':
if ($y) $terminal_id = null;
break;
case 'remote-shell':
if ($y) {
$host = "127.0.0.1";
$port = 9599;
RemoteShell::listen(self::$server, $host, $port);
Console::log(Console::setColor("正在监听" . $host . ":" . strval($port) . "的调试接口,请注意安全", "yellow"));
}
break;
case 'log-error':
if ($y) Console::setLevel(0);
break;
case 'log-warning':
if ($y) Console::setLevel(1);
break;
case 'log-info':
if ($y) Console::setLevel(2);
break;
case 'log-verbose':
if ($y) Console::setLevel(3);
break;
case 'log-debug':
if ($y) Console::setLevel(4);
break;
case 'log-theme':
if ($y !== null) {
Console::$theme = $y;
}
break;
}
}
if ($coroutine_mode) Runtime::enableCoroutine(true, SWOOLE_HOOK_ALL);
}
public static function getTtyWidth() {
return explode(" ", trim(exec("stty size")))[1];
}
}