From 755deaaea5156656b17483c0d47c9de7f4245b67 Mon Sep 17 00:00:00 2001 From: lorik <497824490@qq.com> Date: Wed, 8 Sep 2021 10:55:08 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20Rpc=E6=9C=8D=E5=8A=A1=E5=99=A8=E9=9B=86?= =?UTF-8?q?=E6=88=90=E5=88=B0yii2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bin/server | 27 ---- cert/private_key.pem | 15 --- cert/pub_key.pem | 6 - composer.json | 5 +- composer.lock | 118 ------------------ examples/client.php | 55 -------- examples/coroutine.php | 46 ------- examples/index.php | 8 -- examples/jwt.php | 41 ------ examples/rsa_test.php | 52 -------- examples/server.php | 21 ---- examples/test.php | 50 -------- src/Client.php | 83 ++++++++++++ src/Controller.php | 13 ++ src/RpcServer.php | 84 +++++++------ src/Serializer.php | 87 +++++++++++++ src/Yee.php | 23 ---- src/exception/BadRequestRpcException.php | 10 ++ src/exception/ErrorRpcException.php | 10 ++ src/exception/ForbiddenRpcException.php | 10 ++ .../MethodNotAllowedRpcException.php | 10 ++ src/exception/NotFoundRpcException.php | 10 ++ src/exception/RpcException.php | 10 ++ src/exception/UnauthorizedRpcException.php | 10 ++ systemd/airpc.service | 14 --- 25 files changed, 300 insertions(+), 518 deletions(-) delete mode 100755 bin/server delete mode 100644 cert/private_key.pem delete mode 100644 cert/pub_key.pem delete mode 100644 composer.lock delete mode 100644 examples/client.php delete mode 100755 examples/coroutine.php delete mode 100644 examples/index.php delete mode 100644 examples/jwt.php delete mode 100644 examples/rsa_test.php delete mode 100644 examples/server.php delete mode 100644 examples/test.php create mode 100644 src/Client.php create mode 100644 src/Controller.php create mode 100644 src/Serializer.php delete mode 100644 src/Yee.php create mode 100644 src/exception/BadRequestRpcException.php create mode 100644 src/exception/ErrorRpcException.php create mode 100644 src/exception/ForbiddenRpcException.php create mode 100644 src/exception/MethodNotAllowedRpcException.php create mode 100644 src/exception/NotFoundRpcException.php create mode 100644 src/exception/RpcException.php create mode 100644 src/exception/UnauthorizedRpcException.php delete mode 100644 systemd/airpc.service diff --git a/bin/server b/bin/server deleted file mode 100755 index d6c8ff4..0000000 --- a/bin/server +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env php -reactorNum = 1; -$server->workerNum = 1; -$server->entryPoint = $argv[1]; -$server->run(); -?> \ No newline at end of file diff --git a/cert/private_key.pem b/cert/private_key.pem deleted file mode 100644 index 61af3eb..0000000 --- a/cert/private_key.pem +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXgIBAAKBgQDsldu7vayXD7RE5HEMsvlz/tkq36gBgY1Yz+R9dkZWNDdQTTFm -O2tWFwBvYRx5Nv/CtR1Nl2+pb/Nd6WrWzs9FR7P84nixA+vfzQjqTIlQViO0vB/a -gWa2nk5N4e0dsQ7kDr3+7/w1DeFsMlRBDvSHMsdmlNSFDFB6+MVrC93dRQIDAQAB -AoGBALhxeJZcIDLA7oSLKEuDOJEjDQGszhkmfCDSKstZKyrHmJwFIk8WYe8DDbbH -meAybaDJfGfieQ46lhwP/tgq8VEM7m/bhkhksXHTuKmPGfr53uev9Rp1+TKG1vFW -2c8MFMrDg3ZNy8lAfZmhIWUP9ietU5o836d0/3vJ+nBeSZwhAkEA+0luT5ijhfh4 -Jim81h0yKJFOeg/gjdHtefAWyruAGHZEKz+yLNTPJN0bjPtQAOqSr/Hjt9MmxzPa -HJ0DuvvgbQJBAPEF1mYmqmpBZTDc2zjOTXzVRsNO/bBcx/q9GkQydn/7BV6Dqr9Y -cgJV49CWcbZBHLkCxyidKDvZBzTh0b/vWTkCQH3AsLianXLk9lO63WqVb82Hcit5 -mJnAbcRxFybbkG4teU3fcW4oDYXYNPpnphDfUwtD1P7gZ26XD1b0aLKBbD0CQQC3 -sCY9Rfyc7GgNfFTLD1e46uZ6VUo8zglPDC3niboMQahO5vQLzoFdTE5Km03gg/E7 -A2X7iwKt0fKPGAd+SxDpAkEA6OG77IL8cjrlZKk4ilTCz8rkF4CtZWbDLi1IF40i -jaGlSLvVowHDywtjT8tYfpIH7HI55KS3gj88qAaF38qfRA== ------END RSA PRIVATE KEY----- diff --git a/cert/pub_key.pem b/cert/pub_key.pem deleted file mode 100644 index 1da52e8..0000000 --- a/cert/pub_key.pem +++ /dev/null @@ -1,6 +0,0 @@ ------BEGIN PUBLIC KEY----- -MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDsldu7vayXD7RE5HEMsvlz/tkq -36gBgY1Yz+R9dkZWNDdQTTFmO2tWFwBvYRx5Nv/CtR1Nl2+pb/Nd6WrWzs9FR7P8 -4nixA+vfzQjqTIlQViO0vB/agWa2nk5N4e0dsQ7kDr3+7/w1DeFsMlRBDvSHMsdm -lNSFDFB6+MVrC93dRQIDAQAB ------END PUBLIC KEY----- diff --git a/composer.json b/composer.json index d3e5ebe..3278dae 100644 --- a/composer.json +++ b/composer.json @@ -9,11 +9,10 @@ "email": "klm777x7@gmail.com" } ], - "minimum-stability": "dev", "require": { - "swoole/ide-helper": "dev-master", - "firebase/php-jwt": "dev-master" + "yiisoft/yii2": "2.0.40" }, + "minimum-stability": "dev", "autoload": { "psr-4": { "blobt\\airpc\\": "src" diff --git a/composer.lock b/composer.lock deleted file mode 100644 index f5d9aaa..0000000 --- a/composer.lock +++ /dev/null @@ -1,118 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", - "This file is @generated automatically" - ], - "content-hash": "be484b9b2956b9cbaf4eac46f8dd344a", - "packages": [ - { - "name": "firebase/php-jwt", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/firebase/php-jwt.git", - "reference": "feb0e820b8436873675fd3aca04f3728eb2185cb" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/firebase/php-jwt/zipball/feb0e820b8436873675fd3aca04f3728eb2185cb", - "reference": "feb0e820b8436873675fd3aca04f3728eb2185cb", - "shasum": "", - "mirrors": [ - { - "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", - "preferred": true - } - ] - }, - "require": { - "php": ">=5.3.0" - }, - "require-dev": { - "phpunit/phpunit": ">=4.8 <=9" - }, - "type": "library", - "autoload": { - "psr-4": { - "Firebase\\JWT\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Neuman Vong", - "email": "neuman+pear@twilio.com", - "role": "Developer" - }, - { - "name": "Anant Narayanan", - "email": "anant@php.net", - "role": "Developer" - } - ], - "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", - "homepage": "https://github.com/firebase/php-jwt", - "keywords": [ - "jwt", - "php" - ], - "time": "2020-03-25T18:49:23+00:00" - }, - { - "name": "swoole/ide-helper", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/swoole/ide-helper.git", - "reference": "9082983c671cd79f461fcb9e52687dccca993e9b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/swoole/ide-helper/zipball/9082983c671cd79f461fcb9e52687dccca993e9b", - "reference": "9082983c671cd79f461fcb9e52687dccca993e9b", - "shasum": "", - "mirrors": [ - { - "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", - "preferred": true - } - ] - }, - "require-dev": { - "guzzlehttp/guzzle": "~6.5.0", - "laminas/laminas-code": "~3.4.0", - "squizlabs/php_codesniffer": "~3.5.0", - "symfony/filesystem": "~4.0" - }, - "type": "library", - "notification-url": "https://packagist.org/downloads/", - "license": [ - "Apache-2.0" - ], - "authors": [ - { - "name": "Team Swoole", - "email": "team@swoole.com" - } - ], - "description": "IDE help files for Swoole.", - "time": "2020-08-05T18:18:55+00:00" - } - ], - "packages-dev": [], - "aliases": [], - "minimum-stability": "dev", - "stability-flags": { - "swoole/ide-helper": 20, - "firebase/php-jwt": 20 - }, - "prefer-stable": false, - "prefer-lowest": false, - "platform": [], - "platform-dev": [], - "plugin-api-version": "1.1.0" -} diff --git a/examples/client.php b/examples/client.php deleted file mode 100644 index 9dc14d9..0000000 --- a/examples/client.php +++ /dev/null @@ -1,55 +0,0 @@ -set(array( - 'open_length_check' => true, - 'package_max_length' => 1024 * 1024 * 20, - 'package_length_type' => 'N', - 'package_length_offset' => 9, - 'package_body_offset' => 13 - )); - - if (!$client->connect($host, $port, 0.5)) { - return false; - } - - $client->send($pack); - $pack = @$client->recv(); - $client->close(); - - if ($pack === false) { - //echo $client->errCode . "\n"; - //TODO 获取错误码并进行处理 - return false; - } else if (empty($pack)) { - echo "close by peer\n"; - return false; - } - - $ret = unpack('Ctype/Ntime/Nserid/Nlength/a*data', $pack); - - return $ret['data']; -} - -//$data = '{"controller":"site","methor":"test","params":{"id":1}}'; -$data = file_get_contents("/mnt/hgfs/wdev/data.txt"); -$ret = remoteCall("127.0.0.1", "5188", $data); - -//'{"controller":"site","methor":"test","params":{"id":"111"}} -//'{"controller":"site","methor":"test","params":{"id":1,"status":0}}' -echo "{$ret}\n"; - -?> \ No newline at end of file diff --git a/examples/coroutine.php b/examples/coroutine.php deleted file mode 100755 index e38f4a1..0000000 --- a/examples/coroutine.php +++ /dev/null @@ -1,46 +0,0 @@ -set(array( - 'open_length_check' => true, - 'package_max_length' => 81920, - 'package_length_type' => 'N', - 'package_length_offset' => 9, - 'package_body_offset' => 13, - 'connect_timeout' => 1.0, - 'write_timeout' => 60.0, - 'read_timeout' => 60.0 - )); - - if (!$client->connect($host, $port)) { - echo "connect failed.\n"; - return false; - } - - - @$client->send($pack); - $pack = @$client->recv(); - if ($pack === false) { - echo $client->errCode . "\n"; - return false; - } else if (empty($pack)) { - echo "close by peer.\n"; - return false; - } - - $ret = unpack('Ctype/Ntime/Nserid/Nlength/a*data', $pack); - $client->close(); - return $ret['data']; -}); - - -print_r($ret); \ No newline at end of file diff --git a/examples/index.php b/examples/index.php deleted file mode 100644 index ce06521..0000000 --- a/examples/index.php +++ /dev/null @@ -1,8 +0,0 @@ -run(); diff --git a/examples/jwt.php b/examples/jwt.php deleted file mode 100644 index 64ca2cd..0000000 --- a/examples/jwt.php +++ /dev/null @@ -1,41 +0,0 @@ - "http://example.org", - "aud" => "http://example.com", - "iat" => 1356999524, - "nbf" => 1357000000 -); - -/** - * IMPORTANT: - * You must specify supported algorithms for your application. See - * https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40 - * for a list of spec-compliant algorithms. - */ -echo $jwt = JWT::encode($payload, $key); -$decoded = JWT::decode($jwt, $key, array('HS256')); - -print_r($decoded); - -/* - NOTE: This will now be an object instead of an associative array. To get - an associative array, you will need to cast it as such: -*/ - -$decoded_array = (array) $decoded; - -/** - * You can add a leeway to account for when there is a clock skew times between - * the signing and verifying servers. It is recommended that this leeway should - * not be bigger than a few minutes. - * - * Source: http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html#nbfDef - */ -JWT::$leeway = 60; // $leeway in seconds -$decoded = JWT::decode($jwt, $key, array('HS256')); - -?> \ No newline at end of file diff --git a/examples/rsa_test.php b/examples/rsa_test.php deleted file mode 100644 index c74a20d..0000000 --- a/examples/rsa_test.php +++ /dev/null @@ -1,52 +0,0 @@ - "deeplove.cn", - "name" => "nemo", - "age" => 29, - -]; - -$jwt = JWT::encode($payload, $privateKey, 'RS256'); -echo strlen($jwt) . "\n"; -echo "Encode:\n" . print_r($jwt, true) . "\n"; - -$decoded = JWT::decode($jwt, $publicKey, array('RS256')); - -$decoded_array = (array) $decoded; -echo "Decode:\n" . print_r($decoded_array, true) . "\n"; diff --git a/examples/server.php b/examples/server.php deleted file mode 100644 index 6bc4a48..0000000 --- a/examples/server.php +++ /dev/null @@ -1,21 +0,0 @@ -reactorNum = 2; -$server->workerNum = 6; -$server->daemonize = false; -$server->entryPoint = '/home/blobt/Documents/dev/php/yii2-app-rpc/rpc/index.php'; -$server->run(); -?> \ No newline at end of file diff --git a/examples/test.php b/examples/test.php deleted file mode 100644 index 8055e3c..0000000 --- a/examples/test.php +++ /dev/null @@ -1,50 +0,0 @@ - 23, - 'name' => 'nemo' -]; - - - -//$encode = JWT::encode($data, $privateKey, 'RS256'); -$encode = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eeyJpZCI6MjMsIm5hbWUiOiJuZW1vIn0.xJt8NHFJeQyiWSmAI1C_t2lX99QHChXpR7iNkTQ5oi7_87NPo_S4gbC2zh40SOmv9uk3EoRvsrzzRbtPSeh7D5oCbSVXcqvVwMq0zwYBgW6vyL5DMkuDGyQQpyVGuywy8xY9N9bwUtiL7tVj_S22L1jaYOw7SZtGU4eDa5vU_DM"; -echo "encode: " . $encode . "\n"; - - -$decoded = (array) JWT::decode($encode, $publicKey, array('RS256')); - -print_r($decoded); -?> \ No newline at end of file diff --git a/src/Client.php b/src/Client.php new file mode 100644 index 0000000..a1c09bc --- /dev/null +++ b/src/Client.php @@ -0,0 +1,83 @@ + $controller, + 'method' => $method, + 'params' => $params + ]; + $data = json_encode($data); + $length = strlen($data); + $pack = pack('CNNNa*', 1, time(), 0, $length, $data); + + //TPC调用 + $client = new \Swoole\Client(SWOOLE_SOCK_TCP); + $client->set(array( + 'open_length_check' => true, + 'package_max_length' => 20971520, + 'package_length_type' => 'N', + 'package_length_offset' => 9, + 'package_body_offset' => 13 + )); + if (!$client->connect($serviceData['host'],$serviceData['port'], 10)) + throw new ErrorRpcException('swoole connect failed', 88500002); + $client->send($pack); + $pack = @$client->recv(); + $client->close(); + + //解析数据 + if ($pack === false) { + throw new ErrorRpcException('client recv false , error code : '.$client->errCode, 88500003); + } else if (empty($pack)) + throw new ErrorRpcException('close by peer', 88500004); + $ret = unpack('Ctype/Ntime/Nserid/Nlength/a*data', $pack); + $decodeData = json_decode($ret['data'],true); + if( $decodeData == false ) + throw new ErrorRpcException('remote call result json decode failed', 88500005); + + return $decodeData; + }catch(\Throwable $e){ + return ['statusCode'=>500,'errorCode'=>$e->getCode(),'msg'=>$e->getMessage()]; + } + } + + /** + * 获取微服务节点数据 + * @param $service + * @return array + * @throws ErrorRpcException + */ + private static function serviceData($service): array + { + if( isset(Yii::$app->params['services']) ){ + $servicesList = Yii::$app->params['services']; + if( isset($servicesList[$service]) && !empty($servicesList[$service]) ){ + $randomKey = array_rand($servicesList[$service],1); //随机取一个节点 + return $servicesList[$service][$randomKey]; + }else{ + throw new ErrorRpcException('services information not found', 88500006); + } + }else{ + throw new ErrorRpcException('services information not found', 88500006); + } + } +} \ No newline at end of file diff --git a/src/Controller.php b/src/Controller.php new file mode 100644 index 0000000..ca885d6 --- /dev/null +++ b/src/Controller.php @@ -0,0 +1,13 @@ +serialize($result); + } +} \ No newline at end of file diff --git a/src/RpcServer.php b/src/RpcServer.php index 837e667..d3caddd 100644 --- a/src/RpcServer.php +++ b/src/RpcServer.php @@ -2,44 +2,30 @@ namespace blobt\airpc; +use blobt\airpc\exception\BadRequestRpcException; +use blobt\airpc\exception\NotFoundRpcException; +use blobt\airpc\exception\RpcException; use Swoole; -use blobt\airpc\Pack; +use yii\base\Component; +use Yii; /** * 基于swoole的轻量及 RPC * 服务器 - * */ class RpcServer extends BaseService { - /** - * @var string rpc项目入口文件 - */ - public $entryPoint = false; + const EVENT_RPC_ON_CLOSE = 'rpcClose'; /** * 初始化 */ public function init() { - if (empty($this->entryPoint)) { - die("Please set the entry point." . PHP_EOL); - } $this->setProtocol(Pack::$packageLengthType, Pack::$packageMaxLength, Pack::$packageLengthOffset, Pack::$packageBodyOffset); } /** - * 发送数据 - * @param integral $fd 链接文件描述付 - * @param string $data - * @return boolean - */ - public function send(int $fd, string $data) { - $pack = new Pack($data); - $this->server->send($fd, (string) $pack); - } - - /** - * + * rpc请求处理 * @param Swoole\Server $server * @param int $fd * @param int $reactorId @@ -47,29 +33,49 @@ class RpcServer extends BaseService { */ public function onReceive(Swoole\Server $server, int $fd, int $reactorId, string $pack) { $pack = new Pack($pack); - $data = $pack->data; - $this->handle($fd, $data); + //调用rpc对应的处理函数 + try { + $ret = $this->handle($pack->data); + $ret = json_encode(['statusCode'=>200,'data'=>$ret]); + }catch (\Throwable $e){ + if( $e instanceof RpcException ){ + $ret = json_encode(['statusCode'=>$e->statusCode,'errorCode'=>$e->getCode(),'msg'=>$e->getMessage()]); + }else{ + $ret = json_encode(['statusCode'=>500,'errorCode'=>$e->getCode(),'msg'=>$e->getMessage()]); + Yii::error($e); + } + } + //返回结果 + $pack = new Pack($ret); + $this->server->send($fd, (string) $pack); } /** * 请求处理函数 - * @param int $fd - * @param string $pack + * @param string $data + * @return mixed + * @throws BadRequestRpcException + * @throws NotFoundRpcException */ - public function handle(int $fd, string $data) { - $_SERVER['data'] = $data; - try { - $ret = include $this->entryPoint; - $this->send($fd, $ret); - } catch (\Error $e) { - //TODO 记录日志 - echo "YeeError: ".$e->getMessage(); - $this->send($fd, "YeeError"); - } catch (\Exception $e) { - //TODO 记录日志 - echo "YeeException: ".$e->getMessage(); - $this->send($fd, "YeeException"); - } + private function handle(string $data) { + $data = json_decode($data,true); + if( is_array($data) && isset($data['controller']) && isset($data['method']) ){ + $className = 'rpc\\controllers\\'.ucfirst($data['controller']).'Controller'; + if( class_exists($className) && method_exists($className,'action'.ucfirst($data['method'])) ) { + $obj = new $className($data['controller'],Yii::$app); + return $obj->runAction($data['method'],$data['data']); + }else + throw new NotFoundRpcException('the rpc handler undefined or can not callout the method'); + }else + throw new BadRequestRpcException('bad rpc request data'); } + /** + * @param Swoole\Server $server + * @param int $fd + * @param int $reactorId + */ + public function onClose(Swoole\Server $server, int $fd, int $reactorId) { + Yii::$app->trigger(self::EVENT_RPC_ON_CLOSE); + } } diff --git a/src/Serializer.php b/src/Serializer.php new file mode 100644 index 0000000..ad000db --- /dev/null +++ b/src/Serializer.php @@ -0,0 +1,87 @@ +preserveKeys) { + $models = $dataProvider->getModels(); + } else { + $models = array_values($dataProvider->getModels()); + } + $models = $this->serializeModels($models); + + $pagination = $dataProvider->getPagination(); + + //因为tcp传输,所以不用获取分页链接 +// if (($pagination = $dataProvider->getPagination()) !== false) { +// $this->addPaginationHeaders($pagination); +// } + +// if ($this->request->getIsHead()) { +// return null; +// } else + if ($this->collectionEnvelope === null) { + return $models; + } + + $result = [ + $this->collectionEnvelope => $models, + ]; + if ($pagination !== false) { + return array_merge($result, $this->serializePagination($pagination)); + } + + return $result; + } + + /** + * Serializes a pagination into an array. + * @param Pagination $pagination + * @return array the array representation of the pagination + * @see addPaginationHeaders() + */ + protected function serializePagination($pagination) + { + return [ +// $this->linksEnvelope => Link::serialize($pagination->getLinks(true)), + $this->metaEnvelope => [ + 'totalCount' => $pagination->totalCount, + 'pageCount' => $pagination->getPageCount(), + 'currentPage' => $pagination->getPage() + 1, + 'perPage' => $pagination->getPageSize(), + ], + ]; + } + + /** + * Serializes a model object. + * @param Arrayable $model + * @return array the array representation of the model + */ + protected function serializeModel($model) + { +// if ($this->request->getIsHead()) { +// return null; +// } + +// list($fields, $expand) = $this->getRequestedFields(); + $fields = [];$expand=[]; + return $model->toArray($fields, $expand); + } +} \ No newline at end of file diff --git a/src/Yee.php b/src/Yee.php deleted file mode 100644 index 29591e0..0000000 --- a/src/Yee.php +++ /dev/null @@ -1,23 +0,0 @@ -