ShenYu是一个异步的,高性能的,跨语言的,响应式的 API 网关。有关ShenYu的介绍可以戳这。
一、前瞻
今天我们尝试不同的代码阅读方式,按模块来去阅读源码,看看效果如何。
本次阅读锁定在shenyu-loadbalancer,根据模块名可以了解这个模块主要作用就是负载均衡。
我们可以根据这个模块的组织机构,来思考本次的阅读线索:
- 整个模块为ShenYu提供了什么功能
- 我们很好奇,负载均衡的cache缓存有什么作用
- spi的作用是什么
二、探索
那开始我们今天的模块阅读。
看起来factory就是这个模块的核心了,作为工厂来生产核心对象,我们就从这个工厂开始阅读。
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又是调用了内部的什么模块去返回?我们接着往下看。
@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的历史查询,发现这个缓存对象被废弃了,最新版本的核心缓存对象应该是下面这两个
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提供了什么功能
。我们可以看下上文我们提到的工厂对象。
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列表,通过这个模块的负载均衡算法,负载均衡地返回其中一个对象。
这也就是这个模块提供的功能。
未完待续。。。
好了,今天的分享就到这🤔。大家能否感受到通过按模块这种方式来阅读源码的乐趣呢 !
创作不易,不妨点赞、收藏、关注支持一下,各位的支持就是我创作的最大动力❤️