东东
发布于 2024-12-23 / 2 阅读 / 0 评论 / 0 点赞

RPC框架

基础

远程过程调用

是一种协议,允许程序在不同的计算机之间进行通信和交互,就像在调用本地方法一样

RPC允许程序(这里可以理解为服务消费者)像调用自己程序的方法一样,调用另外一个程序(这里可以理解为服务提供者)的接口。

在调用过程中,服务不需要了解数据的传输处理过程、底层网络通信的细节,这些全都有RPC框架统一进行处理。

基础设计

举个例子来分析RPC框架的流程

假设现在有两个web服务A和B,B提供了一个接口可以对外使用。

http请求

如果A想要调用B的接口,由于不在一个服务,如果要用,可以通过HTTP请求的方式进行调用B接口,这是常规思路。

那么当B提供的接口有很多,A想要使用不同的接口时候,是不是每次调用都要构建HTTP请求来做

请求处理器

这时候,为了减少重复代码,我们可以想到,服务提供者可以构建一个请求处理器,通过传入相应的参数,由请求处理器统一处理如何调用接口。而服务调用者统一调用这个请求处理的接口可以,只需要告诉处理器,你要调用的方法名字是什么,对应你传入的参数是什么。

服务注册器

这个时候,请求处理器拿到了要调用的方法的名字以及参数,但是如何去寻找到方法呢?

就需要在服务提供者的内部维护一个映射关系,即对外提供的接口名字和方法所在类的全路径名的映射关系,这样请求处理器通过接口名字找到类的全路径名,就可以通过反射机制调用方法

序列化

由于AB在不同的服务,之间的通信需要进行网络传输,但是JAVA对象本身是不可以进行网络传输的,就需要用到序列化和反序列化的知识。

请求代理

同时,在服务的调用端,为了简化服务调用者请求接口的代码复杂度,可以使用代理对象的形式,调用者只需要按正常调用接口的方式进行调用,由代理对象对其调用进行http包装,发起请求,返回结果。

扩展设计

服务注册发现-注册中心

  • 消费者在调用接口的时候,怎么知道服务提供者所在的地址是什么?

  • 当接口数量非常多的时候,当服务提供者非常多的时候,如何快速的找到哪个接口所在的服务在哪里呢?

  • 当服务的地址发生变化的时候,提供者如何快速知道呢?

这时候可以引入一个第三方来维护这些内容,称为注册中心

  • 当服务提供者服务启动时,将自己的基础信息注册到注册中心

  • 服务消费者调用的时候,可以通过注册中心拿到对应的调用信息

  • 当服务提供者发生变化的时候,也可以通知到注册中心自己的变化,便于提供者调用的时候从注册中心拿到最新的数据进行调用

常用的注册中心:redis、zookeeper、nacos

负载均衡

举个例子,现在有两个服务A和B,A在调用B的接口的时候,如果B服务只有一个实例,那直接调用即可。那如果B服务有多个实例B1-B9呢?A在调用的时候应该用哪个实例呢?

可以有以下几种策略:

  • 轮询:比如说第一次调B1,第二次调B2,依次类推

  • 随机:每次调用的时候,从1-9中随机选一个数字,然后调用对应的服务

  • 权重:可以为每个实例根据情况设置不同的权重,比如性能,那么在调用的时候,根据权重去选择服务实例

容错

如果服务调用失败,应该怎么处理

  • 调用失败后,可以选择性进行重试

  • 重试失败后,可以对服务进行降级处理

其他问题

  • 如果服务提供者的一个节点下线了,如何从注册中心剔除无效节点

  • 服务提供者每次调用的时候都实时从注册中心拉取服务列表吗?可以使用缓存进行性能优化?

  • 服务之间调用采用网络传输,需要考虑如何优化传输的性能?自定义协议?

  • 如何让框架变得易于扩展?SPI机制?