PHP 超文本预处理器 Personal Home Page Hypertext Preprocessor 英文超文本预处理语言 php语言 ＰＨＰ PHP发展 PHP开发工具 PHP特性 PHP优势 PHP技术应用 PHP参考手册 PHP版本区别 PHPPHP3 PHPPHP4 PHPPHP5 PHP版本6设想 PHP环境配置 PHP其他方面
一般在测试接口的是后，会用到postman等工具，其实phpstrom自带了一个挺好用的功能项目下新建个文件 demo.http点击 Add Request按钮下边即可出现结果，你可以自定义header之类的，也可以设置cookie
项目地址：https://github.com/suframe/think使用thinkphp6作为suframe服务后端的扩展库，让thinkphp6有轻量级微服务功能 本库基于https://github.com/top-think/think-swoole (v3.0.5以上版本)上进行的扩展，基本保持原有用法不变。本系统只针对小型业务系统，大规模的微服务架构请移步到我的其他文章什么是微服务设计教程一.创建1个thinkphp项目作为服务二.复制server1命名为 server2三.修改配置1. 进入serve1目录2. 打开config/swoole.php3. 打开config/suframeProxy.php,4. app下新建文件夹 rpc和 rpc/interfaces5. 新建接口6. 新建服务文件7. 将NewsService注册到服务中去启动swoole8. server2同样处理，命名为goods或者你喜欢的名字，然后启动9. server1中调用server2的服务测试10. 访问http://127.0.0.1:8090开发此功能是为了完善summer体系，形成 api网关(api接口转发)，中控台（带auth菜单权限的后台），服务（rpc内部接口，rest 对外api接口）的完整体系：前端访问 -> api网关 -> 后端服务api -> rest服务(服务间rcp <-> 调用服务注册发现) <- think-admin管理服务及通过rpc接口管理数据什么是微服务大佬就可以略过了，下面的针对对微服务比较模糊，没有尝试过的新手希望有点帮助，也只是我自己个人的见解而已。现在微服务大行其道，各种架构层出不穷，由于使用到的工具繁多，涉及的从运维到开发技术架构都带来非常大的挑战。php在微服务一块比较弱，本身限制于语言特性。swoole的出现让php异步高性能开发有了更多的可能性，作为后端服务再合适不过。说到微服务，就不得不提开发模式的几次改进。微服务又解决了什么问题呢。为什么有人很厌恶它，有人喜欢他呢？当然有人还可能杠一下，现在都有更先进的概念：无服务器架构Serverless 等等，这里就不去杠了，爱谁谁吧。传统的系统，都是1个项目撸完，从管理，到前端，各种模块无限制的网上叠加。导致维护和升级都非常困难，比如想试试thinkphp6吧，以前代码不支持。业务量大了，想分布式部署吧，每台机器全部业务代码都得部署一次，而且每台机器都得是全环境。少一个都运行不了。微服务解决了什么？把一个系统里的各个功能模块给拆分出来，独立运行，提供接口给其他模块用。 这时候出现了一个问题，服务多了，服务地址不好管理，你可以把所有服务的ip和端口记下来，每次上新服务或者下服务的时候全部去改一次。 太累了。这个时候就出现了服务注册和发现什么是服务注册和发现呢，可以理解为，启动一个进程，所有服务上线都告知这个进程我在这个ip的这个端口有某项服务，你负责通知所有在你这里注册的服务更新下自己的服务列表，把我加进去， 然后大家就可以愉快的互相调用，整个过程是自动的。 当然完善的服务注册与发现还有很多细化的功能。 这里有点需要注意，rpc接口是对内的，不开放外网的，而且一般小系统是服务之间是直连的，大的架构是有一系列的工具解决授权限流降级等问题的，这里我们不做讨论，这个功能之针对小业务系统内部服务的服务注册和发现有了,，这个时候问题又来了，服务都分散成小应用了，前端需要的接口，难道我前端得准备一个api地址的列表吗？一堆ip和端口，自己去找要调用的api? 这个时候 api网关成为了重要角色，api网关负责转发前端接口到后端提供的rest服务上，前端只用知道api网关的地址即可。至于后端哪些服务在提供就是完全透明的。 当然api网关还有很多的工作需要做，详细可以去了解下kong等api网关的功能,至此完成了上面一个简易的闭环：前端访问 -> api网关 -> 后端服务api -> rest服务(服务间rcp <-> 调用服务注册发现) <- think-admin管理服务及通过rpc接口管理数据设计通过composer create-project topthink/think创建的为一个独立项目一个项目为一个服务提供者一个服务提供者可以提供多个接口自动注册接口到注册中心有新服务注册，自动更新client列表api网关代理(未完成)本来按照以前sufame-proxy的模式基于think-swoole写了一个，但是think-swoole升级3.0.5后改动太大，无法兼容，不得已，又重新撸了这个。 本着最简实现的原则，未改动think-swoole的原有写法，你依然可以按照他原有方式开发。新的版本，每个服务都可以作为注册中心，当然我没开发自动剔除和选举注册中心，有兴趣的可以修改suframeProxy.php里面的注册地址通过回调函数读取zeekooper，作为注册中心，保证实时切换，不过目前先不用考虑，我们只用一个负载不高，又常驻的作为注册中心即可，后面集成到think-admin后，推荐think-admin作为注册中心。教程先来体验一下吧：你当然也可以根据https://github.com/suframe/think中的快速体验clone demo进行体验，下面的步骤是让你一步步创建自己的服务。一.创建1个thinkphp项目作为服务composer create-project topthink/think server1 cd server1 composer require suframe/think:dev-master二.复制server1命名为 server2cp -r server1 server2三.修改配置1. 进入serve1目录2. 打开config/swoole.php修改server.port为8090 如果2个服务在2台机器的话，修改server.host为0.0.0.0 修改rpc.server.enable 为true修改rpc.server.port 为8091修改rpc.client => include(__DIR__ . '/suframeRpcClient.php');3. 打开config/suframeProxy.php,注意每个服务的path和name都是唯一的，非容器模式下，同一台服务器port和rpcPort也是唯一的path => '/news' 为你想注册的api网关根路径，例如/news, name => 'news' 为你服务的名称（只能是英文字母） registerServer => [ 'ip' => '127.0.0.1' //选一个应用作为服务注册的应用，这里就选第一个 'port' => 8091 ]4. app下新建文件夹 rpc和 rpc/interfaces5. 新建接口rpc/interfaces目录下新建个服务接口 NewsInterface.php<?php namespace app\rpc\interfaces; interface NewsInterface { function get($name); }6. 新建服务文件rpc/ 新建文件NewsService.php<?php namespace app\rpc; use interfaces\NewsInterface; class NewsService impelement NewsInterface { function get($name) { return 'hello news ' . $name; } }7. 将NewsService注册到服务中去打开config/swoole.phprpc.server.services => [ \app\rpc\NewsService::class, ]启动swoolephp think swoole8. server2同样处理，命名为goods或者你喜欢的名字，然后启动9. server1中调用server2的服务测试打开文件 app/controller/Index.php，增加个测试方法 public function rpctest(\rpc\contarct\goods\GoodsInterface $goods) { return $goods->get('sever 1 call serve 2'); }10. 访问http://127.0.0.1:8090ps：遇到swoole卡住无法重启的情况， 第一检测runtime目录下是否有swoole.pid，有则删除 第二:运行ps -ef | grep swoole | grep -v grep | cut -c 9-15 | xargs kill -9
summer进入中控台开发，中后台开发最经常开发的就是表单和列表，有个好用的表单构建能大大的加速开发，喜欢偷懒的我当然不会错过开发一个表单构建的组件。国庆最后一天，撸了这个 https://packagist.org/packages/suframe/formsuframe formsuframe 创建vue表单，基于https://github.com/xaboy/form-create再次封装，将表单字段封装到类，通过类自动生成表单。 后期会基于tp6控制台，通过数据库表字段自动生成类文件，加速开发，一行命令生成表单。由于原组件form-create有些小bug，导致提交的返回报错，iview cdn地址丢失等等问题已经反馈给开发者了，开发者正在修复中。预览环境需求PHP >= 7.2支持iViewUI 2.13.0+iViewUI 3.xElementUI 2.8.2+主要功能内置17种常用的表单组件支持表单验证支持生成任何 Vue 组件支持栅格布局可以配合 form-create 生成更复杂的表单内置组件hiddeninputinputNumbercheckboxradioswitchselectautoCompletecascadercolorPickerdatePickertimePickerrateslideruploadtreeframe快速测试git clone https://github.com/suframe/form cd form/demo composer install php -S 0.0.0.0:9000 index.php访问http://127.0.0.1:9000 即可安装composer require suframe/form使用$form = new \suframe\form\Form(); $form->createElm(); $form->setRuleByClass(Fields::class); echo $form->view();Fields类class Fields { public function title() { return [ 'type' => 'input', 'title' => '名称', 'field' => 'title', 'col' => ['span' => 12], 'props' => [ 'placeholder' => '请输入名称', 'disabled' => true, ], 'validate' => [ ['required' => true] ], 'callback' => function($element){ $element->value(99999); return $element; } ]; } public function enable() { return [ 'type' => 'radio', 'title' => '有效', 'field' => 'enable', 'col' => ['span' => 12], 'props' => [], 'validate' => [], 'options' => [ ['value' => "0", 'label' => "不包邮", 'disabled' => false], ['value' => "1", 'label' => "包邮", 'disabled' => true], ], ]; } public function open() { return [ 'type' => 'switch', 'title' => '是否上架', 'field' => 'open', 'props' => [ 'activeValue' => "1", 'inactiveValue' => "0", ], ]; } public function cascader() { return [ 'type' => 'switch', 'col' => ['span' => 12], 'title' => '所在区域', 'field' => 'cascader', ]; } public function date() { return [ 'type' => 'DatePicker', 'title' => '所在区域', 'field' => 'date', 'props' => [ 'type' => "datetimerange", 'format' => "yyyy-MM-dd HH:mm:ss", 'placeholder' => '请选择活动日期', ], ]; } }文档主要文档参考form-create的文档，简体中文命名规范遵循PSR-2命名规范和PSR-4自动加载规范。参与开发QQ群：904592189All rights reserved。
在完成基础对服务注册发现等功能后，如果要写业务，还是需要一套比较好用对后端框架作为支撑。 选了一大圈没找到满意的，准备自己写，发现找组件，组合这些组件也是很大的工程，而且代码质量不能保证。综合一下，就选了使用人数较多，门槛较低对thinkphp6, 由于tp6正式版还没有出来，所以在开发版上进行集成。等tp6正式版发布，我也发布个summer正式版，哈哈哈，tp也有轻量级对微服务化架构支撑了。整合需求无侵入低配置整合方案基于think-swoole开发suframe/think进行集成，包地址：https://packagist.org/packages/suframe/think大致开发思路：新增thinkphp对services，用于增加console命令初始化配置文件启动tcp服务，自动注册增加rpc接口同步测试接下来完整的走下开发流程1. 安装summer代理网关composer create-project suframe/summer-proxy=@dev cd summer-proxy php app/summer tcp:start2. 安装tp6composer create-project topthink/think=6.0.x-dev tp cp .example.env .env修改.env 内容：APP_DEBUG = true，打开调试模式3. 修改composer.json（重要）这步很重要，因为suframe-think还在开发版，没有发布正式版，只能先安装dev版增加到底部如下{ "minimum-stability": "dev", "prefer-stable": true }4. 安装suframe-thinkcomposer require topthink/think-swoole composer require suframe/think5. 增加测试文件创建app/rpc目录，新增HelloRpc.php,内容如下：<?php namespace app\rpc; class HelloRpc { /** * hello 测试 * @param null $name * @return string */ public function run($name = null){ return 'hello ' . $name; } }6. 开始测试启动rpc服务php think swooleTcp同步rpc接口新窗口打开命令行php think swooleTcp sync此时config目录下会有个.phpstorm.meta.php，这个就是用于rpc提示对文件，当然这个是用于phpstorm编辑器增加测试action打开app/controller/Index.php增加action， public function rpc($name = 'ThinkPHP6') { $rs = [ \suframe\core\components\rpc\SRpc::route('/demo/HelloRpc')->run(1111), (new \app\rpc\HelloRpc())->run(2222) ]; return \think\response\Json::create($rs); }这里用绝对路径而不是use是因为好多朋友直接用记事本编辑，没有自动引入usesuframecorecomponentsrpcSRpc::route(' 这句代码的时候，输入/ 会提示出所有对rpc接口，就是前面sync的时候创建对启动tp6php think php然后访问：http://127.0.0.1:8000/index/rpc总结来看看我们启动了些什么服务suframe/proxy 代理网关和服务注册发现 Asuframe/think 基于tp6的rpc服务 Bthink run tp6的服务启动 C浏览器访问的流程: 浏览器 => c 控制器 => rcp调用 c的rpc接口 当然你可以重新起一个，修改swooleTcp里面对端口和注册的path即可到此summer已经集成到tp6了，至于统一日志和统一配置后面来慢慢处理，这个涉及到tp的一些流程监控，属于定制。一起high起来~~~
由于swoole是常驻内存，就带来个问题，修改了代码，除非重启服务，否则是不会生效的，开发中会很不方便。网上搜索了下些解决方案， 最终选择了inotify扩展的方案inotify官方文档：https://www.php.net/manual/en/book.inotify.php安装：pecl install inotify 为了扩展方便，我把他作为了event扩展 private function inotify(EventInterface $e){ $isWatch = Config::getInstance()->get('tcp.server.watch'); if(!$isWatch){ return false; } $watches = Config::getInstance()->get('watch'); if(!$watches){ return false; } $server = $e->getParam('server'); $notify = inotify_init(); foreach ($watches as $watch) { if(!file_exists($watch)){ continue; } inotify_add_watch($notify, $watch, IN_CREATE | IN_DELETE | IN_MODIFY); } swoole_event_add($notify, function () use ($notify, $server){ inotify_read($notify); if(!empty($server)){ $server->reload(); } }); echo "watching files\n"; }通过命令行参数 -w 触发，php user/summer tcp:start -w这样我们就可以修改api或者rpc文件即时生效 目前内置3个目录apirpcbeans需要监听的，可以在app/config目录下watch.php文件中新增
经过1个半月的开发，summer终于第一个预览版本雏形初现，一个月来，反反复复的修改过很多个版本，也完成了很多次重构和代码删减，保持最简功能。今天完成了包的拆分，目前大致结构如下：总体架构代码结构框架基础包应用功能和特点功能：特点：测试后续开发总体架构代码结构框架基础包核心拆分成了3个包：suframe/core 核心代码和组件库suframe/proxy 服务注册代理中心基础库suframe/service 服务基础库应用应用还是按之前的拆分为:suframe/summer 用于创建服务suframe/summer-proxy 用于创建服务注册代理中心库应用和基础包不同 基础包包含基础代码，用于composer包管理，例如：composer install suframe/core。而应用用于创建项目，利润：composer create-project suframe/summer-proxy=@dev composer create-project suframe/summer=@dev [你的应用名]由于还没发布正式版本，会经常更新，所有库只用的dev-master,方便开发，所以创建项目需要用“=@dev”功能和特点此次预览版实现了如下功能：API接口代理转发服务自动注册服务自动通知更新服务状态检测，自动剔除无效服务服务直接rpc通信特点：不依赖第三方应用的简易服务注册中心通过命令可更新本地.phpstorm.meta.php文件，实现无侵入rpc调用和代码提示(phpstrom开发工具)测试说了这么多，直接上手测试下测试环境：Ubuntu 18.04LTS(win10子系统)， php7.2+, composer, swoole扩展设置阿里composer镜像(已设置可跳过)composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/创建summer-proxy代理服务composer create-project suframe/summer-proxy=@dev cd summer-proxy php app/summer tcp:start //或者后台运行 php app/summer tcp:start -d创建后端服务非后台运行的模式下，需要新开命令行窗口composer create-project suframe/summer=@dev demo cd demo php app/summer tcp:start demo可以修改为你自己的服务名称注册的api根路径在 app/config/app.php 中修改服务的端口和ip在 app/config/tcp.php 中修改ok, 访问：http://127.0.0.1:8080/demo/demo/search恭喜你，测试成功！rpc调用。非-d模式下，新建窗口1.按上个步骤，再次创建个服务，命名为user, 修改config/app.php path为/user, config/tcp.php的端口为8082，然后启动服务然后下面操作进入demo服务目录2.同步rpc接口//demo目录 php app/summer rpc:sync3.修改api/demo/Search代码为远程调用<?php namespace app\api\demo; class Search{ public function run(){ return SRpc::route('/user/Demo')->getList('summer'); } }由于目前没有做热更新，所以重启下服务php app/summer tcp:restart //非-d模式直接ctrl+c终止服务重新start即可然后再次访问ok, 访问：http://127.0.0.1:8080/demo/demo/search。 所以rpc服务的个开发流程就很简单了，在app/rpc下开发服务，其他端运行下sync即可用SRpc::rout('')进行调用后续开发后端服务的热更新，计划用php的inotify和swoole的event完成开发模式下的代码热更新选择或者开发基础库，例如db,cache,log等等。开发基础后端服务，例如user用户,order订单,product商品,store商家，pay支付等等，到时候开发个服务市场，需要什么服务下载下来，运行即可。
阿里composer中国镜像全局配置(推荐)composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/取消配置：composer config -g --unset repos.packagist腾讯composer中国镜像全局配置composer config -g repos.packagist composer https://mirrors.cloud.tencent.com/composer/composer key错误打开地址 ：https://composer.github.io/pubkeys.html执行命令 composer self-update --update-keys
之前本来规划先写服务注册和服务的开发，但是需要依赖代理才能进行访问。 那就先开发接口代理吧前言之前和一个大佬交流的时候，他说项目还得再考虑一下，细化一下，感觉不是很清晰。我认真思考了几天和参考其他项目，整理了下思路。首先还是坚持简单原则，一个复杂庞大的框架和体系，目前一个人很难撸下去。所以组件还是用开源的，只撸业务代码只做2件事，接口代理到后端服务， 后端服务直接可以方便的使用rpc进行内部接口调用。 大致结构如下图至于更复杂的场景和应用市面上已经有足够多的框架和体系可用。代理设计此次版本的代理完成以下功能：接口注册，后端服务可以将对外暴露的api注册到代理中心。代理层可以存储接口。然后根据访问地址进行转发。有新接口注册进来，需要自动重载配置和代理服务。提供接口状态检测机制，接口不可用，自动剔除开发目前的版本设计先支持http代理，所以增加了proxy driver,方便以后扩展其他协议代理。使用swoole的多端口监听，创建2个监听端口，一个用于对外，一个用于后端服务注册apiswoole start后，用swoole timer增加定时器，定时检查api是否可用。后端注册api接口也通过http协议， 主要是为了后面开发可视化界面用，方便管理接口和查看接口状态后端服务全部使用swoole的tcp协议， 代理和后端接口创建长连接, 提供连接池，设置最大链接数量，动态增长和剔除注册服务后，同swoole_process::kill 重载服务，更新代理配置，达到实时注册，实时更新代理本来刚开始设计的时候，代理可以设置多级目录，压测的时候发现很影响效率，所以先改为只代理一级目录，例如 /user、 /orders后续：既然这里整了接口注册，那为何不再把rpc接口一起上报了？然后通知其他服务更新即可？额，好像有道理，先这样做吧，实践出真知。后端服务的rpc调用，经过采访不同的开发者，他们更接受 $rpc->user->getList(参数) 的方式， 先按大众的审美做吧。。示例：启动代理中心启动user和orders服务，分别监听8081和8082端口访问接口看看是否正确如图，user和order通过代理端口8080可以访问了，老铁双击6666吧， 你还可以直接停止user和orders服务，看看接口是否剔除，然后再启动，看是否正常重新注册。 ab一波：
服务注册中心开发花了1周左右，期间改了几个版本，优化重构了下core代码。大致能完成之前设计的功能，当然还有很多不足和值得优化的地方，不过先完成大致框架和功能，等整个流程跑顺了，再来优化细节。注册中心提供了服务注册，通知更新，服务列表查询，那么一个服务要想调用其他服务接口或被人家调用，就需要完成相应的功能。功能需求把自己注册到服务中心接受更改通知拉取服务列表更新本地。开发友好，拉取编辑器提示文件(待实践)[...]