帮助 phper 理解 RPC 是怎么回事儿

1. 什么是 rpc

RPC 全称为 Remote Procedure Call,翻译过来为 “远程过程调用”。

目前,主流的平台中都支持各种远程调用技术,以满足分布式系统架构中不同的系统之间的远程通信和相互调用。远程调用的应用场景极其广泛,实现的方式也各式各样。

2. 从通信协议的层面

基于 HTTP 协议的(例如基于文本的 SOAP(XML)、Rest(JSON),基于二进制 Hessian(Binary))

基于 TCP 协议的(通常会借助 Mina、Netty 等高性能网络框架)

RPC (远程过程调用) 是什么

  • 简单的说,RPC 就是从一台机器(客户端)上通过参数传递的方式调用另一台机器(服务器)上的一个函数或方法(可以统称为服务)并得到返回的结果。
  • RPC 会隐藏底层的通讯细节(不需要直接处理 Socket 通讯或 Http 通讯)
  • RPC 是一个请求响应模型。客户端发起请求,服务器返回响应(类似于 Http 的工作方式)
  • RPC 在使用形式上像调用本地函数(或方法)一样去调用远程的函数(或方法)。

远程过程调用发展历程

  • ONC RPC (开放网络计算的远程过程调用),OSF RPC(开放软件基金会的远程过程调用)
  • CORBA(Common Object Request Broker Architecture 公共对象请求代理体系结构)
  • DCOM(分布式组件对象模型),COM+
  • .NET Remoting
  • XML-RPC,SOAP,Web Service
  • PHPRPC,Hessian,JSON-RPC
  • Microsoft WCF,WebAPI
  • ZeroC Ice,Thrift,GRPC
  • Hprose

早期的 RPC

  • 第一代 RPC(ONC RPC,OSF RPC)不支持对象的传递。
  • CORBA 太复杂,各种不同实现不兼容,一般程序员也玩不转。
  • DCOM,COM+ 逃不出 Windows 的手掌心。
  • RMI 只能在 Java 里面玩。
  • .NET Remoting 只能在 .NET 平台上玩。

XML-RPC,SOAP,WebService

  • 冗余数据太多,处理速度太慢。
  • RPC 风格的 Web Service 跨语言性不佳,而 Document 风格的 Web Service 又太过难用。
  • Web Service 没有解决用户的真正问题,只是把一个问题变成了另一个问题。
  • Web Service 的规范太过复杂,以至于在 .NET 和 Java 平台以外没有真正好用的实现,甚至没有可用的实现。
  • 跨语言跨平台只是 Web Service 的一个口号,虽然很多人迷信这一点,但事实上它并没有真正实现。

 

PHPRPC

  • 基于 PHP 内置的序列化格式,在跨语言的类型映射上存在硬伤。
  • 通讯上依赖于 HTTP 协议,没有其它底层通讯方式的选择。
  • 内置的加密传输既是特点,也是缺点。
  • 虽然比基于 XML 的 RPC 速度快,但还不是足够快。

Hessian

  • 二进制的数据格式完全不具有可读性。
  • 官方只提供了两个半语言的实现(Java,ActionScript 和不怎么完美的 Python 实现),其它语言的第三方实现良莠不齐。
  • 支持的语言不够多,对 Web 前端的 JavaScript 完全无视。
  • 虽然是动态 RPC,但动态性仍然欠佳。
  • 虽然比基于 XML 的 RPC 速度快,但还不是足够快。

JSON-RPC

  • JSON 具有文本可读性,且比 XML 更简洁。
  • JSON 受 JavaScript 语言子集的限制,可表示的数据类型不够多。
  • JSON 格式无法表示数据内的自引用,互引用和循环引用。
  • 某些语言具有多种版本的实现,但在类型影射上没有统一标准,存在兼容性问题。
  • JSON-RPC 虽然有规范,但是却没有统一的实现。在不同语言中的各自实现存在兼容性问题,无法真正互通。

Microsoft WCF,WebAPI

  • 它们是微软对已有技术的一个 .NET 平台上的统一封装,是对 .NET Remoting、WebService 和基于 JSON 、XML 等数据格式的 REST 风格的服务等技术的一个整合。
  • 虽然号称可以在 .NET 平台以外来调用它的这些服务,但实际上跟在 .NET 平台内调用完全是两码事。它没有提供任何在其他平台的语言中可以使用的任何工具

ZeroC Ice,Thrift,GRPC

  • 初代 RPC 技术的跨语言面向对象的回归。
  • 仍然需要通过中间语言来编写类型和接口定义。
  • 仍然需要用代码生成器来将中间语言编写的类型和接口定义翻译成你所使用的编程语言的客户端和服务器端的占位程序(stub)。
  • 你必须要基于生成的服务器代码来单独编写服务,而不能将已有代码直接作为服务发布。
  • 你必须要用生成的客户端代码来调用服务,而没有其它更灵活的方式。
  • 如果你的中间代码做了修改,以上所有步骤你都要至少重复一遍。

Hprose

  • 无侵入式设计,不需要单独定义类型,不需要单独编写服务,已有代码可以直接发布为服务。
  • 具有丰富的数据类型和完美的跨语言类型映射,支持自引用,互引用和循环引用数据。
  • 支持众多传输方式,如 HTTP、TCP、Websocket 等。
  • 客户端具有更灵活的调用方式,支持同步调用,异步调用,动态参数,可变参数,引用参数传递,多结果返回(Golang)等语言特征,Hprose 2.0 甚至支持推送。
  • 具有良好的可扩展性,可以通过过滤器和中间件实现加密、压缩、缓存、代理等各种功能性扩展。
  • 兼容的无差别跨语言调用
  • 支持更多的常用语言和平台
  • 支持浏览器端的跨域调用
  • 没有中间语言,无需学习成本
  • 性能卓越,使用简单

RPC 与 Socket 有什么区别?

两者都是调用远程的方法,都是 client/server 模式。

RPC(远程过程调用)采用客户机 / 服务器模式实现两个进程之间相互通信。socket 是 RPC 经常采用的通信手段之一,RPC 是在 Socket 的基础上实现的,它比 socket 需要更多的网络和系统资源。除了 Socket,RPC 还有其他的通信方法,比如:http、操作系统自带的管道等技术来实现对于远程程序的调用。微软的 Windows 系统中,RPC 就是采用命名管道进行通信。

RPC 与 REST 有什么区别?

通过了解 RPC 后,我们知道是 RPC 是 client/server 模式的,调用远程的方法,REST 也是我们熟悉的一套 API 调用协议方法,它也是基于 client/server 模式的,调用远程的方法的,那他俩又有啥区别呢?

REST API 和 RPC 都是在 Server 端 把一个个函数封装成接口暴露出去,以供 Client 端 调用,不过 REST API 是基于 HTTP 协议的,REST 致力于通过 http 协议中的 POST/GET/PUT/DELETE 等方法和一个可读性强的 URL 来提供一个 http 请求。而 RPC 则可以不基于 HTTP 协议

因此,如果是后端两种语言互相调用,用 RPC 可以获得更好的性能(省去了 HTTP 报头等一系列东西),应该也更容易配置。如果是前端通过 AJAX 调用后端,那么用 REST API 的形式比较好(因为无论如何也避不开 HTTP 这道坎)。

1、HTTP 和 RPC 同一级别,还是被 RPC 包含?

2、Restful 也属于 RPC 么?

图挂了

上图是一个比较完整的关系图,这时我们发现 HTTP(图中蓝色框)出现了两次。其中一个是和 RPC 并列的,都是跨应用调用方法的解决方案;另一个则是被 RPC 包含的,是 RPC 通信过程的可选协议之一。

因此,第一个问题的答案是都对。看指的是哪一个蓝色框。从题主的提问看,既然题主在纠结这两者,应该是指与 RPC 并列的蓝色框。

第二个问题是在问远程过程调用(红色框)是不是包含了 Restful(黄色框),这种理解的关键在于对 RPC 的理解。

RPC 字面理解是远程过程调用,即在一个应用中调用另一个应用的方法。那 Restful 是满足的,通过它可以实现在一个应用中调用另一个应用的方法。

但是,上述理解使得 RPC 的定义过于宽泛。RPC 通常特指在一个应用中调用另一个应用的接口而实现的远程调用,即红色框所指的范围。这样,RPC 是不包含 Restful 的。

因此,第二个问题的答案是 Restful 不属于 RPC,除非对 RPC 有着非常规的宽泛理解。

RPC 的英文全称是 Remote Procedure Call,翻译为中文叫 “远程过程调用”。其中稍显晦涩的其实就是 “过程”,过程其实就是方法。所以,可以把 RPC 理解为 “远程方法调用”。

要了解远程过程调用,那先理解过程调用。非常简单,如下图,就是调用一个方法。这太常见了,不多解释。

而在分布式系统中,因为每个服务的边界都很小,很有可能调用别的服务提供的方法。这就出现了服务 A 调用服务 B 中方法的需求,即远程过程调用。

要想让服务 A 调用服务 B 中的方法,最先想到的就是通过 HTTP 请求实现。是的,这是很常见的,例如服务 B 暴露 Restful 接口,然后让服务 A 调用它的接口。基于 Restful 的调用方式因为可读性好(服务 B 暴露出的是 Restful 接口,可读性当然好)而且 HTTP 请求可以通过各种防火墙,因此非常不错。

然而,如前面所述,基于 Restful 的远程过程调用有着明显的缺点,主要是效率低、封装调用复杂。当存在大量的服务间调用时,这些缺点变得更为突出。

服务 A 调用服务 B 的过程是应用间的内部过程,牺牲可读性提升效率、易用性是可取的。基于这种思路,RPC 产生了。

通过 hprose 实现 rpc

HPROSE 是 High Performance Remote Object Service Engine 的缩写,翻译成中文就是 “高性能远程对象服务引擎”。

它是一个先进的轻量级的跨语言跨平台面向对象的高性能远程动态通讯中间件。它不仅简单易用,而且功能强大。你只需要稍许的时间去学习,就能用它轻松构建跨语言跨平台的分布式应用系统了。

Hprose 支持众多流行的编程语言,例如:

  • AAuto Quicker
  • ActionScript
  • ASP
  • C++
  • Delphi/Free Pascal
  • dotNET(C#, Visual Basic…)
  • Golang
  • Java
  • JavaScript
  • Node.js
  • Objective-C
  • Perl
  • PHP
  • Python
  • Ruby

通过 Hprose,你就可以在这些语言之间方便高效的实现互通了。

基础实现

在同一个文件夹下,执行一下操作,分别是拉取组建的命令,创建两个文件和执行 php 文件。

拉取 hprose 组件

composer require hprose/hprose

  

建立 server.php

<?php
require_once "./vendor/autoload.php";
use Hprose\Socket\Server;
function hello($name) {
return "Hello $name!";
}
$server = new Server("tcp://0.0.0.0:1314");
$server->setErrorTypes(E_ALL);
$server->setDebugEnabled();
$server->addFunction('hello');
$server->start();

  

建立 client.php

<?php
require_once "./vendor/autoload.php";
use \Hprose\Future;
use \Hprose\Socket\Client;
$test = new Client("tcp://127.0.0.1:1314");
$test->fullDuplex = true;
Future\co(function() use ($test) {
try {
var_dump((yield $test->hello("yield world1")));
var_dump((yield $test->hello("yield world2")));
var_dump((yield $test->hello("yield world3")));
var_dump((yield $test->hello("yield world4")));
var_dump((yield $test->hello("yield world5")));
var_dump((yield $test->hello("yield world6")));
}
catch (\Exception $e) {
echo ($e);
}
});

  

执行

php server.php
php client.php

  

结果

string(19) "Hello yield world1!"
string(19) "Hello yield world2!"
string(19) "Hello yield world3!"
string(19) "Hello yield world4!"
string(19) "Hello yield world5!"
string(19) "Hello yield world6!"

  

更多学习内容请访问:

腾讯T3-T4标准精品PHP架构师教程目录大全,只要你看完保证薪资上升一个台阶(持续更新)

 

posted @ 2020-06-12 16:53  八重樱  阅读(419)  评论(0编辑  收藏  举报