回顾前天写的divide插件文章:Soul-源码阅读5-回顾总结插件相关
那天做了总结并分析了AbstractSoulPlugin方法(主要是选择器和规则
的设定)。
今天深入看了divide插件是怎么根据selector和rule进行http请求的代理转发的。
DividePlugin
看之类DividePlugin
的doExecute
()方法
-
根据选择器id获取selector配置的服务地址list, 如果为空会抛出NPE.
final List<DivideUpstream> upstreamList = UpstreamCacheManager.getInstance().findUpstreamListBySelectorId(selector.getId()); if (CollectionUtils.isEmpty(upstreamList)) { log.error("divide upstream configuration error: {}", rule.toString()); Object error = SoulResultWrap.error(SoulResultEnum.CANNOT_FIND_URL.getCode(), SoulResultEnum.CANNOT_FIND_URL.getMsg(), null); return WebFluxResultUtils.result(exchange, error); }
-
根据selector配置的负载均衡策略、业务地址和请求IP,决定将http请求代理到哪个业务地址(具体可看
AbstractLoadBalance
的doSelect
())。
DivideUpstream divideUpstream = LoadBalanceUtils.selector(upstreamList, ruleHandle.getLoadBalance(), ip); if (Objects.isNull(divideUpstream)) { log.error("divide has no upstream"); Object error = SoulResultWrap.error(SoulResultEnum.CANNOT_FIND_URL.getCode(), SoulResultEnum.CANNOT_FIND_URL.getMsg(), null); return WebFluxResultUtils.result(exchange, error); }
-
构建真实调用的业务地址url(buildRealURL)。
String domain = buildDomain(divideUpstream); String realURL = buildRealURL(domain, soulContext, exchange);
-
把上面3获得真实URL、超时时间、重试次数放到
ServerWebExchange
的attribute
里。// set the http url、timeout、retry exchange.getAttributes().put(Constants.HTTP_URL, realURL); exchange.getAttributes().put(Constants.HTTP_TIME_OUT, ruleHandle.getTimeout()); exchange.getAttributes().put(Constants.HTTP_RETRY, ruleHandle.getRetry());
WebClientPlugin
从exchange里面取出了URL、超时时间、重试次数(urlPath、timeout、和retryTimes),并发送了http请求(代理到业务服务去)。
public Mono<Void> execute(final ServerWebExchange exchange, final SoulPluginChain chain) {
final SoulContext soulContext = exchange.getAttribute(Constants.CONTEXT);
assert soulContext != null;
String urlPath = exchange.getAttribute(Constants.HTTP_URL);
。。。
long timeout = (long) Optional.ofNullable(exchange.getAttribute(Constants.HTTP_TIME_OUT)).orElse(3000L);
int retryTimes = (int) Optional.ofNullable(exchange.getAttribute(Constants.HTTP_RETRY)).orElse(0);
log.info("The request urlPath is {}, retryTimes is {}", urlPath, retryTimes);
HttpMethod method = HttpMethod.valueOf(exchange.getRequest().getMethodValue());
WebClient.RequestBodySpec requestBodySpec = webClient.method(method).uri(urlPath);
return handleRequestBody(requestBodySpec, exchange, timeout, retryTimes, chain);
}