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
扫描二维码关注公众号,回复:
16791526 查看本文章