全部的界面和服务均在同一个进程下 java
基于mvc的视图与服务分离,可是实际上仍是在一个应用系统中,只不过在功能层次上划分的更加细致 程序员
粒度更细,对于不一样的功能服务进行切分,并进行单独的部署 数据库
面向服务的架构,将应用程序的不一样功能单元(称为服务)经过这些服务之间定义良好的接口和契约联系起来 bash
微服务服务器
此处不支持图片展现,自行脑补!!!网络
随着业务量和用户量的增长,架构也是从单一系统走向分布式系统,我能想到的是,这种架构的演变主要解决的问题在于:架构
随着集中式架构向分布式架构的转变,应用系统之间的服务调用与通信问题成为了首要解决的需求。并发
而RPC 的主要目标就是为了让构建分布式计算(应用)变得更加简单,在提供强大的远程调用能力时不损失本地调用的语义简洁性。 为实现该目标,RPC 框架需提供一种透明调用机制让使用者没必要显式的区分本地调用和远程调用。mvc
以下代码:app
@Autowired
private GlRpcAgent glRpcAgent; //rpc代理
/**
* @param param 此处约定参数以Map键值对的形式传递
*/
@Override
public List<OrderInfo> queryOrdersByUserId(Map<String, Object> param) {
//建立远程调用代理(远程服务的类的全限定名)
OrderConsumeAgent orderConsumer=glRpcAgent.getAgent("com.glmapper.rpc.interface.OrderConsumeInterface");
//经过代理获取返回结果 此处getOrders为远程服务器上的com.glmapper.rpc.interface.OrderConsumeInterface接口中的方法,param为参数
Map<String,Object> resultMap=(Map)orderConsumer.call("getOrders",param);
//解析返回结果(远程方法一样以Map集合的方式放回)
List<OrderInfo> orders = parseResultMap(resultMap);
return orders;
}
复制代码
为何要以全限定名来获取呢,这个咱们将会在后面来讲。
In distributed computing a remote procedure call (RPC) is when a computer program causes a procedure (subroutine) to execute in another address space(commonly on another computer on a shared network), which is coded as if it were a normal (local) procedure call, without the programmer explicitly coding the details for the remote interaction. RPC 的全称是 Remote Procedure Call 是一种进程间通讯方式。 它容许程序调用另外一个进程上(一般是共享网络的另外一台机器上)的过程或函数,而不用程序员显式编码这个远程调用的细节。即程序员不管是调用本地的仍是远程的函数,本质上编写的调用代码基本相同。
从定义中能够得知,RPC主要来解决三件事情:
首先是进程间的通讯问题,对于分布式环境,rpc可以帮助咱们解决不一样服务器之间的通讯及数据传输问题,即**作好方法调用到数据的转换,而后借助网络进行数据传递;**rpc客户端向rpc服务端发起远程服务调用,经过请求的封装,参数的封装,序列化、编码、约定协议传输、解析请求、处理请求、封装返回消息数据、在进行返回数据的序列化、编码、在经过网络返回给客户端。再者是提供和本地方法调用同样的调用机制,为何这么说,对于业务系统来讲,咱们更多的关注点在于如何解决实际的业务需求问题,而不想花更多的时间和心思在诸如上述过程当中关于网络传输及编解码过程,所以对于rpc来讲,须要将这些编解码、协议约定、网络传输等进行一个总体的封装,而后只向业务系统提供最简单的调用方式。最后一个屏蔽程序员对远程调用的细节实现,其实也就是第二点中提到的那些功能的封装,咱们不用去关系rpc究竟是如何实现的,也不用关心它是如何运做的,对于业务开发人员来讲,经过约定的方式进行相似于本地方法调用的形式来调用远程服务接口就能够了。 那么如何实现透明化的远程调用呢? 什么样的内部封装才能让咱们以为像以本地调用方式调用远程服务呢? 对于java来讲就是使用代理。java代理有两种方式:1) jdk 动态代理(接口代理);2)cglib代理(子类代理)。尽管字节码生成方式实现的代理更为强大和高效,但代码不易维护,大部分公司实现RPC框架时仍是选择动态代理方式。这部分也将会在后续的章节中展开来讲。
上面说到,rpc须要对一些远程调用的内部实现进行封装。咱们说到有如下几个点:
从发起远程调用到接收到数据返回结果,大体过程是:
1)服务消费方(client)调用以本地调用方式调用服务; 2)client stub接收到调用后负责将方法、参数等组装成可以进行网络传输的消息体; 3)client stub找到服务地址,并将消息发送到服务端; 4)server stub收到消息后进行解码; 5)server stub根据解码结果调用本地的服务; 6)本地服务执行并将结果返回给server stub; 7)server stub将返回结果打包成消息并发送至消费方; 8)client stub接收到消息,并进行解码; 9)服务消费方获得最终结果。
那么rpc就至关于将step2-step8的步骤进行了封装。下面借用一张网上的图片来帮助咱们理解这个过程。
对于上图,咱们进行进一步的拆解获得(来自网络):
经过上述分析可知,这里面包括如下核心组件:
目前常见的分布式RPC框架有如下几个:
MQ(message queue)消息队列,从某种程度上来讲,一样能够实现RPC的功能。从功能特色上来讲,MQ能够把消息存储,而RPC不行。关于MQ和RPC作了如下简单的对比,以下图所示:
本文对RPC的基本原理、特色以及基本组件进行了简单的说明,让咱们能够对RPC有一个基本的了解。关于常见的RPC框架也作了基本认识,对于这些优秀的框架,咱们在实现咱们本身RPC时能够借鉴一下这些架构里的一些模式以及技术。最后说明了下为何咱们会在分布式架构中要使用RPC而不是MQ,对于MQ来讲,在处理同步调用没法知足实际的生产需求,而RPC才更加适合分布式应用的实际须要。