一、插件概述

插件定位

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

生效时机

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

二、插件处理流程

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

  1. public Mono<Void> execute(final ServerWebExchange exchange, final SoulPluginChain chain) {
  2. // 获取插件数据
  3. String pluginName = named();
  4. final PluginData pluginData = BaseDataCache.getInstance().obtainPluginData(pluginName);
  5. // 插件生效判定
  6. if (pluginData != null && pluginData.getEnabled()) {
  7. // 获取选择器数据
  8. final Collection<SelectorData> selectors = BaseDataCache.getInstance().obtainSelectorData(pluginName);
  9. ...
  10. // 匹配选择器
  11. final SelectorData selectorData = matchSelector(exchange, selectors);
  12. ...
  13. // 获取规则数据
  14. final List<RuleData> rules = BaseDataCache.getInstance().obtainRuleData(selectorData.getId());
  15. ...
  16. // 匹配规则
  17. RuleData rule;
  18. if (selectorData.getType() == SelectorTypeEnum.FULL_FLOW.getCode()) {
  19. //get last
  20. rule = rules.get(rules.size() - 1);
  21. } else {
  22. rule = matchRule(exchange, rules);
  23. }
  24. ...
  25. // 执行自定义处理
  26. return doExecute(exchange, chain, selectorData, rule);
  27. }
  28. // 继续执行插件链处理
  29. return chain.execute(exchange);
  30. }

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

  • 判断通过,则开始执行该插件处理
    1. 匹配选择器
    2. 匹配规则
    3. 执行自定义处理
  • 否则,继续执行插件链处理。

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

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

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 实现。