数据库 - Model 前置说明
官方开源项目 抓取代理IP

介绍

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库中,存储数据格式如下:

类型:SETS 键前缀:_sets_ + md5(class + function),存储某项服务下的全部节点Redis_hash键名
类型:HMSET 键前缀:_hash_ + md5(class + function + ip + port),存储单个服务节点信息
类型:SET 键前缀:_score_ + md5(class + function + ip + port),存储单个服务的当前评分值
类型:SET 键前缀:_peaks_ + md5(class + function + ip + port),存储单个服务的当前延迟ms
类型:SET 键前缀:_num_ + md5(class + function + ip + port),存储单个服务的当前请求占用数

以下为获取某个服务下全部节点信息的PHP示例代码:

/**
 * 读取配置
 * @todo 无
 * @author 小黄牛
 * @version v1.2.24 + 2021.1.9
 * @deprecated 暂不启用
 * @global 无
 * @return void
*/
public static function get($class, $function) {
    $redis_key = \x\Config::get('rpc.redis_key');
    $set_key = '_sets_'.md5($class.$function);
    $redis = new \x\Redis();

    $array = $redis->SMEMBERS($redis_key.$set_key);
    $list = [];
    // 读取全部节点
    foreach ($array as $key) {
        $val = $redis->hGetAll($redis_key.$key);
        if ($val) {
            $md5 = md5($val['class'].$val['function'].$val['ip'].$val['port']);
            $score_key = '_score_'.$md5;
            $peaks_key = '_peaks_'.$md5;
            $num_key = '_num_'.$md5;
            
            $val['ping_ms'] = $redis->get($redis_key.$peaks_key);
            $val['score'] = $redis->get($redis_key.$score_key);
            $val['request_num'] = $redis->get($redis_key.$num_key);
            
            $list[] = $val;
        }
    }

    $redis->return();
    return $list;
}

获取到的节点配置为数据内容如下(这里用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~!');
}

SW-X

企业级 - 高性能 PHP 框架

最后更新:3年前 . 作者-小黄牛

本篇目录