Nacos+OpenFeign请求原理简要分析

Idea Debug断点配置

Idea Debug断点配置

Nacos+OpenFeign请求原理简要分析

  1. 触发自动装配

spring-cloud-commons-3.0.1.jar!/META-INF/spring.factories:5

org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClientAutoConfiguration

CompositeDiscoveryClientAutoConfiguration

  1. 注入容器中的所有DiscoveryClient实例

org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClientAutoConfiguration#compositeDiscoveryClient

org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClientAutoConfiguration#compositeDiscoveryClient
@Configuration(proxyBeanMethods = false)
@AutoConfigureBefore(SimpleDiscoveryClientAutoConfiguration.class)
public class CompositeDiscoveryClientAutoConfiguration {

@Bean
@Primary
public CompositeDiscoveryClient compositeDiscoveryClient(List<DiscoveryClient> discoveryClients) {
return new CompositeDiscoveryClient(discoveryClients);
}

}
  1. 根据服务名称选择一个可用的服务实例

org/springframework/cloud/openfeign/loadbalancer/FeignBlockingLoadBalancerClient.java:88

org.springframework.cloud.loadbalancer.core.DiscoveryClientServiceInstanceListSupplier
@Override
public Response execute(Request request, Request.Options options) throws IOException {
final URI originalUri = URI.create(request.url());
String serviceId = originalUri.getHost();
Assert.state(serviceId != null, "Request URI does not contain a valid hostname: " + originalUri);
String hint = getHint(serviceId);
DefaultRequest<RequestDataContext> lbRequest = new DefaultRequest<>(
new RequestDataContext(buildRequestData(request), hint));
Set<LoadBalancerLifecycle> supportedLifecycleProcessors = LoadBalancerLifecycleValidator
.getSupportedLifecycleProcessors(
loadBalancerClientFactory.getInstances(serviceId, LoadBalancerLifecycle.class),
RequestDataContext.class, ResponseData.class, ServiceInstance.class);
supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onStart(lbRequest));
// 根据服务名称选择一个可用的服务实例
ServiceInstance instance = loadBalancerClient.choose(serviceId, lbRequest);

// 后部分代码省略...
}
  1. 获取指定服务的实例信息,并在规定的超时时间内返回对应的 Flux 序列。如果在超时时间内无法获取到数据或者发生异常,则返回一个空的 Flux 序列

org.springframework.cloud.loadbalancer.core.DiscoveryClientServiceInstanceListSupplier.java:62

org.springframework.cloud.loadbalancer.core.DiscoveryClientServiceInstanceListSupplier
public DiscoveryClientServiceInstanceListSupplier(DiscoveryClient delegate, Environment environment) {
this.serviceId = environment.getProperty(PROPERTY_NAME);
resolveTimeout(environment);
// 获取指定服务的实例信息: delegate.getInstances(serviceId)
this.serviceInstances = Flux.defer(() -> Flux.just(delegate.getInstances(serviceId)))
.subscribeOn(Schedulers.boundedElastic()).timeout(timeout, Flux.defer(() -> {
logTimeout();
return Flux.just(new ArrayList<>());
})).onErrorResume(error -> {
logException(error);
return Flux.just(new ArrayList<>());
});
}
  1. 通过serviceName获取ServiceInstance集合

org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClient#getInstances

org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClient#getInstances
// 第4点中的delegate就是CompositeDiscoveryClient对象实例,也是第2点注入的Bean
@Override
public List<ServiceInstance> getInstances(String serviceId) {
if (this.discoveryClients != null) {
for (DiscoveryClient discoveryClient : this.discoveryClients) {
List<ServiceInstance> instances = discoveryClient.getInstances(serviceId);
if (instances != null && !instances.isEmpty()) {
return instances;
}
}
}
return Collections.emptyList();
}
  1. 根据获取到的服务信息,重新构建请求URL

org/springframework/cloud/openfeign/loadbalancer/FeignBlockingLoadBalancerClient.java:102

org.springframework.cloud.loadbalancer.core.DiscoveryClientServiceInstanceListSupplier
@Override
public Response execute(Request request, Request.Options options) throws IOException {
// 前部分代码省略...

// 根据获取到的服务信息,重新构建请求URL
String reconstructedUrl = loadBalancerClient.reconstructURI(instance, originalUri).toString();
Request newRequest = buildRequest(request, reconstructedUrl);
return executeWithLoadBalancerLifecycleProcessing(delegate, options, newRequest, lbRequest, lbResponse,
supportedLifecycleProcessors);
}
  1. 根据ServiceInstance重新构建请求URL,替换FeignClient中的name等属性

org.springframework.cloud.client.loadbalancer.LoadBalancerUriTools#doReconstructURI

org.springframework.cloud.client.loadbalancer.LoadBalancerUriTools#doReconstructURI
private static URI doReconstructURI(ServiceInstance serviceInstance, URI original) {
String host = serviceInstance.getHost();
String scheme = Optional.ofNullable(serviceInstance.getScheme())
.orElse(computeScheme(original, serviceInstance));
int port = computePort(serviceInstance.getPort(), scheme);

if (Objects.equals(host, original.getHost()) && port == original.getPort()
&& Objects.equals(scheme, original.getScheme())) {
return original;
}

boolean encoded = containsEncodedParts(original);
return UriComponentsBuilder.fromUri(original).scheme(scheme).host(host).port(port).build(encoded).toUri();
}
  1. 最终完成请求,获得响应

org/springframework/cloud/openfeign/loadbalancer/LoadBalancerUtils.java:56

org/springframework/cloud/openfeign/loadbalancer/LoadBalancerUtils.java
static Response executeWithLoadBalancerLifecycleProcessing(Client feignClient, Request.Options options,
Request feignRequest, Request lbRequest,
Response<ServiceInstance> lbResponse,
Set<LoadBalancerLifecycle> supportedLifecycleProcessors, boolean loadBalanced) throws IOException {
supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onStartRequest(lbRequest, lbResponse));
try {
// 最终完成请求,获得响应
Response response = feignClient.execute(feignRequest, options);
if (loadBalanced) {
supportedLifecycleProcessors.forEach(
lifecycle -> lifecycle.onComplete(new CompletionContext<>(CompletionContext.Status.SUCCESS,
lbRequest, lbResponse, buildResponseData(response))));
}
return response;
}
catch (Exception exception) {
if (loadBalanced) {
supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onComplete(
new CompletionContext<>(CompletionContext.Status.FAILED, exception, lbRequest, lbResponse)));
}
throw exception;
}
}