一、插件概述
插件定位
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 判断插件是否存在且启用:
判断通过,则开始执行该插件处理
- 匹配选择器
- 匹配规则
- 执行自定义处理
- 否则,继续执行插件链处理。
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 实现。