summer项目开发二:manage开发

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大致雏形就出来了,经过一晚上撸码,大致呈现如下:
1.jpg
2.jpg
3.jpg
4.jpg
5.jpg
6.jpg

代码已经提交到: 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,
];

这样我们就完成了一个基本的事件管理和扩展,现在我们只要合理的增加监听点,即可很方便的进行扩展。
7.jpg

细心的观众发现了,我用了Atomic生成了一个唯一的id,不知道Atomic的请看我前面一篇《重学swoole》里面有介绍到。
Atomic这个id+服务器的name+请求访问时间应该能生成一个唯一id了, 之所以要生成唯一id,是为了追述请求分发到哪些后端接口了,通过后端接口上报的日志,可以把一个请求所有的相关的日志聚合在一起,方便排查。

Atomic的性能是刚刚的,ab了一下,基本无损速度:
8.jpg

9.jpg

ab如果出现请求超时等情况,请看下swoole官网关于内核优化的一些注意事项https://wiki.swoole.com/wiki/page/p-server/sysctl.html
ulimit 需要重新设置,否则系统会限制请求数,不管怎么压都超时

ulimit -n
ulimit -n 100000
ulimit -n

ok,初步的扩展就开发到这里。接下来需要完成服务的后台运行,重启,检查功能。。。 待续。。

标签: 无

发表评论: