专栏链接:https://time.geekbang.org/column/intro/100046201
RPC
不仅是微服务的架构基础,只要涉及网络通信,就可能用到RPC
。
什么是RPC
RPC
的全称是:Remote Procedure Call
,即远程过程调用。
RPC
的作用体现在两个方面:
- 屏蔽远程调用跟本地调用的差异,让用户像调用本地一样去调用远程方法。
- 隐藏底层网络通信的复杂性,让用户更专注于业务逻辑。
RPC通信流程
RPC
是一个远程调用,因此必然需要通过网络传输数据,且RPC
常用于业务系统之间的数据交互,需要保证其可靠性。
- 所以
RPC
一般默认采用 TCP协议来传输。网络传输数据是二进制数据,因此请求方需要将请求参数转为二进制数据,即序列化。
响应方接受到请求,要将二进制数据转换为请求参数,需要反序列化。
请求方和响应方识别彼此的信息,需要约定好彼此数据的格式,即协议。
大多数的协议会分成两部分,分别是数据头和消息体。
- 数据头一般用于身份识别,包括协议标识、数据大小、请求类型、序列化类型等信息。
- 消息体主要是请求的业务参数信息和扩展属性等。
为了屏蔽底层通信细节,使用户聚焦自身业务,因此
RPC
框架一般引入了动态代理。
- 通过依赖注入等技术,拦截方法调用,完成远程调用的通信逻辑。
动态代理
动态代理可以帮用户屏蔽远程调用的细节,实现像调用本地一样地调用远程的体验。
JDK
支持的动态代理方式是通过实现InvocationHandler
接口。
- 它要求被代理的类只能是接口。
有性能问题,它生成后的代理类是使用反射来完成方法调用的,而这种方式相对直接用编码调用来说,性能会降低。
JavasSist
的是通过控制底层字节码来实现动态代理,不需要反射完成调用,所以性能比JDK
的动态代理方式性能要好。
负载均衡
RPC
的服务调用者会与 注册中心 下发的所有服务节点建立长连接。在每次发起
RPC
调用时,服务调用者都会通过配置的负载均衡插件,自主选择一个服务节点,发起RPC
调用请求。
异常重试
当调用端发起的请求失败时,
RPC
框架自身可以进行重试,再重新发送请求,用户可以自行设置是否开启重试以及重试的次数。