什么是RPC

时间:2024-10-22 08:16:51

目录

 

RPC定义

RPC的相关问题

DUBBO


RPC定义

RPC就是远程服务调用(Remote Procedure Call),这在分布式环境中就是调用一个服务的事情.你可以理解为,一个复杂的Service实现,在公司里已经有人做过了,而你需要的,就是去调用他写好的服务,这就是RPC.分布式就是一个业务需要通过两个服务器完成,也就是远程服务调用.这和集群的概念可不一样,集群是表示的是多个服务器拥有同一个服务,消费者调用任何一个都可以.

消费者是什么?顾客就是上帝?不不不,消费者和用户在RPC中是两个概念,消费者指代的是调用服务的人,也就是程序员,而提供服务的人叫生产者.这个消费者和生产者,其实也就是程序罢了.

RPC在Java层面来讲,是一个服务器去访问另一个服务器,所以一定会涉及到对象的序列化和反序列化,什么是序列化和反序列化?其实就是把对象解析成字节流,然后通过网络发送过去,毕竟网络通信不识别对象.

所以序列化是对象转为字节流,反序列化是字节流转为对象.而两个服务之间的通信,有多种选择.比如说多线程阻塞式的bio通信,单线程的通道轮询NIO,还有单线程异步的aio.目前比较成熟的是基于NIO的netty框架.值得注意的是,两个服务器内部的通信不需要遵守http协议,目前采用gRPC.

RPC的相关问题

大家可能已经接触过zookeeper,dubbo等分布式开发工具了,觉得RPC很复杂,其实不然,真正要实现RPC也就不过百行的代码.简单的说,那就是一个网络交互,你发请求我监听,监听到了再处理处理把数据还给你.基于Socket通信就能够做的出来.

那zookeeper和dubbo干嘛用的呢?别急,且听我娓娓道来.

首先我们脑补一个环境,在一个大公司里,业务有很多,项目也很多,同一段程序,可能已经在其他人那里实现过了.那么,这个时候我们如果能够直接调用岂不美哉.也就是用RPC.但是公司内部那么多的生产者消费者,如果没有人管某天这个服务器崩了都不知道怎么回事,更别提改了.于是,zookeeper和dubbo就应运而生了.

且想,如果我要管理所有的生产者和消费者,我需要写一个管理者出来,而这个管理者要能够知道所有的消费者和生产者,除此以外,他还要能够控制消费者的访问权限,不然的话,一个并发数十万的消费者,去访问一个并发不过万级的生产者,程序不就崩了吗.因此,我们需要子*仓库有权限控制.如果再细想的话,并发量控制也是不可缺少的,当消费者的并发突然大过预期时,要避免发送到生产者上去,严重的话可能会导致服务器雪崩.

简单的来讲,就是这些.

说完*控制,就要说说消费者和生产者了,如果每一个消费者都通过*管理去调用生产者的方法,很不现实,这就相当于你本来搭好了集群结果又合并了一样.所以,在生产者和消费者那里,还有要相应的措施,也就是我要介绍的Dubbo去做的事情.

DUBBO

首先是服务调用的问题,上面说道,通过*管理去处理请求会导致请求太过集中.所以,我们要维持RPC的本来面目,即:两个服务器之间直接通过网络访问.所以,*管理只需要去告诉所有的消费者,这些生产者的IP地址、端口号以及可以被调用的服务就可以了.

而对于生产者来说,首先他需要完成一件事,定义接口.而在定义接口的时候,又避免不了方法入参会有实体的介入,所以生产者要将自己的工作分为两部分:一部分是定义接口和类,另一部分是实现接口中的方法.

而生产者自然是要通过*仓库也好,引入Jar包也好,需要先将生产者的接口和类引入,然后通过接口对象去调用对应的方法.而对于之前提到的两个服务器之间直接通过网络去访问,首先对于消费者来说,他要知道有哪些服务以及对应的服务在哪个ip和端口有.所以这个活必须交给*仓库去完成.而*仓库要想知道,只能通过生产者注入的方式完成,毕竟他自己不能监听到局域网内哪里有服务提供.所以,生产者还有个活,那就是将自己的接口和类暴露给仓库,好让仓库转告消费者.

消费者获得接口后,就要去调用它,可是Java中接口是不能实例化对象的,但是它可以作为一个引用,去指向实现了该接口的类对象.而作为一个微服务来讲,肯定不希望消费者自己去创建一个接口的实现,然后在调用方法时,自己去做网络连接,发送数据获取数据以及对象的序列化等.所以,在框架中我们需要将这个接口的实现类,在一开始加载或调用的时候,在内存中创建一个看不到的实现了接口的类对象,这在/shenshaoming/article/details/101621629中讲解的比较清楚,此处就不做过多解释.

那么,先提出几个问题供读者思考:1.当一个生产者宕机时,如何快速的通知消费者.

2.当一个生产者宕机或网络断开后重新上线时,怎么快速的通知消费者.

3.如何控制并发量,避免生产者因为并发过大而宕机.