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