soul网关springCloud插件的http调用与divide插件的调用过程基本相似,具体可见 soul网关学习五之divide插件的http调用 ,只是在进行负载均衡与获取实际调用下游真实服务地址时使用springCloud的LoadBalancerClient
获取。
1.请求先通过GlobalPlugin
全局插件设置 soulContext
2.通过AbstractSoulPlugin.execute()
获取到匹配的selector与rule
3.再调用SpringCloudPlugin.doExecute()
方法获取springCloud的配置
protected Mono<Void> doExecute(final ServerWebExchange exchange, final SoulPluginChain chain, final SelectorData selector, final RuleData rule) {
if (Objects.isNull(rule)) {
return Mono.empty();
}
// 获取 soulContext
final SoulContext soulContext = exchange.getAttribute(Constants.CONTEXT);
assert soulContext != null;
// 获取 rule
final SpringCloudRuleHandle ruleHandle = GsonUtils.getInstance().fromJson(rule.getHandle(), SpringCloudRuleHandle.class);
// 获取 select
final SpringCloudSelectorHandle selectorHandle = GsonUtils.getInstance().fromJson(selector.getHandle(), SpringCloudSelectorHandle.class);
if (StringUtils.isBlank(selectorHandle.getServiceId()) || StringUtils.isBlank(ruleHandle.getPath())) {
Object error = SoulResultWrap.error(SoulResultEnum.CANNOT_CONFIG_SPRINGCLOUD_SERVICEID.getCode(), SoulResultEnum.CANNOT_CONFIG_SPRINGCLOUD_SERVICEID.getMsg(), null);
return WebFluxResultUtils.result(exchange, error);
}
// 通过 RibbonLoadBalancerClient 获取要使用的下游服务id
final ServiceInstance serviceInstance = loadBalancer.choose(selectorHandle.getServiceId());
if (Objects.isNull(serviceInstance)) {
Object error = SoulResultWrap.error(SoulResultEnum.SPRINGCLOUD_SERVICEID_IS_ERROR.getCode(), SoulResultEnum.SPRINGCLOUD_SERVICEID_IS_ERROR.getMsg(), null);
return WebFluxResultUtils.result(exchange, error);
}
// 获取实际调用的 url
final URI uri = loadBalancer.reconstructURI(serviceInstance, URI.create(soulContext.getRealUrl()));
String realURL = buildRealURL(uri.toASCIIString(), soulContext.getHttpMethod(), exchange.getRequest().getURI().getQuery());
exchange.getAttributes().put(Constants.HTTP_URL, realURL);
//set time out.
exchange.getAttributes().put(Constants.HTTP_TIME_OUT, ruleHandle.getTimeout());
return chain.execute(exchange);
}
4.调用WebClientPlugin.execute()
方法实际调用下游真实服务
5.最后WebClientResponsePlugin
插件来处理下游服务的response