RPC框架(5)—— 路由层的实现

348 阅读4分钟

前言:上一节中,我们在注册中心中保存了诸多服务提供者地ip端口号,但是在客户端申请链接的时候,要链接到哪一个服务端呢 ?

路由层的存在意义 :通过一套负载均衡算法,计算出合适的服务提供方,然后发起网络调用,为客户端选择一个合适的服务端。

  • 抽象一个路由层的方法 需要有三个方法:刷新路由数组,获取到请求链接通道,更新权重信息

image.png

  • 随机调用方法 不推荐使用简单暴力Random函数,因为它的性能比较差,具体原因,可以看其他的博客,之后我再自己总结一下。

可以换一种方式来实现随机顺序查询:提前定义好需要调用的服务提供者顺序,然后根据这个随机顺序去做轮询,伪随机,但是效果是一样的

设置一个refreshRouteArr,在客户端与服务端提供者建立链接的环节,触发路由层的这个函数,生成一个有顺序的随机数组,并将其放入到一个map集合中。

image.png

image.png

随机路由层的对外暴漏核心方法:Select函数,每次调用外界服务的时候,都要通过这个函数去获取自己对应的那个服务端。

Map集合中,按照服务的key查询对应的服务调用顺序数组,通过取模运算,可以实现轮询效果

因为每个服务端的性能不相同,可以实现通过设置权值来实现

  • 注册一个服务端节点监听器

image.png

  • 轮询策略

image.png

此时,已经完全定义好了路由层的具体实现,其中包括了随即路由和轮询路由两大类,之后,在客户端启动类的入口处添加上路由层的初始化操作,就可以将他们联系在一起了。

image.png

image.png

扩展: 负载均衡算法

1 随机算法

1.1 简单随机算法

1.2 加权随机算法V1

每个服务器按照它所对应的权值进行复制,当某个节点的权值比较大的时候,浪费内存

1.3 加权随机算法V2

不用复制的方法,而通过区间来表示。性能好的、权值大的,所占据的区间也大一些,所以被调用的机会也就多一些

2 轮询算法

2.1 简单轮询算法

没啥好说的 ,当索引大于size的时候,就重置

2.2 加权轮询算法

  • AAAAABC这种的 ,做一下优化 : 将权重值平铺到一位作标系中,对总权重取余,获得offset

2.3 平滑加权轮询算法

  • 每个服务器对应两个权重,分别为weight和currentWeight。其中weight是固定的,currentWeight会动态调整,初始值为0
  • 当有新的请求进来时,遍历服务器列表,让它的currentWeight加上自身权重,遍历完成后,找到最大的currentWeight。
  • 将最大的currentWeight减去权重总和,然后返回相应的服务器即可。 经过处理后,服务器排序变为:AABACAA,相较于之前,更均匀了

3 一致性hash算法

根据请求路径,算出hash值,再将其映射到一个ip地址,
可以做到使相同的请求落到同一个服务器上。

由于客户端发起的请求是无穷大的,不是所有的hash值都能映射到服务器ip上,所以使用hash环进行处理。

image.png 但是四个节点不一定能均匀分布,尤其时某些节点宕机之后,更不公平了。

为了解决这个问题,可以加入诸多虚拟节点,使环更加平衡

image.png

4 最小活跃数算法

上面只考虑到了使调用次数尽可能均衡,但是却没考虑每次调用的时间
如果要考虑上时间的话 ,可以使用最小活跃数算法

每个服务提供者对应一个活跃数。初始情况下,所有服务提供者活跃数均为0。每 收到一个请求,活跃数加1,完成请求后则将活跃数减1。

再运行一段时间后,性能好的服务提供者处理请求的速度快,活跃数下降的也快,可以优先获得新的请求。

最小活跃数算法 = 甲醛算法 + 最小活跃数

图来自于:juejin.cn/post/699221…