读Spring-Cloud-Gateway源码收获

读Spring-Cloud-Gateway源码收获

  1. 当初始化类的成员变量时,如果操作比较复杂,可以这样写。通过一个private函数来返回你想要的东西

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    /**
    * List of filter definitions that are applied to every route.
    */
    private List<FilterDefinition> defaultFilters = loadDefaults();

    private ArrayList<FilterDefinition> loadDefaults() {
    ArrayList<FilterDefinition> defaults = new ArrayList<>();
    FilterDefinition definition = new FilterDefinition();
    definition.setName(normalizeFilterName(RemoveNonProxyHeadersGatewayFilterFactory.class));
    defaults.add(definition);
    return defaults;
    }
  2. Spring-Cloud-Gateway中为什么要用响应式编程?

  3. 通过配置来生成一个东西的时候,可以用这种方式。比如这里的RouteDefinition => Route ,前者是管理配置route的,后者是实现的route。而且可以抽象出一个接口,然后实现具体的类实现接口,比如从文件获取配置、从mysql数据库获取配置,从zookeeper、etcd获取配置。

  4. 接口为什么可以多继承?因为接口全都是抽象方法继承谁都无所谓,所以接口可以继承多个接口。注意:类实现接口的时候一定要写明public,要不默认的protected,相当于缩小了方法的使用范围。接口中如果返回类型不是void,则实现类一定要有return。

  5. synchronizedMap(new LinkedHashMap<String, RouteDefinition>()); LHM不是线程安全的哦!

  6. 什么时候用对象,什么时候new就好,就像这个亚子

    1
    2
    3
    4
    5
    RouteDefinition routeDefinition = new RouteDefinition();
    // 设置 ID
    routeDefinition.setId(this.routeIdPrefix + serviceId);
    // 设置 URI
    routeDefinition.setUri(URI.create("lb://" + serviceId));
  7. 如果想创建一个东西,可以通过静态内部类builder的方式,比如这里的build route

  8. 当实现方法变换多端时,可以通过一个委托模式来收集,这样能提供一个统一的入口。比如org.springframework.cloud.gateway.route.CompositeRouteLocator ,组合多种 RouteLocator 的实现类,为 RoutePredicateHandlerMapping 提供统一入口访问路由。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    public class CompositeRouteLocator implements RouteLocator {

    private final Flux<RouteLocator> delegates;

    public CompositeRouteLocator(Flux<RouteLocator> delegates) {
    this.delegates = delegates;
    }

    @Override
    public Flux<Route> getRoutes() {
    return this.delegates.flatMap(RouteLocator::getRoutes);
    }
    }
  9. AtomicReference无锁的对象引用

    1
    2
    3
    4
    /**
    * 路由缓存
    */
    private final AtomicReference<List<Route>> cachedRoutes = new AtomicReference<>();

这里为什么需要用无锁的对象引用呢?

  1. java里没有tuple,在spring库里实现了一个,https://docs.spring.io/spring-xd/docs/0.1.x-SNAPSHOT/reference/html/_tuples.html

  2. 有关HTTP Security headers的一篇文章
    https://blog.appcanary.com/2017/http-security-headers.html

  3. 搭建一个 WebSocket 服务可以使用wscat。npm install -g wscat

  4. Hystrix 基于 RxJava ,而SpringCloudGateWay中的 GatewayFilter 基于 Reactor 。未来,Hystrix也会基于Reactor。

  5. 限流算法

  • 漏桶算法
    有一个漏水的桶,肯定是以一定不变的速度漏水吧,当水桶满了,水就溢出去了,可以看出漏桶算法能强行限制数据的传输速率。这里的“桶”是用来buffer请求的。

  • 令牌桶算法
    对于很多应用场景来说,除了要求能够限制数据的平均传输速率外,还要求允许某种程度的突发传输。这时候漏桶算法可能就不合适了,令牌桶算法更为适合。这个是以一定的速度往桶里放令牌,那我取令牌的速度快一点就可以应对这种突发传输的情况。而令牌桶里的“桶”来计量可用资源数量(令牌)的。虽然我们并不会创建令牌实体,但是仍然可以假想,这个桶内每隔X时间就会新增一定数量的令牌,如果没有请求申请令牌,那么这个令牌桶是会溢出的。

令牌桶成了buffer,如果请求密度低,或者处于冷却状态,那么令牌桶就会溢满,此后如果流量突发,则过去积累的结余资源则可以直接被“借用”。
https://juejin.im/post/5d1c978d51882555433429e6

  1. 基于令牌桶算法的限流的特点:让流量平稳,而不是瞬间流量。1000 QPS 相对平均的分摊在这一秒内,而不是第 1 ms 999 请求,后面 999 ms 0 请求。

  2. 可以通过Redis Lua 脚本,实现基于令牌桶算法实现限流。不会有并发问题吗?不会,因为redis是单线程的啊。


读SOFA_RPC源码收获


Motan 源码学习(比dubbo轻量)

其他源码荟萃

-------------本文结束感谢您的阅读-------------