您的位置:首页 > 编程语言 > PHP开发

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

2017-10-10 09:39 543 查看
时间: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官方人员得到,并为在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,对部分概念不是很清晰,上面若有写的不对的地方,请在评论中进行交流, 灰常感谢.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: