manage按之前的设计,需要一个命令行工具,需要一个http和websocket服务进行转发,然后有一系列功能需要扩展,万里长征需要迈出第一步。
命令行工具
上一篇文章选型的时候选择了https://github.com/inhere/php-console/blob/master/README_cn.md, 那么开始搭建自己的命令行吧
manage在设计的时候,我只把他设计成了一个命令行工具集,相关功能和扩展通过编写命令文件来完成。所以新建sufreame/manage/Core.php
这个类完成2件事情,加载命令行配置,转发命令即可,保持功能单一和结构简单。
class Core {
public function init(){} //初始化
public function run(array $args){} //执行命令转发
}
由于这个命令行库有部分不太满足需求,需要稍稍修改下,所以继承了下放到core里面进行了下改造。
初始化的时候需要一些配置,比如项目名称,logo,版本等,当然启动swoole http server也需要一些配置,所以引入了一个配置管理的库,对比了下用的https://github.com/hassankhan/config,不过还是稍稍有点不满足需求,同样继承下来做了稍稍修改放到core库。
ok,至此一个manage大致雏形就出来了,经过一晚上撸码,大致呈现如下:
代码已经提交到: GitHub:https://github.com/shulinqian/summer/tree/dev
事件
架构搭起了,为了不让核心代码越来越臃肿,需要引入事件机制,让运行的各个流程可定制和扩展。选型一个事件管理的库,目前选的https://zendframework.github.io/zend-eventmanager/
安装好库以后,再core/event/创建个文件EventManager作为全局事件管理的类
class EventManager implements EventManagerAwareInterface {
public function setEventManager(EventManagerInterface $eventManager) {}
public function getEventManager() {}
public static function get(){
return EventManager::getInstance()->getEventManager();
}
}
增加了个get方法,外面可以方便使用
EventManager::get()->attach() //监听事件
EventManager::get()->trigger() //触发事件
然后修改下manage/Core.php,各个节点增加attach
监听点有了,需要注册一些监听类来监听这些点。
例如我现在要swoole http的请求:
在core/http/Server.php中添加
EventManager::get()->trigger('http.request', null, $request);
然后在suframemanageevents目录下,新建listener类。
class HttpListener implements ListenerAggregateInterface {
use ListenerAggregateTrait;
public function attach(EventManagerInterface $events, $priority = 1) {
$this->listeners[] = $events->attach(Events::E_HTTP_REQUEST, [$this, 'request'], $priority);
}
public function request(EventInterface $e) {
/** @var Request $request */
$request = $e->getParams();
//生成唯一请求id
$id = Atomic::getInstance()->requestId();
$request->header['request-id'] = $id;
echo "新请求,通过事件" .$e->getName(), '访问id:'. $request->header['request-id'], "\n";
// echo $request->['request_time_float'] , "\n";
}
}
有了监听点,有了监听类,剩下的事情就是注册这些监听类到事件管理器里面。
在manageCore 的init中第一行添加个函数
$this->registerListener();
然后增加个方法
/**
* 注册事件
*/
protected function registerListener(){
$config = __DIR__ . '/config/listener.php';
$this->getConfig()->load($config);
//自定义事件
$selfConfig = SUMMER_APP_ROOT . 'config/listener.php';
$this->getConfig()->load($selfConfig);
$listeners = $this->getConfig()->get('listener');
if(!$listeners){
return;
}
$eventManager = EventManager::get();
foreach ($listeners as $listener) {
(new $listener)->attach($eventManager);
}
}
这样,我们就可以通过config里面的listener.php动态的完成监听类的热插拔。
修改suframemanageconfiglistener.php
<?php
return [
\suframe\manage\events\HttpListener::class,
];
这样我们就完成了一个基本的事件管理和扩展,现在我们只要合理的增加监听点,即可很方便的进行扩展。
细心的观众发现了,我用了Atomic生成了一个唯一的id,不知道Atomic的请看我前面一篇《重学swoole》里面有介绍到。
Atomic这个id+服务器的name+请求访问时间应该能生成一个唯一id了, 之所以要生成唯一id,是为了追述请求分发到哪些后端接口了,通过后端接口上报的日志,可以把一个请求所有的相关的日志聚合在一起,方便排查。
Atomic的性能是刚刚的,ab了一下,基本无损速度:
ab如果出现请求超时等情况,请看下swoole官网关于内核优化的一些注意事项https://wiki.swoole.com/wiki/page/p-server/sysctl.html
ulimit 需要重新设置,否则系统会限制请求数,不管怎么压都超时
ulimit -n
ulimit -n 100000
ulimit -n
ok,初步的扩展就开发到这里。接下来需要完成服务的后台运行,重启,检查功能。。。 待续。。