Feign源码解析

注入容器过程

一、EnableFeignClients 入口

开启Feign使用注解EnableFeignClients ,进入EnableFeignClients ,
与大多数集成Spring的框架一样,使用@Import方式实现ImportBeanDefinitionRegistrar进行对接(Mybatis等也是如此)。

另外可以通过spring.factories查看入口

org.springframework.cloud.openfeign.hateoas.FeignHalAutoConfiguration,\
org.springframework.cloud.openfeign.FeignAutoConfiguration,\
org.springframework.cloud.openfeign.encoding.FeignAcceptGzipEncodingAutoConfiguration,\
org.springframework.cloud.openfeign.encoding.FeignContentGzipEncodingAutoConfiguration,\
org.springframework.cloud.openfeign.loadbalancer.FeignLoadBalancerAutoConfiguration

此处FeignClientsRegistrar实现了ImportBeanDefinitionRegistrar接口。

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
//Spring bean注入方式之一
@Import({FeignClientsRegistrar.class})
public @interface EnableFeignClients {
    String[] value() default {};

    String[] basePackages() default {};

    Class<?>[] basePackageClasses() default {};

    Class<?>[] defaultConfiguration() default {};

    Class<?>[] clients() default {};
}

二、FeignClientsRegistrar 注入Bean

注入bean主要有一下几步:
1、获取注解信息,扫包下的@FeignClient 接口
2、根据扫描的信息,生成bean定义
3、创建FeignClientFactoryBean(FactoryBean实现)类信息
4、把bean定义注入到Spring容器(回调中通过FactortBean.getObject创建真实bean即代理对象)

class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {
    ...
    
	//Spring注册@EnableFeignClients 后会回调此处(详细了解@Import)
    public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
    	//注入配置类FeignClientSpecification
        this.registerDefaultConfiguration(metadata, registry);
        //注入扫描包下的@FeignClient的接口
        this.registerFeignClients(metadata, registry);
    }
	//注入配置类FeignClientSpecification
    private void registerDefaultConfiguration(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        Map<String, Object> defaultAttrs = metadata.getAnnotationAttributes(EnableFeignClients.class.getName(), true);
        if (defaultAttrs != null && defaultAttrs.containsKey("defaultConfiguration")) {
            String name;
            if (metadata.hasEnclosingClass()) {
                name = "default." + metadata.getEnclosingClassName();
            } else {
                name = "default." + metadata.getClassName();
            }

            this.registerClientConfiguration(registry, name, defaultAttrs.get("defaultConfiguration"));
        }

    }

	//循环注入@FeignClient 接口bean
    public void registerFeignClients(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
        LinkedHashSet<BeanDefinition> candidateComponents = new LinkedHashSet();
        Map<String, Object> attrs = metadata.getAnnotationAttributes(EnableFeignClients.class.getName());
        Class<?>[] clients = attrs == null ? null : (Class[])((Class[])attrs.get("clients"));
        if (clients != null && clients.length != 0) {
            Class[] var12 = clients;
            int var14 = clients.length;

            for(int var16 = 0; var16 < var14; ++var16) {
                Class<?> clazz = var12[var16];
                candidateComponents.add(new AnnotatedGenericBeanDefinition(clazz));
            }
        } else {
            ClassPathScanningCandidateComponentProvider scanner = this.getScanner();
            scanner.setResourceLoader(this.resourceLoader);
            scanner.addIncludeFilter(new AnnotationTypeFilter(FeignClient.class));
            Set<String> basePackages = this.getBasePackages(metadata);
            Iterator var8 = basePackages.iterator();

            while(var8.hasNext()) {
                String basePackage = (String)var8.next();
                candidateComponents.addAll(scanner.findCandidateComponents(basePackage));
            }
        }

        Iterator var13 = candidateComponents.iterator();

        while(var13.hasNext()) {
            BeanDefinition candidateComponent = (BeanDefinition)var13.next();
            if (candidateComponent instanceof AnnotatedBeanDefinition) {
                AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition)candidateComponent;
                AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
                Assert.isTrue(annotationMetadata.isInterface(), "@FeignClient can only be specified on an interface");
                Map<String, Object> attributes = annotationMetadata.getAnnotationAttributes(FeignClient.class.getCanonicalName());
                String name = this.getClientName(attributes);
                //注入配置类FeignClientSpecification(一个@FeignClient对应一个)
                this.registerClientConfiguration(registry, name, attributes.get("configuration"));
                //注入@FeignClient接口代理bean
                this.registerFeignClient(registry, annotationMetadata, attributes);
            }
        }

    }

	//注入@FeignClient (与mybatis类似,有细微不同,mybatis直接注入FactoryBean),然后在FactoryBean.getObject() 获取动态代理类注入到Spring容器中
    private void registerFeignClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
    	//@FeignClient 接口
        String className = annotationMetadata.getClassName();
        Class clazz = ClassUtils.resolveClassName(className, (ClassLoader)null);
        ConfigurableBeanFactory beanFactory = registry instanceof ConfigurableBeanFactory ? (ConfigurableBeanFactory)registry : null;
        String contextId = this.getContextId(beanFactory, attributes);
        String name = this.getName(attributes);
        //FeignClientFactoryBean 实现FactoryBean,FactoryBean是一种特殊的bean,在注入到Spring时Spring会通过getObjct获取真实的Bean,此类后续会分析。
        FeignClientFactoryBean factoryBean = new FeignClientFactoryBean();
        factoryBean.setBeanFactory(beanFactory);
        factoryBean.setName(name);
        factoryBean.setContextId(contextId);
        //类文件
        factoryBean.setType(clazz);
        factoryBean.setRefreshableClient(this.isClientRefreshEnabled());
        //生成bean定义,在回调中生成bean
        BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(clazz, () -> {
            factoryBean.setUrl(this.getUrl(beanFactory, attributes));
            factoryBean.setPath(this.getPath(beanFactory, attributes));
            factoryBean.setDecode404(Boolean.parseBoolean(String.valueOf(attributes.get("decode404"))));
            Object fallback = attributes.get("fallback");
            if (fallback != null) {
                factoryBean.setFallback(fallback instanceof Class ? (Class)fallback : ClassUtils.resolveClassName(fallback.toString(), (ClassLoader)null));
            }

            Object fallbackFactory = attributes.get("fallbackFactory");
            if (fallbackFactory != null) {
                factoryBean.setFallbackFactory(fallbackFactory instanceof Class ? (Class)fallbackFactory : ClassUtils.resolveClassName(fallbackFactory.toString(), (ClassLoader)null));
            }
			//此处获取真实的bean(该bean其实是一个Proxy java动态代理)
            return factoryBean.getObject();
        });
        definition.setAutowireMode(2);
        //设置懒加载
        definition.setLazyInit(true);
        this.validate(attributes);
        //构建起模式获取 bean定义
        AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();
        beanDefinition.setAttribute("factoryBeanObjectType", className);
        beanDefinition.setAttribute("feignClientsRegistrarFactoryBean", factoryBean);
        boolean primary = (Boolean)attributes.get("primary");
        beanDefinition.setPrimary(primary);
        String[] qualifiers = this.getQualifiers(attributes);
        if (ObjectUtils.isEmpty(qualifiers)) {
            qualifiers = new String[]{contextId + "FeignClient"};
        }
		//bean定义包装器
        BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className, qualifiers);
        //注入Spring容器
        BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
        this.registerOptionsBeanDefinition(registry, contextId);
    }
    //获取扫描的包名
    protected Set<String> getBasePackages(AnnotationMetadata importingClassMetadata) {
        Map<String, Object> attributes = importingClassMetadata.getAnnotationAttributes(EnableFeignClients.class.getCanonicalName());
        Set<String> basePackages = new HashSet();
        String[] var4 = (String[])((String[])attributes.get("value"));
        int var5 = var4.length;

        int var6;
        String pkg;
        for(var6 = 0; var6 < var5; ++var6) {
            pkg = var4[var6];
            if (StringUtils.hasText(pkg)) {
                basePackages.add(pkg);
            }
        }

        var4 = (String[])((String[])attributes.get("basePackages"));
        var5 = var4.length;

        for(var6 = 0; var6 < var5; ++var6) {
            pkg = var4[var6];
            if (StringUtils.hasText(pkg)) {
                basePackages.add(pkg);
            }
        }

        Class[] var8 = (Class[])((Class[])attributes.get("basePackageClasses"));
        var5 = var8.length;

        for(var6 = 0; var6 < var5; ++var6) {
            Class<?> clazz = var8[var6];
            basePackages.add(ClassUtils.getPackageName(clazz));
        }

        if (basePackages.isEmpty()) {
            basePackages.add(ClassUtils.getPackageName(importingClassMetadata.getClassName()));
        }

        return basePackages;
    }

    //获取feign的中实例id
    private String getClientName(Map<String, Object> client) {
        if (client == null) {
            return null;
        } else {
            String value = (String)client.get("contextId");
            if (!StringUtils.hasText(value)) {
                value = (String)client.get("value");
            }

            if (!StringUtils.hasText(value)) {
                value = (String)client.get("name");
            }

            if (!StringUtils.hasText(value)) {
                value = (String)client.get("serviceId");
            }

            if (StringUtils.hasText(value)) {
                return value;
            } else {
                throw new IllegalStateException("Either 'name' or 'value' must be provided in @" + FeignClient.class.getSimpleName());
            }
        }
    }

	//注入FeignClientSpecification,后续在构建FeignContext 时需要用到
    private void registerClientConfiguration(BeanDefinitionRegistry registry, Object name, Object configuration) {
       //Bean定义构建创建FeignClientSpecification
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FeignClientSpecification.class);
        builder.addConstructorArgValue(name);
        builder.addConstructorArgValue(configuration);
        //注入FeignClientSpecification
        registry.registerBeanDefinition(name + "." + FeignClientSpecification.class.getSimpleName(), builder.getBeanDefinition());
    }
}

三、FeignClientFactoryBean实现bean创建

1、通过FeignContext 构造Builder
2、如果@FeignClient中url不为空,那么走直接Client.Default直接http调用
3、如果@FeignClient中url为空,那么走负载均衡逻辑

public class FeignClientFactoryBean implements FactoryBean<Object>, InitializingBean, ApplicationContextAware, BeanFactoryAware {
	...
	//获取目标代理对象
	<T> T getTarget() {
		//FeignAutoConfiguration中自动注入了FeignContext
        FeignContext context = this.beanFactory != null ? (FeignContext)this.beanFactory.getBean(FeignContext.class) : (FeignContext)this.applicationContext.getBean(FeignContext.class);
        //此处是通过FeignContext构建Builder,一系列配置信息 
        Builder builder = this.feign(context);
        //如果@FeignClient中配置了url,那么就要直接访问http请求,不会走注册中心负载均衡逻辑。
        if (StringUtils.hasText(this.url)) {
            if (StringUtils.hasText(this.url) && !this.url.startsWith("http")) {
                this.url = "http://" + this.url;
            }

            String url = this.url + this.cleanPath();
            //获取调用Client
            Client client = (Client)this.getOptional(context, Client.class);
            if (client != null) {
            	//如果是FeignBlockingLoadBalancerClient获取Delegate(这个就是Client.Default 这个就是通过HttpUrlConnection做http请求)
                if (client instanceof FeignBlockingLoadBalancerClient) {
                //获取Client.Default
                    client = ((FeignBlockingLoadBalancerClient)client).getDelegate();
                }
				//同理FeignBlockingLoadBalancerClient
                if (client instanceof RetryableFeignBlockingLoadBalancerClient) {
                	//获取Client.Default
                    client = ((RetryableFeignBlockingLoadBalancerClient)client).getDelegate();
                }
				
                builder.client(client);
            }

            Targeter targeter = (Targeter)this.get(context, Targeter.class);
            //实际是通过client调用
            return targeter.target(this, builder, context, new HardCodedTarget(this.type, this.name, url));
        } else {
        	//如果@FeignClient中没有配置url,那么会走注册中心负载均衡逻辑。
            if (this.url != null && LOG.isWarnEnabled()) {
                LOG.warn("The provided URL is empty. Will try picking an instance via load-balancing.");
            } else if (LOG.isDebugEnabled()) {
                LOG.debug("URL not provided. Will use LoadBalancer.");
            }

            if (!this.name.startsWith("http")) {
                this.url = "http://" + this.name;
            } else {
                this.url = this.name;
            }

            this.url = this.url + this.cleanPath();
            //负载均衡逻辑。
            return this.loadBalance(builder, context, new HardCodedTarget(this.type, this.name, this.url));
        }
    }
    //负载均衡逻辑。会获取注册中心对应的服务,通过负载均衡策略获取对应实例,从而获得本次http访问的真实url
    protected <T> T loadBalance(Builder builder, FeignContext context, HardCodedTarget<T> target) {
    	//获取http请求访问的类,实际请求http通过此类
        Client client = (Client)this.getOptional(context, Client.class);
        if (client != null) {
        	//构建期中加入http访问类
            builder.client(client);
            //此处会根据FeignContext进入DefaultTarget(暂时看其中细节,细节较多)
            Targeter targeter = (Targeter)this.get(context, Targeter.class);
            //创建动态代理对象 
            return targeter.target(this, builder, context, target);
        } else {
            throw new IllegalStateException("No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-loadbalancer?");
        }
    }
}

四、Feign类构建器构造Feign实现类

1、构造ReflectiveFeign,该对象包含了很多基本信息,如Encoder(编码器),Decoder(解码器),RequestInterceptor(拦截器)
2、newInstance() ,构造动态代理对现象

public abstract class Feign {
	public static class Builder {
			...
			//newInstance()构建动态代理对象
	       public <T> T target(Target<T> target) {
	           return this.build().newInstance(target);
	       }
			//创建一个Feign对象即(ReflectiveFeign),通过此对象构建动态代理对象,此处会带入所有访问调用的拦截器,编码解码,协议等配置信息
	       public Feign build() {
	           Client client = (Client)Capability.enrich(this.client, this.capabilities);
	           Retryer retryer = (Retryer)Capability.enrich(this.retryer, this.capabilities);
	           List<RequestInterceptor> requestInterceptors = (List)this.requestInterceptors.stream().map((ri) -> {
	               return (RequestInterceptor)Capability.enrich(ri, this.capabilities);
	           }).collect(Collectors.toList());
	           Logger logger = (Logger)Capability.enrich(this.logger, this.capabilities);
	           Contract contract = (Contract)Capability.enrich(this.contract, this.capabilities);
	           Options options = (Options)Capability.enrich(this.options, this.capabilities);
	           Encoder encoder = (Encoder)Capability.enrich(this.encoder, this.capabilities);
	           Decoder decoder = (Decoder)Capability.enrich(this.decoder, this.capabilities);
	           InvocationHandlerFactory invocationHandlerFactory = (InvocationHandlerFactory)Capability.enrich(this.invocationHandlerFactory, this.capabilities);
	           QueryMapEncoder queryMapEncoder = (QueryMapEncoder)Capability.enrich(this.queryMapEncoder, this.capabilities);
	           Factory synchronousMethodHandlerFactory = new Factory(client, retryer, requestInterceptors, logger, this.logLevel, this.decode404, this.closeAfterDecode, this.propagationPolicy, this.forceDecoding);
	           ParseHandlersByName handlersByName = new ParseHandlersByName(contract, options, encoder, decoder, queryMapEncoder, this.errorDecoder, synchronousMethodHandlerFactory);
	           return new ReflectiveFeign(handlersByName, invocationHandlerFactory, queryMapEncoder);
	       }
	   }
	}
}

五、ReflectiveFeign创建动态代理对象

1、构造MethodHandler,方法处理器
2、获取InvocationHandler (FeignInvocationHandler)
3、创建Java动态代理对象(Proxy.newProxyInstance(target.type().getClassLoader(), new Class[]{target.type()}, handler);)

public class ReflectiveFeign extends Feign {
	public <T> T newInstance(Target<T> target) {
		//获取方法处理器,每一个feign方法对应一个MethodHandler,bean调用时进入InvocationHandler 后通过方法名找到对应MethodHandler进行处理
        Map<String, MethodHandler> nameToHandler = this.targetToHandlersByName.apply(target);
        Map<Method, MethodHandler> methodToHandler = new LinkedHashMap();
        List<DefaultMethodHandler> defaultMethodHandlers = new LinkedList();
        Method[] var5 = target.type().getMethods();
        int var6 = var5.length;

        for(int var7 = 0; var7 < var6; ++var7) {
            Method method = var5[var7];
            if (method.getDeclaringClass() != Object.class) {
                if (Util.isDefault(method)) {
                    DefaultMethodHandler handler = new DefaultMethodHandler(method);
                    defaultMethodHandlers.add(handler);
                    methodToHandler.put(method, handler);
                } else {
                    methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method)));
                }
            }
        }
		//动态代理处理器(调用feign都会进入此handler即FeignInvocationHandler)
        InvocationHandler handler = this.factory.create(target, methodToHandler);
        //动态代理对象
        T proxy = Proxy.newProxyInstance(target.type().getClassLoader(), new Class[]{target.type()}, handler);
        Iterator var12 = defaultMethodHandlers.iterator();

        while(var12.hasNext()) {
            DefaultMethodHandler defaultMethodHandler = (DefaultMethodHandler)var12.next();
            defaultMethodHandler.bindTo(proxy);
        }

        return proxy;
    }
}

调用过程

FeignInvocationHandler代理所有调用

接口调用一般都是通过动态代理实现,和mybatis一样,都是使用的java的动态代理。feign使用的是静态内部类FeignInvocationHandler。
MethodHandler 有三种:
1、SynchronousMethodHandler 处理正常远程调用逻辑,
2、DefaultMethodHandler处理接口default方法逻辑
3、匿名内部类处理异常逻辑

static class FeignInvocationHandler implements InvocationHandler {
        private final Target target;
        //每个方法的处理器
        private final Map<Method, MethodHandler> dispatch;
		
        FeignInvocationHandler(Target target, Map<Method, MethodHandler> dispatch) {
            this.target = (Target)Util.checkNotNull(target, "target", new Object[0]);
            this.dispatch = (Map)Util.checkNotNull(dispatch, "dispatch for %s", new Object[]{target});
        }
		//调用代理,所有调用在此处代理
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        	//个人认为此处代码不是特别好,就我自己而言认为应该把 equals,hashCode,toString分别用if处理,主干逻辑this.dispatch.get(method)).invoke(args) 放在else中,这样代码可读性更好
            if (!"equals".equals(method.getName())) {
                if ("hashCode".equals(method.getName())) {
                    return this.hashCode();
                } else {
                    return "toString".equals(method.getName()) ? this.toString() : ((MethodHandler)this.dispatch.get(method)).invoke(args);
                }
            } else {
                try {
                    Object otherHandler = args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;
                    return this.equals(otherHandler);
                } catch (IllegalArgumentException var5) {
                    return false;
                }
            }
        }
		...

    }

SynchronousMethodHandler 处理每个方法

通过ReflectiveFeign.ParseHandlersByName 代码可以看出创建MethodHandler 使用的 SynchronousMethodHandler .Factory
1、Client调用
2、失败后根据配置重试

final class SynchronousMethodHandler implements MethodHandler {
 
    ...
	//调用逻辑处理
    public Object invoke(Object[] argv) throws Throwable {
        RequestTemplate template = this.buildTemplateFromArgs.create(argv);
        Options options = this.findOptions(argv);
        Retryer retryer = this.retryer.clone();
		//开始调用,失败后根据配置重试
        while(true) {
            try {
            	//执行远程调用,并解码
                return this.executeAndDecode(template, options);
            } catch (RetryableException var9) {
                RetryableException e = var9;

                try {
                	//判断是否继续重试
                    retryer.continueOrPropagate(e);
                } catch (RetryableException var8) {
                    Throwable cause = var8.getCause();
                    if (this.propagationPolicy == ExceptionPropagationPolicy.UNWRAP && cause != null) {
                        throw cause;
                    }

                    throw var8;
                }

                if (this.logLevel != Level.NONE) {
                    this.logger.logRetry(this.metadata.configKey(), this.logLevel);
                }
            }
        }
    }
	//真实执行调用并解码代码
    Object executeAndDecode(RequestTemplate template, Options options) throws Throwable {
    	//生成请求对象(此处的请求只是选择实例使用)
        Request request = this.targetRequest(template);
        if (this.logLevel != Level.NONE) {
            this.logger.logRequest(this.metadata.configKey(), this.logLevel, request);
        }
		
        long start = System.nanoTime();

        Response response;
        try {
        	//执行远程调用返回调用结果Response
            response = this.client.execute(request, options);
            response = response.toBuilder().request(request).requestTemplate(template).build();
        } catch (IOException var12) {
            if (this.logLevel != Level.NONE) {
                this.logger.logIOException(this.metadata.configKey(), this.logLevel, var12, this.elapsedTime(start));
            }

            throw FeignException.errorExecuting(request, var12);
        }

        long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
        if (this.decoder != null) {
        	//通过Decoder解码Response为@FeignClient方法中的返回的对象
            return this.decoder.decode(response, this.metadata.returnType());
        } else {
            CompletableFuture<Object> resultFuture = new CompletableFuture();
            this.asyncResponseHandler.handleResponse(resultFuture, this.metadata.configKey(), response, this.metadata.returnType(), elapsedTime);

            try {
                if (!resultFuture.isDone()) {
                    throw new IllegalStateException("Response handling not done");
                } else {
                    return resultFuture.join();
                }
            } catch (CompletionException var13) {
                Throwable cause = var13.getCause();
                if (cause != null) {
                    throw cause;
                } else {
                    throw var13;
                }
            }
        }
    }
    ...
}

FeignBlockingLoadBalancerClient 处理调用

1、通过负载均衡获取实例对象(如果没有配置OkHttpClient或ApacheClient,并且自己也没有配置Client,那么就会用DefaultFeignLoadBalancerConfiguration中配置的Client(FeignBlockingLoadBalancerClient ))
2、如果获取不到ServiceInstance,那么返回503Response
3、如果获取到ServiceInstance,那么获取真实url后,开始请求(实际是通过Client.Default调用处理)。

public class FeignBlockingLoadBalancerClient implements Client {
    ...
	//具体执行
    public Response execute(Request request, Options options) throws IOException {
    	//此处originalUri为分布式实例组成的。不是真实url
        URI originalUri = URI.create(request.url());
        //服务id
        String serviceId = originalUri.getHost();
        Assert.state(serviceId != null, "Request URI does not contain a valid hostname: " + originalUri);
        String hint = this.getHint(serviceId);
        DefaultRequest<RequestDataContext> lbRequest = new DefaultRequest(new RequestDataContext(LoadBalancerUtils.buildRequestData(request), hint));
        Set<LoadBalancerLifecycle> supportedLifecycleProcessors = LoadBalancerLifecycleValidator.getSupportedLifecycleProcessors(this.loadBalancerClientFactory.getInstances(serviceId, LoadBalancerLifecycle.class), RequestDataContext.class, ResponseData.class, ServiceInstance.class);
        supportedLifecycleProcessors.forEach((lifecycle) -> {
            lifecycle.onStart(lbRequest);
        });
        //通过负载均衡选择实例(Spring默认有轮询和随机两种负载均衡器)
        ServiceInstance instance = this.loadBalancerClient.choose(serviceId, lbRequest);
        org.springframework.cloud.client.loadbalancer.Response<ServiceInstance> lbResponse = new DefaultResponse(instance);
        String message;
        //实例为空那么报错
        if (instance == null) {
            message = "Load balancer does not contain an instance for the service " + serviceId;
            if (LOG.isWarnEnabled()) {
                LOG.warn(message);
            }

            supportedLifecycleProcessors.forEach((lifecycle) -> {
                lifecycle.onComplete(new CompletionContext(Status.DISCARD, lbRequest, lbResponse));
            });
            //错误码HttpStatus.SERVICE_UNAVAILABLE 503
            return Response.builder().request(request).status(HttpStatus.SERVICE_UNAVAILABLE.value()).body(message, StandardCharsets.UTF_8).build();
        } else {
        	//实例存在,找到真实url(域名或ip 与端口组成的url)
            message = this.loadBalancerClient.reconstructURI(instance, originalUri).toString();
            //组建请求参数
            Request newRequest = this.buildRequest(request, message);
            //远程调用返回响应对象(delegate为真实处理Client)
            return LoadBalancerUtils.executeWithLoadBalancerLifecycleProcessing(this.delegate, options, newRequest, lbRequest, lbResponse, supportedLifecycleProcessors);
        }
    }
    ...
}

Client.Default 处理http远程调用

1、通过请求对象获取HttpURLConnection
2、请求后组装为Response

public static class Default implements Client {
        ...
		
        public Response execute(Request request, Options options) throws IOException {
        	//使用HttpURLConnection 进行http请求
            HttpURLConnection connection = this.convertAndSend(request, options);
            //请求后组装为Response对象
            return this.convertResponse(connection, request);
        }

        Response convertResponse(HttpURLConnection connection, Request request) throws IOException {
            int status = connection.getResponseCode();
            String reason = connection.getResponseMessage();
            if (status < 0) {
                throw new IOException(String.format("Invalid status(%s) executing %s %s", status, connection.getRequestMethod(), connection.getURL()));
            } else {
                Map<String, Collection<String>> headers = new LinkedHashMap();
                Iterator var6 = connection.getHeaderFields().entrySet().iterator();

                while(var6.hasNext()) {
                    Entry<String, List<String>> field = (Entry)var6.next();
                    if (field.getKey() != null) {
                        headers.put(field.getKey(), field.getValue());
                    }
                }

                Integer length = connection.getContentLength();
                if (length == -1) {
                    length = null;
                }

                InputStream stream;
                if (status >= 400) {
                    stream = connection.getErrorStream();
                } else {
                    stream = connection.getInputStream();
                }

                return Response.builder().status(status).reason(reason).headers(headers).request(request).body(stream, length).build();
            }
        }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

年迈程序

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值