【Soul网关探秘】springcloud插件原理

一、插件概述

插件定位

springcloud 插件是一个 springcloud 正向代理插件,所有的 springcloud 请求都由该插件进行负载均衡处理。

生效时机

当请求头的 rpcType = springcloud 且插件启用时,它将根据请求参数匹配规则,最终交由下游插件进行响应式代理调用。

二、插件处理流程

1)先回顾下请求处理类插件的通用流程(AbstractSoulPlugin # execute):

public Mono execute(final ServerWebExchange exchange, final SoulPluginChain chain) {
    // 获取插件数据
    String pluginName = named();
    final PluginData pluginData = BaseDataCache.getInstance().obtainPluginData(pluginName);
    // 插件生效判定
    if (pluginData != null && pluginData.getEnabled()) {
        // 获取选择器数据
        final Collection selectors = BaseDataCache.getInstance().obtainSelectorData(pluginName);
        ...
        // 匹配选择器
        final SelectorData selectorData = matchSelector(exchange, selectors);
        ...
        // 获取规则数据
        final List rules = BaseDataCache.getInstance().obtainRuleData(selectorData.getId());
        ...
        // 匹配规则
        RuleData rule;
        if (selectorData.getType() == SelectorTypeEnum.FULL_FLOW.getCode()) {
            //get last
            rule = rules.get(rules.size() - 1);
        } else {
            rule = matchRule(exchange, rules);
        }
        ...
        // 执行自定义处理
        return doExecute(exchange, chain, selectorData, rule);
    }
    // 继续执行插件链处理
    return chain.execute(exchange);
}

AbstractSoulPlugin 判断插件是否存在且启用:

  • 判断通过,则开始执行该插件处理

    1. 匹配选择器
    2. 匹配规则
    3. 执行自定义处理
  • 否则,继续执行插件链处理。

2)再来看看 springcloud 插件的自定义处理流程(SpringCloudPlugin # doExecute):

protected Mono doExecute(final ServerWebExchange exchange, final SoulPluginChain chain, final SelectorData selector, final RuleData rule) {
    ...
    // 获取规则处理对象
    final SpringCloudRuleHandle ruleHandle = GsonUtils.getInstance().fromJson(rule.getHandle(), SpringCloudRuleHandle.class);
    // 获取选择器处理对象
    final SpringCloudSelectorHandle selectorHandle = GsonUtils.getInstance().fromJson(selector.getHandle(), SpringCloudSelectorHandle.class);
    ...
    // 负载均衡器选择服务实例
    final ServiceInstance serviceInstance = loadBalancer.choose(selectorHandle.getServiceId());
    ...
    // 重建 URI
    final URI uri = loadBalancer.reconstructURI(serviceInstance, URI.create(soulContext.getRealUrl()));
    // 生成真实的 URL
    String realURL = buildRealURL(uri.toASCIIString(), soulContext.getHttpMethod(), exchange.getRequest().getURI().getQuery());
    // 设置真实 url 和超时时间
    exchange.getAttributes().put(Constants.HTTP_URL, realURL);
    exchange.getAttributes().put(Constants.HTTP_TIME_OUT, ruleHandle.getTimeout());
    // 继续执行插件链处理
    return chain.execute(exchange);
}

SpringCloudPlugin 先获取到选择器处理对象,然后使用负载均衡器根据处理对象的服务 id 选择服务实例并重建 URI,据此 URI 生成真实的 URL,最后设置最终的 url 和超时时间交由插件链下游进行处理。

注意:

springcloud 插件自身只是负责根据选择器、规则和注入的负载均衡器选出待分发的服务器实例,并不直接向后端服务发起请求。

三、负载均衡器

springcloud 插件在处理过程中,插件本身并不承担如 divide 插件一般的探活和负载均衡的职责,而是交由一个负载均衡器去处理。

该负载均衡器需要实现 org.springframework.cloud.client.loadbalancer.LoadBalancerClient,官方使用的是 org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient。

3.1 Ribbon 是什么?

Ribbon 是 Netflix 发布的一个开源的客户端负载均衡器,是 SpringCloud-Netflix 中重要的一环,通过它将 Netflix 的中间层服务连接在一起。
Ribbon 客户端组件提供一系列完善的配置项,如连接超时、重试等。简单的说,就是在配置文件中列出 Load Balancer 后面所有的服务,Ribbon 会自动的基于某种规则(如简单轮询,随机连接等)去连接这些服务,也很容易实现自定义的负载均衡算法。

3.2 Ribbon 能干什么?

Ribbon 是在客户端来实现负载均衡的访问服务,主要的功能:

  • 服务发现,发现依赖服务的列表
  • 服务选择规则,在多个服务中如何选择一个有效服务
  • 服务监听,检测失效的服务,高效剔除失效服务

3.3 Ribbon 在插件中的职责

通过集成 ribbon,springcloud 插件可以轻易地实现 springcloud 服务的服务发现及负载均衡策略。

在 springcloud 插件中,ribbon 主要承担以下职责:

  • 服务发现:自动发现依赖的服务列表
  • 服务监听:自动剔除失效服务,维护有效服务列表
  • 服务选择:根据某种规则选择一个有效服务(负载均衡)

四、小结

springcloud 插件通过负载均衡器,实现了对 springcloud 服务的负载均衡,选择出一个有效服务的真实 URL 后,交由插件链下游进行处理。

负载均衡器是 springcloud 插件中至关重要的一环,插件的负载均衡器默认使用 ribbon 实现。

你可能感兴趣的:(java分布式soul)