【专栏】RPC系列(实战)-摸清RPC骨架

发布于:2023-01-11 ⋅ 阅读:(247) ⋅ 点赞:(0)

学长来引流啦,刚毕业一年,在魔都某大厂,大家可以关注公众号【离心计划】,我会出一些高质量的实战教程,让大家对于技术有更多的了解

 【RPC系列合集】

【专栏】RPC系列(理论)-夜的第一章

【专栏】RPC系列(理论)-协议与序列化

【专栏】RPC系列(理论)-动态代理

| 前言

从这节开始我们进入了Sparrow-RPC系列的实战篇,当我们接触一个新的技术,拒绝盲人摸象,拒绝细节循环,而是先摸清它的骨架,这种方法对于学习任何技术,大到企业级项目如Flink、Dubbo等,小到一个工具如ThreadPoolExecutor等都是适用的,所以作为实战系列第一篇,我们也要先搞清楚实现一个RPC我们需要些什么“配件”才能凑齐一套完整工具。

| 从一个请求开始

相信大家都啃过HashMap的源码,为了了解HashMap的各种原理,它是怎么存储键值对的,是怎么处理哈希冲突的,又是怎么扩容的,我们往往从一个put方法开始就行了,这种方法也叫做”主流法(我瞎取的)。所以我们要想了解RPC的脉络,我们可以从一个简单的应答请求,看看这个请求经过了什么”配件“,我们就知道了大概的一个脉络,也就是常说的:架构

首先,客户端需要知道我们服务的地址,基本的TCP通信四元组(两对ip+端口)至少要知道吧,那问题来了,这个信息是如何知道的?服务端实现了UserService接口的getUserByName后,部署在服务端,服务端就需要把自己的ip地址与端口告诉就客户端才能进行通信,明眼人都知道,两端直接交换这个信息是不可能的,所以就需要一个 注册中心 来管理服务地址这个元信息

这样,客户端就可以拿到注册了UserService的所有地址信息了,那么这时候就需要判断,我到底拿哪个ip去链接呢,这个就涉及到了负载均衡,如何选择地址也就是负载均衡策略,常见的有随机、权重随机、轮询等方法,这部分后续我们会展开,这里只要知道我们需要一个注册中心帮我们提供服务注册服务发现的功能。

我们拿到了服务地址后,就可以进行通信了,之前我们提到过了协议与序列化,这时候就涉及到网络的知识了,还是getUserByName,我们至少需要把函数签名、方法参数组装成我们的数据,按照我们的应用层协议和序列化方式传给对方,那么这个发送的动作我们就需要网络框架来帮我们做掉,总不能自己去经历TCP那套bind、listen、accept,所以Netty就出场了,netty是CS架构,帮我们屏蔽了底层处理连接的繁琐。有了Netty,我们就可以把序列化好的二进制流在Netty的两端进行传输了。

| 很重要却不必需的流程

上面的流程是我们最最最核心的RPC流程,也就是说没有这些功能,RPC无法提供基本服务,但是除了这些核心组件,我们还需要有哪些非核心但很重要的机制呢?那我们简单理一理。

压缩算法。为什么说这个很重要,还记得我们为什么在选择应用层协议时不直接用HTTP1.1,为什么不在选择序列化时用json,看的一目了然,为的就是效率。微服务之间可能涉及到的数据交互会非常频繁且大,因此将我们的数据压缩到更小的空间,能够节省传输的效率。当然压缩数据本身也会有一定损耗,还会占用CPU资源,所以好的压缩算法很重要,读者可以自行去查阅,像Dubbo自定义的协议中已经包含了压缩算法,所以协议头中会携带压缩算法这个控制位标识,详情可见:    

https://dubbo.apache.org/zh/docs/concepts/rpc-protocol/

服务治理。这个就很宽泛了,因为我不想分开来写了,就以服务治理为头吧。服务治理不仅在RPC中,只要是现在的微服务都需要一套服务治理,它包含了:限流、熔断、降级、背压等,这些的目的都是为了一个:保证服务的安全运行。比如A服务调用B服务,B服务依赖C服务,此时C服务因为故障提供服务的能力明显下降,导致处理B的请求大量超时,那么B服务就会有大量请求等待C相应,但是进来的请求依旧不变,然后资源耗尽,导致整个B服务不可能,而B服务可能被D\E\F等服务也在调用,就全链路瘫痪了。所以这里限流指的是当B服务出现大量超时,应该对上游做限流比如一分钟只能把进来一千个请求,当B调用C出现大量超时,可以进行降级,降级是比较笼统的说法,包括了限流和熔断,如果是熔断,表示B直接停止对C的调用,保证自己资源稳定。或者是业务降级,比如返回默认值等方式。而背压是一种动态的限流机制,也就是C服务感觉到自己不行了,就赶紧告诉调用方慢一点,TCP中的滑动窗口就是天然的背压机制。

其实还有很多非核心但很重要的机制,都包含在各个细节中,只有有了这些机制的保护,才能成为一个企业级的应用,后面我们会逐渐展开,比较深入的,我会在番外篇中讲解。

| 代码架构

https://github.com/JAYqq/my-sparrow-rpc

读者可以fork一下项目到自己仓库,然后clone下来,这个只是一个空壳子,为了后续讲解的方便,大家可以统一用这个,或者按照自己的思路来也行。这个壳子分成了五部分:

  • sparrow-rpc-core

包含了我们核心的逻辑,包括netty、序列化、动态代理等

  • sparrow-rpc-client

客户端代码,主要是测试客户端

  • sparrow-rpc-server

服务端,模拟提供服务的一端

  • sparrow-rpc-api

存放一些接口类,提供SPI

  • sparrow-rpc-nameserver

提供服务注册与发现功能

| 小结

本章主要讲解了我们实现一个RPC需要用到哪些核心的组件,以及我们不会涉及到但是必须要知道的非核心但是很重要的机制,其实看似是讲解RPC,但是很多框架都与上面的知识息息相关,比如消息队列同样需要序列化。最后把代码骨架发给了大家,接下来我们会按照模块和功能往里面填,敬请期待把大家~


网站公告

今日签到

点亮在社区的每一天
去签到