内容简介:swoolefy是基于swoole实现的轻量级高性能框架,框架支持http,websocket,udp服务器,以及基于tcp实现可扩展的rpc服务,同时支持composer包方式安装部署项目。基于实用,swoolefy抽象Event事件处理类,实现与底层...
swoolefy是基于swoole实现的轻量级高性能框架,框架支持http,websocket,udp服务器,以及基于tcp实现可扩展的rpc服务,同时支持composer包方式安装部署项目。基于实用,swoolefy抽象Event事件处理类,实现与底层的回调的解耦,支持同步|异步调用,内置view、log、session、 mysql 、 redis 、 memcached 、 mongodb 等常用组件等。
swoolefy经过多个版本的迭代和实践,以及优化,性能稳定,目前已经至1.0.6版本。
1.0.6版本主要的更新:
添加RpcClientManager管理器,可以方便的注册client服务实例,支持单sock连接(或者多socket连接)阻塞调用,单sock连接(或者多sock连接)并行调用,同时RpcClientManager可以在apache|php-fpm中使用。
RPC的服务端和RPC的客户端支持多种方式获取整包数据,包头,包体。
RPC配置服务化,简单配置服务即可快速搭建一个RPC的服务器和对应的RPC的服务端。
组件实例化支持配置闭包回调函数。
添加了进程池PoolsManager管理器,方便创建swoole_process
github:https://github.com/bingcool/swoolefy
文档:https://www.kancloud.cn/bingcoolhuang/php-swoole-swoolefy/587501
下面是一个rpc的demo:
RPC的服务端:
1、设置协议层配置文件protocol/rpc/config.php,添加packet设置:
'packet'=>[ // 服务端使用长度检查packet时,设置包头结构体,如果使用eof时,不需要设置,底层会读取package_eof 'server'=>[ 'pack_header_struct' => ['length'=>'N', 'version'=>'a10', 'name'=>'a30', 'request_id'=>'a12'], 'pack_length_key' => 'length', 'serialize_type' => 'json' ], //客户端解包设置 'client' => [ 'pack_check_type' => 'length', 'pack_header_struct' => ['length'=>'N', 'version'=>'a10', 'name'=>'a30', 'request_id'=>'a12'], 'pack_length_key' => 'length', 'serialize_type' => 'json' ] ],
2、服务端的控制器中
<?php namespace Service\Coms\Book; use Swoolefy\Core\Swfy; use Swoolefy\Core\SController; use Swoolefy\Core\Application; use Swoolefy\Core\Task\TaskManager; class BookmanageService extends SController { public function test($params) { // 客户端发送过来的数据 var_dump($params); $data = $params; //客户端的头部与服务端头部相同,当然可以根据返回数据不同,返回包头可以不同。 $header = ['length'=>'', 'version'=>'1.0.1', 'name'=>'bingcool', 'request_id'=>$this->getRpcPackHeader()['request_id']]; // 返回数据给客户端 $this->send($this->fd, $data, $header); }
至此,很很简单的服务端就ok了,其实就是设置一下packet就可以了。
RPC的客户端:
client端是基于swoole_client实现的,所以环境中必须安装swoole和swoole_serialize扩展。这个客户端其实是可以用在Apache|php-fpm的环境中,并且支持并行调用。
1、在/protocol/rpc/RpcServer.php的onWorkerStart中注册client的访问的服务,或者在start_init配置项中的类的onWorkerStart函数中注册服务,因为该类必须继承于Swoolefy\Core\StartInit的。
/** * onWorkerStart * @param $server * @return */ public function onWorkerStart($server, $worker_id) { if(Swfy::isWorkerProcess()) { $productServiceConfig = [ 'servers' => '127.0.0.1:9504', 'timeout' => 0.5, 'noblock' => 0 ]; $orderServiceConfig = array( 'servers' => '127.0.0.1:9506', 'timeout' => 0.5, 'noblock' => 0 ); //客户端pack长度检查设置 $setting = array( 'open_length_check' => 1, 'package_length_type' => 'N', 'package_length_offset' => 0, //第N个字节是包长度的值 'package_body_offset' => 56, //第几个字节开始计算长度 'package_max_length' => 2000000, //协议最大长度 ); // 包头结构体设置,默认客户端与服务端包头结构体相同 $header_struct = array( 'length'=>'N', 'version'=>'a10', 'name'=>'a30', 'request_id'=>'a12' ); // 注册product服务 RpcClientManager::getInstance(true)->registerService('productService', productServiceConfig, $setting, $header_struct,[ // swoole_client 长连接 'swoole_keep' => false ]); // 注册order服务 RpcClientManager::getInstance(true)->registerService('orderService', $orderServiceConfig, $setting, $header_struct,[ // swoole_client 长连接 'swoole_keep' => true ]); } }
2、在controller或者model中可以直接调用向服务端发送数据
a、阻塞调用,请求/应答模式
public function test() { $callable = 'Service\Coms\Book\BookmanageService::test'; $params = ['content'=>'我是rpc的客户端,我向你发送消息']; $header = ['length'=>'', 'version'=>'1.0.0', 'name'=>'bingcool']; //调用发送数据 $client1 = RpcClientManager::getInstance()->getServices('productService')->buildHeaderRequestId($header)->waitCall($callable, $params); //阻塞等待数据返回 $res1 = $client1->waitRecv(); var_dump($res1); }
上面将返回一个数据,数组里有两个元素,arr[0]是包头,arr[1]是包体数据,例如:
array(2) { [0] => array(4) { ["length"] => int(83) ["version"] => string(10) "1.0.0" ["name"] => string(30) "bingcool" ["request_id"] => string(12) "d189dfd5b997" } [1] => array(4) { ["content"] => array(1) { ["content"] => string(16) "我是rpc的服务端,我已收到你发送的消息" } }
b、并行调用,然后在时间内等待接收所有数据,再进行数据聚合
// productService 调用 $callable = 'Service\Coms\Book\BookmanageService::test'; $params = ['content'=>'hhhhhhhhhhhhhhhh']; $header = ['length'=>'', 'version'=>'1.0.1', 'name'=>'bingcool']; $client2 = RpcClientManager::getInstance()->getServices('productService')->buildHeaderRequestId($header)->waitCall($callable, $params); // orderService 调用 $callable = 'Service\Coms\Book\BookmanageService::test'; $params = ['content'=>'hhhhhhhhhhhhhhhh']; $header = ['length'=>'', 'version'=>'1.0.1', 'name'=>'bingcool']; $client3 = RpcClientManager::getInstance()->getServices('orderService')->buildHeaderRequestId($header)->waitCall($callable, $params); // productService 调用 $callable = 'Service\Coms\Book\BookmanageService::test'; $params = ['content'=>'hhhhhhhhhhhhhhhh']; $header = ['length'=>'', 'version'=>'1.0.1', 'name'=>'bingcool']; $client4 = RpcClientManager::getInstance()->getServices('productService')->buildHeaderRequestId($header)->waitCall($callable, $params); // productService 调用 $callable = 'Service\Coms\Book\BookmanageService::test'; $params = ['content'=>'hhhhhhhhhhhhhhhh']; $header = ['length'=>'', 'version'=>'1.0.1', 'name'=>'bingcool']; $client5 = RpcClientManager::getInstance()->getServices('productService')->buildHeaderRequestId($header)->waitCall($callable, $params); // 并行等待数据返回,这里返回的是所有调用的数据,例如上面调用4次,那么将返回给数组$res中4个整包元素 $res = RpcClientManager::getInstance()->multiRecv(); var_dump($res); ~~~ 那么如何获取其中某一个的客户端的数据呢,很简单 ~~~ // 获取整包数据,包括包头和包体 $pack_data = $client2->getResponsePackData(); // 分离包头包体 list($pack_header, $pack_body) = $pack_data; // 直接获取包头 $pack_header = $client2->getResponsePackHeader(); 或者 $pack_header = $pack_data[0]; // 直接获取包头 $pack_body = $client2->getResponsePackBody(); 或者 $pack_body = $pack_data[1];
这是一个简单的说明,具体可以参考文档。
【声明】文章转载自:开源中国社区 [http://www.oschina.net]
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Django企业开发实战
胡阳 / 人民邮电出版社 / 2019-2 / 99.00元
本书以博客系统贯穿始末,介绍了Django的方方面面。书中共分四部分,第一部分介绍了正式进入编码之前的准备工作,内容包括需求分析、基础知识和Demo系统的开发;第二部分开始实现需求,内容涉及环境配置、编码规范以及项目结构规划,编写了Model层、admin页面、Form代码和View逻辑,引入了Bootstrap框架;第三部分重点介绍xadmin、django-autocomple-light和d......一起来看看 《Django企业开发实战》 这本书的介绍吧!