Rpc-Server
場(chǎng)景
例如在一個(gè)商場(chǎng)系統(tǒng)中,我們將商品庫(kù)和系統(tǒng)公告兩個(gè)服務(wù)切分開(kāi)到不同的服務(wù)器當(dāng)中。當(dāng)用戶打開(kāi)商場(chǎng)首頁(yè)的時(shí)候,
我們希望 App 向某個(gè)網(wǎng)關(guān)發(fā)起請(qǐng)求,該網(wǎng)關(guān)可以自動(dòng)地幫我們請(qǐng)求商品列表和系統(tǒng)公共等數(shù)據(jù),合并返回。
服務(wù)定義
每一個(gè) Rpc 服務(wù)其實(shí)就是一個(gè) EasySwoole\Rpc\Service\AbstractService 類,在服務(wù)下面我們又分為多個(gè)子模塊,每個(gè)子模塊提供不同的服務(wù)。 如下:
定義商品服務(wù)
<?php
namespace App\RpcServices;
use EasySwoole\Rpc\Protocol\Request;
use EasySwoole\Rpc\Service\AbstractService;
class Goods extends AbstractService
{
/**
* 重寫(xiě)onRequest(比如可以對(duì)方法做ip攔截或其它前置操作)
*
* @param Request $request
* @return bool
*/
protected function onRequest(Request $request): bool
{
return true;
}
function serviceName(): string
{
return 'Goods';
}
}
定義商品服務(wù)的子模塊
<?php
namespace App\RpcServices;
use EasySwoole\Rpc\Service\AbstractServiceModule;
class GoodsModule extends AbstractServiceModule
{
function moduleName(): string
{
return 'GoodsModule';
}
function list()
{
$this->response()->setResult([
[
'goodsId' => '100001',
'goodsName' => '商品1',
'prices' => 1124
],
[
'goodsId' => '100002',
'goodsName' => '商品2',
'prices' => 599
]
]);
$this->response()->setMsg('get goods list success');
}
function exception()
{
throw new \Exception('the GoodsModule exception');
}
protected function onException(\Throwable $throwable)
{
$this->response()->setStatus(-1)->setMsg($throwable->getMessage());
}
}
定義公共服務(wù)
<?php
namespace App\RpcServices;
use EasySwoole\Rpc\Service\AbstractService;
class Common extends AbstractService
{
function serviceName(): string
{
return 'Common';
}
}
定義公共服務(wù)的子模塊
<?php
namespace App\RpcServices;
use EasySwoole\Rpc\Service\AbstractServiceModule;
class CommonModule extends AbstractServiceModule
{
function moduleName(): string
{
return 'CommonModule';
}
public function mailBox()
{
// 獲取client 全局參數(shù)
$this->request()->getClientArg();
// 獲取參數(shù)
$this->request()->getArg();
$this->response()->setResult([
[
'mailId'=>'100001',
'mailTitle'=>'系統(tǒng)消息1',
],
[
'mailId'=>'100001',
'mailTitle'=>'系統(tǒng)消息1',
],
]);
$this->response()->setMsg('get mail list success');
}
public function serverTime()
{
$this->response()->setResult(time());
$this->response()->setMsg('get server time success');
}
}
服務(wù)注冊(cè)
在 EasySwoole 全局事件(即項(xiàng)目根目錄的 EasySwooleEvent 文件)中,進(jìn)行服務(wù)注冊(cè)。至于節(jié)點(diǎn)管理、服務(wù)類定義等具體用法請(qǐng)看對(duì)應(yīng)章節(jié)。
<?php
namespace EasySwoole\EasySwoole;
use EasySwoole\EasySwoole\AbstractInterface\Event;
use EasySwoole\EasySwoole\Swoole\EventRegister;
class EasySwooleEvent implements Event
{
public static function initialize()
{
date_default_timezone_set('Asia/Shanghai');
}
public static function mainServerCreate(EventRegister $register)
{
###### 注冊(cè) rpc 服務(wù) ######
/** rpc 服務(wù)端配置 */
$config = new \EasySwoole\Rpc\Config();
$config->setNodeId('EasySwooleRpcNode1');
$config->setServerName('EasySwoole'); // 默認(rèn) EasySwoole
$config->setOnException(function (\Throwable $throwable) {
});
$serverConfig = $config->getServer();
// 單機(jī)部署內(nèi)部調(diào)用時(shí)可指定為 127.0.0.1
// 分布式部署時(shí)多臺(tái)調(diào)用時(shí)請(qǐng)?zhí)?0.0.0.0
$serverConfig->setServerIp('127.0.0.1');
// rpc 具體配置請(qǐng)看配置章節(jié)
$rpc = new \EasySwoole\Rpc\Rpc($config);
// 創(chuàng)建 Goods 服務(wù)
$goodsService = new \App\RpcServices\Goods();
// 添加 GoodsModule 模塊到 Goods 服務(wù)中
$goodsService->addModule(new \App\RpcServices\GoodsModule());
// 添加 Goods 服務(wù)到服務(wù)管理器中
$rpc->serviceManager()->addService($goodsService);
// 創(chuàng)建 Common 服務(wù)
$commonService = new \App\RpcServices\Common();
// 添加 CommonModule 模塊到 Common 服務(wù)中
$commonService->addModule(new \App\RpcServices\CommonModule());
// 添加 Common 服務(wù)到服務(wù)管理器中
$rpc->serviceManager()->addService($commonService);
// 此刻的rpc實(shí)例需要保存下來(lái) 或者采用單例模式繼承整個(gè)Rpc類進(jìn)行注冊(cè) 或者使用Di
// 注冊(cè) rpc 服務(wù)
$rpc->attachServer(ServerManager::getInstance()->getSwooleServer());
}
}
服務(wù)端響應(yīng)狀態(tài)碼說(shuō)明
| 狀態(tài)碼 | 說(shuō)明 |
|---|---|
| 0 | 調(diào)用成功 |
| 1001 | 獲取不到服務(wù)端可用節(jié)點(diǎn),調(diào)用失敗 |
| 1002 | 客戶端連接服務(wù)端節(jié)點(diǎn)超時(shí),調(diào)用失敗 |
| 1003 | 服務(wù)端響應(yīng)超時(shí),調(diào)用失敗 |
| 2001 | 服務(wù)端讀取客戶端請(qǐng)求數(shù)據(jù)包超時(shí),調(diào)用失敗 |
| 2002 | 客戶端發(fā)送的數(shù)據(jù)包不合法,調(diào)用失敗 |
| 3000 | 服務(wù)端節(jié)點(diǎn)宕機(jī),調(diào)用失敗 |
| 3001 | 調(diào)用的服務(wù)不存在,調(diào)用失敗 |
| 3002 | 調(diào)用服務(wù)的子模塊不存在,調(diào)用失敗 |
| 3003 | 調(diào)用服務(wù)錯(cuò)誤,調(diào)用失敗 |
| 其他 | 未知錯(cuò)誤,調(diào)用失敗 |
為了方便測(cè)試,我把兩個(gè)服務(wù)放在同一臺(tái)機(jī)器中注冊(cè)。實(shí)際生產(chǎn)場(chǎng)景應(yīng)該是
N臺(tái)機(jī)注冊(cè)商品服務(wù),N臺(tái)機(jī)器注冊(cè)公告服務(wù),把服務(wù)分開(kāi)。