Browse Source

feat: Rpc服务器集成到yii2

base-server
lorik 3 years ago
parent
commit
755deaaea5
  1. 27
      bin/server
  2. 15
      cert/private_key.pem
  3. 6
      cert/pub_key.pem
  4. 5
      composer.json
  5. 118
      composer.lock
  6. 55
      examples/client.php
  7. 46
      examples/coroutine.php
  8. 8
      examples/index.php
  9. 41
      examples/jwt.php
  10. 52
      examples/rsa_test.php
  11. 21
      examples/server.php
  12. 50
      examples/test.php
  13. 83
      src/Client.php
  14. 13
      src/Controller.php
  15. 84
      src/RpcServer.php
  16. 87
      src/Serializer.php
  17. 23
      src/Yee.php
  18. 10
      src/exception/BadRequestRpcException.php
  19. 10
      src/exception/ErrorRpcException.php
  20. 10
      src/exception/ForbiddenRpcException.php
  21. 10
      src/exception/MethodNotAllowedRpcException.php
  22. 10
      src/exception/NotFoundRpcException.php
  23. 10
      src/exception/RpcException.php
  24. 10
      src/exception/UnauthorizedRpcException.php
  25. 14
      systemd/airpc.service

27
bin/server

@ -1,27 +0,0 @@
#!/usr/bin/env php
<?PHP
/*
* @Descripttion:
* @version:
* @Author: Blobt
* @Date: 2020-07-30 09:48:18
* @LastEditors: Blobt
* @LastEditTime: 2020-07-30 14:20:19
*/
include __DIR__."/../vendor/autoload.php";
use blobt\airpc\RpcServer;
if(!isset($argv[1]))
die("Error: {$argv[0]} {your enter point}.\n");
if(!file_exists($argv[1]))
die("Error: enter point {$argv[1]} not found.\n");
$server = new RpcServer("0.0.0.0", 5188);
$server->reactorNum = 1;
$server->workerNum = 1;
$server->entryPoint = $argv[1];
$server->run();
?>

15
cert/private_key.pem

@ -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-----

6
cert/pub_key.pem

@ -1,6 +0,0 @@
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDsldu7vayXD7RE5HEMsvlz/tkq
36gBgY1Yz+R9dkZWNDdQTTFmO2tWFwBvYRx5Nv/CtR1Nl2+pb/Nd6WrWzs9FR7P8
4nixA+vfzQjqTIlQViO0vB/agWa2nk5N4e0dsQ7kDr3+7/w1DeFsMlRBDvSHMsdm
lNSFDFB6+MVrC93dRQIDAQAB
-----END PUBLIC KEY-----

5
composer.json

@ -9,11 +9,10 @@
"email": "klm777x7@gmail.com" "email": "klm777x7@gmail.com"
} }
], ],
"minimum-stability": "dev",
"require": { "require": {
"swoole/ide-helper": "dev-master",
"firebase/php-jwt": "dev-master"
"yiisoft/yii2": "2.0.40"
}, },
"minimum-stability": "dev",
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"blobt\\airpc\\": "src" "blobt\\airpc\\": "src"

118
composer.lock

@ -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"
}

55
examples/client.php

@ -1,55 +0,0 @@
<?PHP
/**
* {
* unisgned char type;
* unsigned int time;
* unsigned int serid;
* unsigned int length;
* char body[length];
* }
*/
function remoteCall(string $host, $port, string $data) {
$length = strlen($data);
$pack = pack('CNNNa*', 1, time(), 0, $length, $data);
$client = new Swoole\Client(SWOOLE_SOCK_TCP);
$client->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";
?>

46
examples/coroutine.php

@ -1,46 +0,0 @@
<?php
$host = '127.0.0.1';
$port = 5188;
$data = '{"controller":"site","methor":"test","params":{"id":1}}';
$length = strlen($data);
$pack = pack('CNNNa*', 1, time(), 0, $length, $data);
$ret = Swoole\Coroutine::create(function()use($host, $port, $pack) {
$client = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP);
$client->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);

8
examples/index.php

@ -1,8 +0,0 @@
<?php
include __DIR__ . "/../vendor/autoload.php";
use blobt\airpc\Yee;
return Yee::getInstaance()->run();

41
examples/jwt.php

@ -1,41 +0,0 @@
<?php
include __DIR__ . "/../vendor/autoload.php";
use \Firebase\JWT\JWT;
$key = "example_key";
$payload = array(
"iss" => "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'));
?>

52
examples/rsa_test.php

@ -1,52 +0,0 @@
<?php
include __DIR__ . "/../vendor/autoload.php";
use \Firebase\JWT\JWT;
$key = "73937393";
$privateKey = <<<EOD
-----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-----
EOD;
$publicKey = <<<EOD
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDsldu7vayXD7RE5HEMsvlz/tkq
36gBgY1Yz+R9dkZWNDdQTTFmO2tWFwBvYRx5Nv/CtR1Nl2+pb/Nd6WrWzs9FR7P8
4nixA+vfzQjqTIlQViO0vB/agWa2nk5N4e0dsQ7kDr3+7/w1DeFsMlRBDvSHMsdm
lNSFDFB6+MVrC93dRQIDAQAB
-----END PUBLIC KEY-----
EOD;
$payload = [
"iss" => "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";

21
examples/server.php

@ -1,21 +0,0 @@
<?PHP
/*
* @Descripttion:
* @version:
* @Author: sueRimn
* @Date: 2020-07-30 09:48:18
* @LastEditors: sueRimn
* @LastEditTime: 2020-07-30 14:20:19
*/
include __DIR__."/../vendor/autoload.php";
use blobt\airpc\RpcServer;
$server = new RpcServer("0.0.0.0", 5188);
$server->reactorNum = 2;
$server->workerNum = 6;
$server->daemonize = false;
$server->entryPoint = '/home/blobt/Documents/dev/php/yii2-app-rpc/rpc/index.php';
$server->run();
?>

50
examples/test.php

@ -1,50 +0,0 @@
<?php
include __DIR__ . "/../vendor/autoload.php";
use \Firebase\JWT\JWT;
$privateKey = <<<EOD
-----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-----
EOD;
$publicKey = <<<EOD
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDsldu7vayXD7RE5HEMsvlz/tkq
36gBgY1Yz+R9dkZWNDdQTTFmO2tWFwBvYRx5Nv/CtR1Nl2+pb/Nd6WrWzs9FR7P8
4nixA+vfzQjqTIlQViO0vB/agWa2nk5N4e0dsQ7kDr3+7/w1DeFsMlRBDvSHMsdm
lNSFDFB6+MVrC93dRQIDAQAB
-----END PUBLIC KEY-----
EOD;
$data = [
'id' => 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);
?>

83
src/Client.php

@ -0,0 +1,83 @@
<?php
namespace blobt\airpc;
use blobt\airpc\exception\ErrorRpcException;
use Yii;
class Client
{
/**
* 远程调用
* @param $service
* @param $controller
* @param $method
* @param $params
* @return array
*/
public static function remoteCall($service, $controller, $method, $params) : array
{
try{
//找到service对应服务器
$serviceData = self::serviceData($service);
//打包数据
$data = [
'controller' => $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);
}
}
}

13
src/Controller.php

@ -0,0 +1,13 @@
<?php
namespace blobt\airpc;
class Controller extends \yii\base\Controller
{
public function afterAction($action, $result)
{
$result = parent::afterAction($action, $result);
//格式化输出
$serializer = new Serializer();
return $serializer->serialize($result);
}
}

84
src/RpcServer.php

@ -2,44 +2,30 @@
namespace blobt\airpc; namespace blobt\airpc;
use blobt\airpc\exception\BadRequestRpcException;
use blobt\airpc\exception\NotFoundRpcException;
use blobt\airpc\exception\RpcException;
use Swoole; use Swoole;
use blobt\airpc\Pack;
use yii\base\Component;
use Yii;
/** /**
* 基于swoole的轻量及 RPC * 基于swoole的轻量及 RPC
* 服务器 * 服务器
*
*/ */
class RpcServer extends BaseService { class RpcServer extends BaseService {
/**
* @var string rpc项目入口文件
*/
public $entryPoint = false;
const EVENT_RPC_ON_CLOSE = 'rpcClose';
/** /**
* 初始化 * 初始化
*/ */
public function init() { 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); $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 Swoole\Server $server
* @param int $fd * @param int $fd
* @param int $reactorId * @param int $reactorId
@ -47,29 +33,49 @@ class RpcServer extends BaseService {
*/ */
public function onReceive(Swoole\Server $server, int $fd, int $reactorId, string $pack) { public function onReceive(Swoole\Server $server, int $fd, int $reactorId, string $pack) {
$pack = new Pack($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);
}
} }

87
src/Serializer.php

@ -0,0 +1,87 @@
<?php
namespace blobt\airpc;
use yii\base\Arrayable;
use yii\data\DataProviderInterface;
use yii\data\Pagination;
/**
* 重载部分yii\rest\Serializer方法,以适应RPC数据返回格式化
* Class Serializer
* @package blobt\airpc
*/
class Serializer extends \yii\rest\Serializer
{
/**
* Serializes a data provider.
* @param DataProviderInterface $dataProvider
* @return array the array representation of the data provider.
*/
protected function serializeDataProvider($dataProvider)
{
if ($this->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);
}
}

23
src/Yee.php

@ -1,23 +0,0 @@
<?php
namespace blobt\airpc;
use yii\console\controllers\HelpController;
class Yee {
private static $instance;
public static function getInstaance() {
if (empty(self::$instance)) {
self::$instance = new self();
}
return self::$instance;
}
public function run() {
$ret = "some data ".$_SERVER['data'];
return $ret;
}
}

10
src/exception/BadRequestRpcException.php

@ -0,0 +1,10 @@
<?php
namespace blobt\airpc\exception;
class BadRequestRpcException extends RpcException
{
public $statusCode = 400;
}

10
src/exception/ErrorRpcException.php

@ -0,0 +1,10 @@
<?php
namespace blobt\airpc\exception;
class ErrorRpcException extends RpcException
{
public $statusCode = 500;
}

10
src/exception/ForbiddenRpcException.php

@ -0,0 +1,10 @@
<?php
namespace blobt\airpc\exception;
class ForbiddenRpcException extends RpcException
{
public $statusCode = 403;
}

10
src/exception/MethodNotAllowedRpcException.php

@ -0,0 +1,10 @@
<?php
namespace blobt\airpc\exception;
class MethodNotAllowedRpcException extends RpcException
{
public $statusCode = 405;
}

10
src/exception/NotFoundRpcException.php

@ -0,0 +1,10 @@
<?php
namespace blobt\airpc\exception;
class NotFoundRpcException extends RpcException
{
public $statusCode = 404;
}

10
src/exception/RpcException.php

@ -0,0 +1,10 @@
<?php
namespace blobt\airpc\exception;
class RpcException extends \Exception
{
public $statusCode = 500;
}

10
src/exception/UnauthorizedRpcException.php

@ -0,0 +1,10 @@
<?php
namespace blobt\airpc\exception;
class UnauthorizedRpcException extends RpcException
{
public $statusCode = 401;
}

14
systemd/airpc.service

@ -1,14 +0,0 @@
[Unit]
Description=AI Rpc Server
After=network.target
After=syslog.target
[Service]
Type=simple
LimitNOFILE=65535
ExecStart=/usr/bin/php {your server path}
ExecReload=/bin/kill -USR1 $MAINPID
Restart=always
[Install]
WantedBy=multi-user.target graphical.target
Loading…
Cancel
Save