php:RPC是什么?

1、什么是RPC?

  • RPC全称Remote Procedure Call,即远程过程调用,就是要像调用本地的函数一样去调远程函数,屏蔽远程调用的复杂性。

 

2、为什么需要RPC?

  • 微服务、分布式应用的开发越来越常见,RPC可以解决各个节点之间的服务调用以及通信问题。
  • 治理功能,比如连接管理、健康检测、负载均衡、优雅启停机、异常重试、业务分组以及熔断限流等等。

 

3、demo实例(php)

上面简单介绍了下rpc,下面咱们直接上代码(以json格式传递,使用http作为传输协议,也可以使用别的协议传输,例如tcp socket)。

//服务端

jsonRPCServer.php //实现rpc逻辑文件

lib.php //业务测试文件

server.php //调用注册实例文件

//jsonRPCServer.php
<?php
class jsonRPCServer
{
    /**
     *处理一个request类,这个类中绑定了一些请求参数
     * @param object $object
     * @return boolean
     */
    public static function handle($object)
    {
        // 判断是否是一个rpc json请求
        if ($_SERVER['REQUEST_METHOD'] != 'POST' || empty($_SERVER['CONTENT_TYPE']) || $_SERVER['CONTENT_TYPE'] != 'application/json'){
            return false;
        }

        // reads the input data
        $request = json_decode(file_get_contents('php://input'), true);

        // 执行请求类中的接口
        try {
            if ($result = @call_user_func_array(array($object, $request['method']), $request['params'])) {
                $response = array('id' => $request['id'], 'result' => $result, 'error' => NULL);
            } else {
                $response = array(
                    'id' => $request['id'], 'result' => NULL,
                    'error' => 'unknown method or incorrect parameters'
                );
            }
        } catch (Exception $e) {
            $response = array('id' => $request['id'], 'result' => NULL, 'error' => $e->getMessage());
        }

        // json 格式输出
        if (!empty($request['id'])) { // notifications don't want response
            header('content-type: text/javascript');
            echo json_encode($response);
        }
        return true;
    }
}
//lib.php
<?php
class lib{

    public function test($string){
        return $string."####success"; //返回字符串
    }
}

//server.php
<?php
require_once 'jsonRPCServer.php';
require 'lib.php';// lib 为测试类

// 服务端调用
$lib = new lib();

// 注入实例
jsonRPCServer::handle($lib)
?>

客户端

jsonRPCClient.php //组装发送请求文件

client.php //调用文件

//jsonRPCClient.php
<?php
class jsonRPCClient
{
    private $debug;

    private $url;

    private $id;//请求id

    private $notification = false;

    /**
     * @param $url
     * @param bool $debug
     */
    public function __construct($url, $debug = false)
    {
        // server URL
        $this->url = $url;

        // debug state
        empty($debug) ? $this->debug = false : $this->debug = true;

        // message id
        $this->id = 1;
    }

    /**
     *
     * @param boolean $notification
     */

    public function setRPCNotification($notification)
    {
        //设置是否不用返回结果(因为有的是异步调用,不需要返回结果)
        empty($notification) ? $this->notification = false  : $this->notification = true;
    }

    /**
     * @param $method
     * @param $params
     * @return bool
     * @throws Exception
     */
    public function __call($method, $params)
    {

        // 检验request信息
        if (!is_scalar($method)) {
            throw new Exception('Method name has no scalar value');
        }

        if (is_array($params)) {
            $params = array_values($params);
        } else {
            throw new Exception('Params must be given as array');
        }

        if ($this->notification) {
            $currentId = NULL;
        } else {
            $currentId = $this->id;
        }

        // 拼装成一个request请求
        $request = array('method' => $method,  'params' => $params, 'id' => $currentId);
        $request = json_encode($request);
        $this->debug && $this->debug .= '***** Request *****' . "\n" . $request . "\n" . '***** End Of request *****' . "\n\n";
        $opts = array('http' => array(
            'method'  => 'POST',
            'header'  => 'Content-type: application/json',
            'content' => $request
        ));

        //  关键几部
        $context  = stream_context_create($opts);
        if ($result = file_get_contents($this->url, false, $context)) {
            $response = json_decode($result, true);
        } else {
            throw new Exception('Unable to connect to ' . $this->url);
        }

        // 输出调试信息
        if ($this->debug) {
            echo nl2br(($this->debug));
        }

        // 检验response信息
        if (!$this->notification) {
            // check
            if ($response['id'] != $currentId) {
                throw new Exception('Incorrect response id (request id: ' . $currentId . ', response id: ' . $response['id'] . ')');
            }

            if (!is_null($response['error'])) {
                throw new Exception('Request error: ' . $response['error']);
            }
            return $response['result'];
        } else {
            return true;
        }
    }
}

?>

//client.php
<?php
require_once 'jsonRPCClient.php';

$url = 'http://127.0.0.1:8080/server.php';//这里是我的测试地址
$jsonRPCClient = new jsonRPCClient($url);

// 客户端调用
try {
	$rs = $jsonRPCClient->test("hello world");
	var_dump($rs);
} catch (Exception $e) {
	echo nl2br($e->getMessage()).'<br />'."\n";
}

 

大家也可以看看,目前一些常用的rpc框架:Dubbo、Spring Cloud、gRPC、Thrift 、Yar

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值