说明
- 本文将探讨 Apache ShenYu 网关的 springCloud插件的底层原理
- 本文不再讨论 springCloud 项目如何接入 shenyu 网关,shenyu-bootstrap 关于springCloud 插件的引入,shenyu-admin 开启插件等;详情可参考 Apache ShenYu 官方examples体验系列文章
springCloud插件底层原理分析
插件说明
springCloud插件提供了http访问springCloud微服务的功能。
源码解析
在 shenyu-spring-boot-starter-plugin-springcloud pom文件得知,该插件引入了 spring-cloud-commons以及spring-cloud-starter-netflix-ribbon组件,它会默认注入负载均衡等核心bean。
接下来我们分析SpringCloudPlugin插件的核心代码,它的核心逻辑是,进入该插件后获取选择器和规则信息,然后做相关判断。条件满足后,根据选择器的关联信息去得到上游服务注册到 eureka注册中心的 serviceId,用LoadBalancerClient.choose(serviceId) 负载均衡获取可用服务,并取出可用服务的uri,最后用spring-web 通过该 uri 去访问目标服务。核心代码如下:
public class SpringCloudPlugin extends AbstractShenyuPlugin {
……
@Override
protected Mono<Void> doExecute(final ServerWebExchange exchange, final ShenyuPluginChain chain, final SelectorData selector, final RuleData rule) {
……
//根据serviceId从springCloud负载均衡器里获取上游服务s
final ServiceInstance serviceInstance = loadBalancer.choose(selectorHandle.getServiceId());
if (Objects.isNull(serviceInstance)) {
Object error = ShenyuResultWrap.error(ShenyuResultEnum.SPRINGCLOUD_SERVICEID_IS_ERROR.getCode(), ShenyuResultEnum.SPRINGCLOUD_SERVICEID_IS_ERROR.getMsg(), null);
return WebFluxResultUtils.result(exchange, error);
}
//从上游服务中获取上游服务的 uri
final URI uri = loadBalancer.reconstructURI(serviceInstance, URI.create(shenyuContext.getRealUrl()));
//构造上游服务的完整url
String realURL = buildRealURL(uri.toASCIIString(), shenyuContext.getHttpMethod(), exchange.getRequest().getURI().getQuery());
exchange.getAttributes().put(Constants.HTTP_URL, realURL);
//设置超时时间
exchange.getAttributes().put(Constants.HTTP_TIME_OUT, ruleHandle.getTimeout());
//用 spring-web 去请求上游服务
return chain.execute(exchange);
}
}