RPC架构简单理解
RPC(Remote Promote Call) 一种进程间通信方式。允许像调用本地服务一样调用远程服务。
RPC框架的主要目标就是让远程服务调用更简单、透明。RPC框架负责屏蔽底层的传输方式(TCP或者UDP)、序列化方式(XML/JSON/二进制)和通信细节。开发人员在使用的时候只需要了解谁在什么位置提供了什么样的远程服务接口即可,并不需要关心底层通信细节和调用过程。

RPC框架原理图
简单的RPC代码实现
package Server;
public interface EchoService {
String echo(String ping);
}
package Server;
public class EchoServiceImpl implements EchoService{
@Override
public String echo(String ping) {
// TODO Auto-generated method stub
return ping !=null?ping+"--> I am ok.":"I am bad.";
}
}
package Exporter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
/**
* RPC服务端发布者
* 作为服务端,监听客户端的TCP连接,接收到新的客户端连接之后,将其封装成Task,由线程池执行
* 将客户端发送的码流反序列化成对象,反射调用服务实现者,获取执行结果
* 将执行结果对象发序列化,通过Socket发送给客户端
* 远程调用完成之后,释放Socket等连接资源,防止句柄泄露
* @author Administrator
*
*/
public class RpcExporter {
//创建一个可重用固定线程数的线程池
//Runtime.getRuntime().availableProcessors()返回虚拟机可用的处理器数量
static Executor executor=Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
public static void exporter(String hostname,int port) throws IOException {
//创建一个监听特定端口的Serversocket,负责接收客户连接请求
ServerSocket server = new ServerSocket();
//绑定主机名端口号
server.bind(new InetSocketAddress(hostname,port));
try{
while(true)
{
executor.execute(new ExporterTask(server.accept()));
}
}finally
{
server.close();
}
}
private static class ExporterTask implements Runnable{
Socket client=null;
public ExporterTask(Socket client){
this.client=client;
}
@Override
public void run() {
// TODO Auto-generated method stub
ObjectInputStream input=null;
ObjectOutputStream output=null;
try{
//获取输入流
input=new ObjectInputStream(client.getInputStream());
//获取调用的接口名
String interfaceName = input.readUTF();
//加载接口
Class<?> service = Class.forName(interfaceName);
//获取调用的方法名
String methodName = input.readUTF();
//获取方法返回类型
Class<?>[] ParameterTypes = (Class<?>[]) input.readObject();
//获取参数
Object[] arguments = (Object[]) input.readObject();
//通过反射获取方法
Method method = service.getMethod(methodName, ParameterTypes);
//通过反射调用方法
Object result = method.invoke(service.newInstance(), arguments);
output = new ObjectOutputStream(client.getOutputStream());
output.writeObject(result);
}catch(Exception e){
e.printStackTrace();
}
finally{
if(output != null)
try{
output.close();
}catch ( IOException e){
e.printStackTrace();
}
if(input !=null)
try{
input.close();
}catch(IOException e){
e.printStackTrace();
}
if(client != null)
try{
client.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
}
package Client;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.InetSocketAddress;
import java.net.Socket;
/**
*本地服务代理
*将本地的接口调用转换成JDK的动态代理,在动态代理中实现接口的远程调用
*创建Socket客户端,根据指定地址连接远程服务提供者
*将远程服务调用所需要的接口类,方法名,参数列表等编码参数发送给服务提供者
*同步阻塞等待服务端返回应答,获取应答之后返回
* @author Administrator
*
* @param <S>
*/
public class RpcImporter<S> {
@SuppressWarnings("unchecked")
public S importer(final Class<?> serviceClass,final InetSocketAddress addr)
{
return (S) Proxy.newProxyInstance(serviceClass.getClassLoader(), new Class<?>[] {serviceClass.getInterfaces()[0]}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
Socket socket =null;
ObjectOutputStream output = null;
ObjectInputStream input = null;
try{
socket = new Socket();
socket.connect(addr);
//将远程服务调用所需要的接口类,方法名,参数列表等编码参数发送给服务提供者
output = new ObjectOutputStream(socket.getOutputStream());
output.writeUTF(serviceClass.getName());
output.writeUTF(method.getName());
output.writeObject(method.getParameterTypes());
output.writeObject(args);
//同步阻塞等待服务端返回应答,获取应答之后返回
input= new ObjectInputStream(socket.getInputStream());
return input.readObject();
}
finally{
if(socket != null)
socket.close();
if(output != null)
output.close();
if(input != null)
input.close();
}
}
});
}
}
package test;
import java.net.InetSocketAddress;
import Client.RpcImporter;
import Exporter.RpcExporter;
import Server.EchoService;
import Server.EchoServiceImpl;
public class run {
public static void main(String[] args) {
// TODO Auto-generated method stub
//创建异步发布服务端的线程并启动,用于接受PRC客户端的请求,根据请求参数调用服务实现类,返回结果给客户端
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try{
RpcExporter.exporter("localhost", 8088);
}catch (Exception e){
e.printStackTrace();
}
}
}).start();
//创建客户端服务代理类,构造RPC求情参数,发起RPC调用
RpcImporter<EchoService> importer=new RpcImporter<EchoService>();
EchoService echo = importer.importer(EchoServiceImpl.class, new InetSocketAddress("localhost",8088));
System.out.println(echo.echo("Are u ok?"));
}
}
RPC框架实现的几个核心技术点:
(1)远程提供者需要以某种形式提供服务调用相关的信息,包括但不限于服务接口定义、数据结构、或者中间态的服务定义文件。例如Facebook的 Thrift的IDL文件,Web service的WSDL文件;服务的调用者需要通过一定的图景获取远程服务调用相关的信息。
(2)远程代理对象:服务调用者用的服务实际是远程服务的本地代理。说白了就是通过动态代理来实现。
(3)通信:RPC框架与具体的协议无关。
(4)序列化:毕竟是远程通信,需要将对象转化成二进制流进行传输。不同的RPC框架应用的场景不同,在序列化上也会采取不同的技术
RPC面临的挑战
在大规模服务化之前,应用可能只是通过RPC框架,简单的暴露和引用远程服务,通过配置URL地址进行远程服务调用,路由则通过F5负载均衡器等进行简单的负载均衡。
当服务越来越多的时候,服务的URL配置管理变得更加困难。单纯的使用RPC就有点吃不消。所以在大规模分布式集群中,RPC只是作为集群的一个方法调用手段。例如在Hadoop的进程间交互都是通过RPC来进行的,比如Namenode与Datanode直接,Jobtracker与Tasktracker之间等。
RPC与Web Servie
讲道理,我觉得RPC与Webservice很像.可以说Web Service是在RPC发展的基础之上。web service是运行在web上的一个服务
RPC使用C/S方式,发送请求到服务器,等待服务器返回结果。
Web Service提供的服务是基于web容器的,底层使用http协议,类似一个远程的服务提供者,比如天气预报服务,对各地客户端提供天气预报,是一种请求应答的机制,是跨系统跨平台的。就是通过一个servlet,提供服务出去。
RPC与JMS
在RPC中,当一个请求到达RPC服务器时,这个请求就包含了一个参数集和一个文本值,通常形成“classname.methodname”的形式。这就向RPC服务器表明,被请求的方法在为“classname”的类中,名叫“methodname”。然后RPC服务器就去搜索与之相匹配的类和方法,并把它作为那种方法参数类型的输入。这里的参数类型是与RPC请求中的类型是匹配的。一旦匹配成功,这个方法就被调用了,其结果被编码后返回客户方。
JMS 一般只是一个点发出一个Message到Message Server,发出之后一般不会关心谁用了这个message。JMS可以做到异步调用完全隔离了客户端和服务提供者,能够抵御流量洪峰;JMS获得消息可以进行延迟处理,而RPC一般是进行实时调用。
相比较其他的通信而言,RPC的侧重点在于方法。并且是C/S架构方式

服务化架构的演进图
MVC架构:当业务规模很小时,将所有功能都不熟在同一个进程中,通过双机或者负载均衡器实现负债分流;此时,分离前后台逻辑的MVC架构是关键。
PRC架构:当垂直应用越来越多,应用之间交互不可避免,将核心和公共业务抽取出来,作为独立的服务,实现前后台逻辑分离。此时,用于提高业务复用及拆分的RPC框架是关键。
SOA架构:随着业务发展,服务数量越来越多,服务生命周期管控和运行态的治理成为瓶颈,此时用于提升服务质量的SOA服务治理是关键。
微服务架构:通过服务的原子化拆分,以及微服务的独立打包、部署和升级,小团队的交付周期将缩短,运维成本也将大幅度下降。
RPC架构简单理解的更多相关文章
- B/S和C/S架构简单理解
B/S和C/S架构简单理解 B/S结构.C/S结构 B(browser浏览器)-S(server服务器),说简单点就是通过浏览器来请求服务器,实现数据交互.那自然了,C(client客户端软件)-S( ...
- [svc]简单理解什么是rpc调用?跟restapi有何区别?
什么是rpc调用 restapi调用方式是对数据的crud. 常见的我们写flash写个api,或者借助django drf写个标准的resetapi,一个url可以借助httpget post pu ...
- RPC架构-美团,京东面试题目
RPC(Remote Procedure Call) RPC服务 从三个角度来介绍RPC服务:分别是RPC架构,同步异步调用以及流行的RPC框架. RPC架构 先说说RPC服务的基本架构吧.允许我可耻 ...
- 关于RabbitMQ的简单理解
说明:想要理解RabbitMQ,需要先理解MQ是什么?能做什么?然后根据基础知识去理解RabbitMQ是什么.提供了什么功能. 一.MQ的简单理解 1. 什么是MQ? 消息队列(Message Que ...
- SQL SERVER 2005/2008 中关于架构的理解(一)
SQL SERVER 2005/2008 中关于架构的理解(一) 在一次的实际工作中碰到以下情况,在 SQL SERVER 2008中,新建了一个新用户去访问几张由其他用户创建的表,但是无法进行查询, ...
- 关于ASP.NET或VS2005 搭建三层架构的理解
最近想学习ASP.NET建网站,关于ASP.NET或VS2005 搭建三层架构的理解,网上摘录了一些资料,对于第(2)点的讲解让我理解印象深刻,如下: (1)为何使用N层架构? 因为每一层都可以在仅仅 ...
- REST RPC架构思想
1.REST RPC是什么? REST RPC是一个改进版的RPC架构,它是为了解决传统的RPC和REST方案的一些不足之处而生的,它结合了REST API和RPC的优点,同时又克服了REST API ...
- 【转】Linux 概念架构的理解
转:http://mp.weixin.qq.com/s?__biz=MzA3NDcyMTQyNQ==&mid=400583492&idx=1&sn=3b18c463dcc451 ...
- 【转】SQL SERVER 2005/2008 中关于架构的理解
在一次的实际工作中碰到以下情况,在 SQL SERVER 2008中,新建了一个新用户去访问几张由其他用户创建的表,但是无法进行查询,提示“对象名'CustomEntry' 无效.”.当带上了架构名称 ...
随机推荐
- LNMP架构之搭建wordpress博客网站
系统环境版本 [root@db02 ~]# cat /etc/redhat-release CentOS release 6.9 (Final) [root@db02 ~]# uname -a Lin ...
- CSS制作波浪线
建议先去了解清楚了径向渐变,线性渐变的用法先 这个作者的css制作波浪线讲解很不错额:https://www.jianshu.com/p/8570433e3669不理解的可以看看这个链接的额 可以去菜 ...
- 解决 iPhone 微信 H5 无法自动播放音乐问题
使用 wx sdk 在html导入sdk js文件.(如果网站是https导入的sdk也要使用https!) 然后在 wx.ready 中设置 play 方法并复制给全局变量 fm,当需要使用的时候再 ...
- linux下一键安装redis并设置为后台进程及开机启动
1.下载适合你的版本的redis(下载页面https://redis.io/download),我下载的是4.0.6版本 wget http://download.redis.io/releases/ ...
- 如何压缩UUID长度?
java中UUID的toString方法,生成的uuid是36位了,在项目中,有时候会显的过长,占用空间比较多,如何能够压缩存储下,又能够保证uuid的唯一性呢? 一. 思路 看源码后,发现UUID的 ...
- Python笔记(一):安装+爬虫环境配置+打包为EXE文件
1. 安装 https://www.python.org/downloads/windows/ 到官网下载安装程序 Windows x86 32位操作系统 Windows x8 ...
- [转载]阿里云MySQL优化主从同步,降低数据延迟
1. 背景 为了提高系统的可用性和数据保护,MySQL通常采用master-slave的部署结构,简单高效,master和slave之间使用binlog来复制数据. binlog支持statement ...
- python语言学习笔记整理
什么是程序? 程序等于数据结构加算法,那么数据结构是一个静态的东西,算法是一个动态的东西,我们用一个新的语言编写这个程序,我们要考虑到语言也主要由数据结构和算法相关的东西,或静态或动态的东西来构成,所 ...
- Educational Codeforces Round 2_B. Queries about less or equal elements
B. Queries about less or equal elements time limit per test 2 seconds memory limit per test 256 mega ...
- use ambiguous的错误——编译错误
出现这样的问题是因为namespace std里面已经有一个count了,而 using namespace std;语句把该namespace 打开了,这导致了后面的引用不明确: 不过这里也可以把u ...