前言

RPC在实际应用中,通常会被多种编程语言所调用,但SW-X官方只提供了PHP相关的RPC-Client封装,若需要使用PHP外的其他编程语言,调用SW-X的RPC服务,则需要自行封装RPC-Client服务。

以下将进入详细的RPC-Client介绍。

RPC-Client的工作

一个完整的Client服务需要支持以下功能:

1、读取RPC服务节点配置(存储在Redis)
2、根据服务路由+目标函数,读取出该服务的全部节点配置
3、在节点配置中,取出评分最高,调用人数最低,延迟最低的节点
4、根据服务配置,按照SW-X规定的RPC交互格式,通过TCP协议发起请求
5、Client与RPC-Server的数据交互需支持AES加密,可自由开启关闭
6、若Server异常或Client发送失败,则需支持最大重复发送次数
7、Client需要支持异步投递任务到RPC-Server端

1、Redis的服务配置格式

RPC服务节点,被存储在select 0redis库中,存储格式是list队列,可以通过llen()lindex()指令读取出某个服务的全部节点,
KEY格式:前缀+swoolex_rpc_+md5(路由+目标函数)
通过lindex()获取到的单条节点配置为JSON数据格式,内容如下:

{
    title:"服务标题" // 服务标题
    ip:"127.0.0.1" // TCP地址
    port:"9501" // TCP端口
    score:"100" // TCP地址
    max_ms:"200" // 最大延迟MS
    status:"0" // 手动关闭状态 0.开启 1.关闭
    is_fault:0 // 故障状态 0.正常 1.故障
    ping_ms:"0.008" // 延迟检测MS
    request_num:23 // 当前使用人数
    class:"driver/get_near_user" // 路由地址
    function:"run" // 目标函数
}

2、Client的数据提交格式

Client是通过TCP连接,请求的RPC-Server服务,所以有严格的数据交互规范,Client的请求数据包必须是JSON数据格式,结构如下:

{
    "class": "zabbix/client_report", // 路由地址
    "function": "run", // 目标函数
    "headers": [], // 业务请求头
    "param": { // 业务请求参数
      "time": 1621498661,
      "task_time": 0.005142,
      "cpu": "1012.34KB"
    },
    "task": true, // 是否异步调用
    "callback": false, // 是否启用异步回调通知,若启用则该参数填入API回调网址
    "callback_type": "post" // 异步回调请求类型
}

3、AES数据加密

由于SW-X的RPC通讯是走的TCP协议,所以在数据传输前后均支持AES加密与解密,若Server开启了数据加密,Client端则都要支持加解密。
使用的AES加密协议,具体可参考PHP的AES加密案例:

PHP数据加解密范例如下:

class Currency
{ 
    /**
        * AES加密方法
        * @todo 无
        * @author 小黄牛
        * @version v1.2.24 + 2021.1.9
        * @deprecated 暂不启用
        * @global 无
        * @param string $data 要加密的数据 
        * @return void
    */
    public function aes_encrypt($data) {  
        $config = \x\Config::run()->get('rpc');
        return openssl_encrypt($data, $config['aes_method'], $config['aes_key'], 0, $config['aes_iv']);  
    }  
    
    /**
        * AES解密方法
        * @todo 无
        * @author 小黄牛
        * @version v1.2.24 + 2021.1.9
        * @deprecated 暂不启用
        * @global 无
        * @param string $data 要解密的数据 
        * @return void
    */  
    public function aes_decrypt($data) {  
        $config = \x\Config::run()->get('rpc');
        return openssl_decrypt($data, $config['aes_method'], $config['aes_key'], 0, $config['aes_iv']);  
    } 
}

4、返回值数据格式

若开启AES加密,Server的返回值则需要进行解密,最终得到明文数据为一个JSON字符串,范例如下:

{
    "status":"200" // 状态码
    "msg":"SUCCESS" // 说明
    "data":true // 服务返回值
}

若请求成功,则status状态码为200,其余状态码均表示请求失败。

具体的Client自行封装,可以参考SW-X提供的FPM-Client类包。点击下载

5、建议的封装风格

$Rpc = new \x\RpcClient();
$body = $Rpc->route(路由地址)
        ->func(目标函数)
        ->header(业务请求头)
        ->param(业务请求参数)
        ->max(异常最大递归次数)
        ->task(true) // 启用异步传输
        ->callback('http://www.baidu.com', 'GET'); // 异步回调通知
        ->send();
// send()的结果,只取Server返回的data部分
if ($Rpc->isSuccess()) {
    var_dump($body);
} else {
    var_dump('no~!');
}