【Apache ShenYu源码】如何实现负载均衡模块设计

ShenYu是一个异步的,高性能的,跨语言的,响应式的 API 网关。有关ShenYu的介绍可以戳这

一、前瞻

今天我们尝试不同的代码阅读方式,按模块 来去阅读源码,看看效果如何。

本次阅读锁定在shenyu-loadbalancer ,根据模块名可以了解这个模块主要作用就是负载均衡

我们可以根据这个模块的组织机构,来思考本次的阅读线索

  1. 整个模块为ShenYu提供了什么功能
  2. 我们很好奇,负载均衡的cache缓存有什么作用
  3. spi的作用是什么

二、探索

那开始我们今天的模块阅读。

看起来factory就是这个模块的核心了,作为工厂来生产核心对象,我们就从这个工厂开始阅读。

java 复制代码
public final class LoadBalancerFactory {

    private LoadBalancerFactory() {
    }

    /**
     * Selector upstream.
     *
     * @param upstreamList the upstream list
     * @param algorithm    the loadBalance algorithm
     * @param ip           the ip
     * @return the upstream
     */
    public static Upstream selector(final List<Upstream> upstreamList, final String algorithm, final String ip) {
        LoadBalancer loadBalance = ExtensionLoader.getExtensionLoader(LoadBalancer.class).getJoin(algorithm);
        return loadBalance.select(upstreamList, ip);
    }
}

很明显LoadBalancerFactory是作为外部的调用中心,那LoadBalancerFactory又是调用了内部的什么模块去返回?我们接着往下看。

java 复制代码
@SPI
public interface LoadBalancer {

    /**
     * this is select one for upstream list.
     *
     * @param upstreamList upstream list
     * @param ip ip
     * @return upstream
     */
    Upstream select(List<Upstream> upstreamList, String ip);
}

可以看到通过select方法进行调用内部方法。

我们可以看下这个接口类的类图,看下调用的最终实现者是什么对象。

类图很清晰地告诉我们,最终实现者共有6个子类对象,也就是说每个子类对象都是不同的负载均衡算法实现

大家有没看到类图最上面的底层接口SPI,和模块里的spi文件夹是相对应的 ,spi的作用就是存储各种负载均衡算法的实现。那我们就解决了我们的阅读线索3。

spi的作用是什么

我们继续探索,看看阅读线索2的答案:

负载均衡的cache缓存有什么作用

查询代码发现缓存对象是UPSTREAM_MAP,但很奇怪这个核心的缓存对象只有删除、设置的引用,却没有使用的逻辑。

通过Git的历史查询,发现这个缓存对象被废弃了,最新版本的核心缓存对象应该是下面这两个

java 复制代码
    private final Map<String, List<Upstream>> healthyUpstream = Maps.newConcurrentMap();

    private final Map<String, List<Upstream>> unhealthyUpstream = Maps.newConcurrentMap();

找到了核心缓存对象,我们就来看看这个cache对象的作用究竟是什么。

我们看看调用缓存的对应方法。

Upstream流从shenyu-loadbalancer 取出,需要负载均衡时把该缓存传入。也就是说这个模块的cache充当了存储所有Upstream流的作用。

到这我们就解决了阅读线索2的问题了。

三、总结

而阅读线索3也显而易见:整个模块为ShenYu提供了什么功能。我们可以看下上文我们提到的工厂对象。

java 复制代码
public final class LoadBalancerFactory {

    private LoadBalancerFactory() {
    }

    /**
     * Selector upstream.
     *
     * @param upstreamList the upstream list
     * @param algorithm    the loadBalance algorithm
     * @param ip           the ip
     * @return the upstream
     */
    public static Upstream selector(final List<Upstream> upstreamList, final String algorithm, final String ip) {
        LoadBalancer loadBalance = ExtensionLoader.getExtensionLoader(LoadBalancer.class).getJoin(algorithm);
        return loadBalance.select(upstreamList, ip);
    }
}

核心方法很清晰,我们传入Upsteam列表,通过这个模块的负载均衡算法,负载均衡地返回其中一个对象。

这也就是这个模块提供的功能。

未完待续。。。

好了,今天的分享就到这🤔。大家能否感受到通过按模块这种方式来阅读源码的乐趣呢

创作不易,不妨点赞、收藏、关注支持一下,各位的支持就是我创作的最大动力❤️

相关推荐
Ai 编码助手5 小时前
在 Go 语言中如何高效地处理集合
开发语言·后端·golang
小丁爱养花5 小时前
Spring MVC:HTTP 请求的参数传递2.0
java·后端·spring
Channing Lewis5 小时前
什么是 Flask 的蓝图(Blueprint)
后端·python·flask
轩辕烨瑾6 小时前
C#语言的区块链
开发语言·后端·golang
栗豆包8 小时前
w175基于springboot的图书管理系统的设计与实现
java·spring boot·后端·spring·tomcat
萧若岚9 小时前
Elixir语言的Web开发
开发语言·后端·golang
Channing Lewis9 小时前
flask实现重启后需要重新输入用户名而避免浏览器使用之前已经记录的用户名
后端·python·flask
Channing Lewis9 小时前
如何在 Flask 中实现用户认证?
后端·python·flask
一只爱吃“兔子”的“胡萝卜”10 小时前
2.Spring-AOP
java·后端·spring
AI向前看10 小时前
PHP语言的软件工程
开发语言·后端·golang