微服务框架php-msf使用时,问题记录.

时间:2017-10-10

php-msf版本:3.0.3

php版本:php7.1.8

swoole版本-1.9.18

vagrant版本:1.8.6

VM VirtualBox版本:5.1.8

操作系统;Win7_64bit

基于PHP-MSF DEMO项目.

介于官方文档中,常见问题信息太少,故在此做下记录.


目录结构

├── app // PHP业务代码
│   ├── AppServer.php // 应用server类,可根据需求自定义
│   ├── Controllers // 控制器类目录
│   ├── Lib // 特殊逻辑处理类目录
│   ├── Models // Model类目录
 |   ├         ├── Handlers目录 对外提供Rpc服务
 |   ├         ├── DTO目录  mysql table 对应的Model类
 |   ├         ├── DAO目录  mysql CRUD操作类 及 缓存处理.

│   ├── Route // 特殊路由规则类目录
│   ├── Tasks // Task类目录
│   └── Views // 视图文件目录

│   └── Services //业务逻辑处理类
├── build.sh // 构建脚本(拉取docker镜像,启动容器)
├── checkstyle.sh // 代码检查脚本
├── composer.json // composer包依赖配置文件
├── config // 配置目录
├── server.php // server启动脚本
├── console.php // 命令行脚本
├── test // 单元测试目录


MVC调用顺序为

Http请求:

Controller ---> Services ---> Dao ---> DTO

   |
   |

 Views


Rpc请求:  注意rpc.php配置

Handlers(Controller) ---> Services ---> Dao ---> DTO


遇到的问题记录


1.规范:config目录不能存放除配置信息以外的其他内容,

 比如一个php函数,如果有解析配置文件的函数,请放到Lib目录. 每个配置文件的最后都要return $config;


2.规范: Rpc的Handlers只能创建在models目录下.  

不一定非得是models目录,但无规矩不成方圆,很容易被用乱了.


3.Rpc的高可用及负载均衡(词挺高大上,希望你明白是啥意思.)

有一个配置文件 rpc.php 内容为:

$config['service']['demo']['host']    = 'http://192.168.33.22:8000';
$config['service']['demo']['timeout'] = 2000;

这里配置的名称demo,为服务名称,使用时

$this->getObject(RpcClient::class, ['demo'])->handler('sum')->func('multi', 1, 2, 3, 4, 5);
详情在Controller目录里的RpcTest.php文件中.

那么,现在问题来了,demo服务,部署在多台机器上, 提供同样的功能,

是在rpc.php文件里配置多个吗?还是?
建议的做法为 

$config['service']['demo']['host'] = 域名+端口.

然后使用阿里云SLB在域名解析上做负载均衡. 同类产品也可以.

或者,使用Nginx进行请求转发,然后做负载均衡,Nginx不一定非要和php-fpm合作,可以把请求转发到任意端口.


4.使用vagrant进行本地调试.代码变更之后worker没有自动reload

使用这个命令,运行就可以啦.

nodemon是node的解决方法.  记得一定要加上-L的参数,否则也是不好使的.

 nodemon -L --exec php server.php

效果请看下图

微服务框架php-msf使用时,问题记录._第1张图片

  或者使用
   从php-msf官方人员得到,并为在vagrant中进行使用测试,推荐大家使用Docker.

   公网地址: docker pull registry.cn-hangzhou.aliyuncs.com/pinguo-ops/php-msf-docker:latest


5.使用tail 命令查看日志文件时,不能使用jq小工具,以json格式方式查看日志. 日志内容看起来比较乱.

  建议重写日志内容组成部分的代码. monlog


6.关于yield关键字.

   Controller ---> Services ---> Dao ---> Model时.

如果Model层操作mysql时,使用了

$list =yield $this->getMysqlPool('master')->go(null, 'select * from biz');

那么,在Controller ---> Services ---> Dao是,都必须加上yield关键字,yield是需要层层嵌套的,否则程序异常.

但没有任何错误日志输出.

另外,当同一个类中A函数调用B函数时,如果B函数内部使用了yield关键字,那么A函数调用B函数时,也要使用yield关键字,否则程序异常. 

但依然没有任何错误日志输出.



7.编辑器phpStorm代码跳转失效. 

原因是

$dao  = $this->getObject(MerchantDao::class);
$list = yield $dao->getAllMerchant();
修改成下面这样,就可以了.

/**
  * @var MerchantDao $dao
*/
$dao  = $this->getObject(MerchantDao::class);
$list = yield $dao->getAllMerchant();
请使用 phpStorm2017版本, 如果低于这个版本,即使添加了@var注释,当使用yield关键字时,依然无法跳转.
如果需要phpStorm2017的安装包,汉化包,请在评论中进行留言.



8.如何修改View视图文件的后缀名?  默认为.php

   继承Controller类,重写outputView()函数. 

/**
     * 通过模板引擎响应输出HTML
     *
     * @param array $data 待渲染KV数据
     * @param string|null $view 文件名
     * @throws \Exception
     * @throws \Throwable
     * @throws Exception
     * @return void
     */
    public function outputView(array $data, $view = null)
    {
        if ($this->requestType !== Marco::HTTP_REQUEST) {
            throw new \Exception('$this->outputView not support '. $this->requestType);
        }
        $this->getContext()->getOutput()->setContentType('text/html; charset=UTF-8');
        if (empty($view)) {
            $view = str_replace('\\', '/', $this->getContext()->getControllerName()) . '/' .
                str_replace($this->getConfig()->get('http.method_prefix', 'action'), '', $this->getContext()->getActionName());
        }

        try {
            $viewFile = ROOT_PATH . '/app/Views/' . $view;
            $engine = getInstance()->templateEngine;
            //设置视图模版文件后缀格式
            $engine->setFileExtension('phtml');
            $template = $engine->make($viewFile);
            $response = $template->render($data);
        } catch (\Throwable $e) {
            $template = null;
            /**
             * 首先加载的视图文件为app/Views/Controller/Action.phtml,
             * 如果失败,会继续加载php-msf/src/Views/Controller/Action.phtml,如果还是失败,则会抛出异常。
             */
            $viewFile = getInstance()->MSFSrcDir . '/Views/' . $view;
            try {
                $engine = getInstance()->templateEngine;
                //设置视图模版文件后缀格式
                $engine->setFileExtension('phtml');
                $template = $engine->make($viewFile);
                $response = $template->render($data);
            } catch (\Throwable $e) {
                throw new Exception('app view and server view both not exist, please check again');
            }
        }

        $template = null;
        $this->getContext()->getOutput()->end($response);
    }



说明:本人第一次使用php-msf,对部分概念不是很清晰,上面若有写的不对的地方,请在评论中进行交流, 灰常感谢.


你可能感兴趣的:(PHP,微服务)