• SpringCloud之Ribbon源码解析(二)--请求流程


    一 RestTemplate.doExecute

    protected <T> T doExecute(URI url, HttpMethod method, RequestCallback requestCallback,
                ResponseExtractor<T> responseExtractor) throws RestClientException {
    
            Assert.notNull(url, "'url' must not be null");
            Assert.notNull(method, "'method' must not be null");
            ClientHttpResponse response = null;
            try {
                ClientHttpRequest request = createRequest(url, method);
                if (requestCallback != null) {
                    requestCallback.doWithRequest(request);
                }
                response = request.execute();
                handleResponse(url, method, response);
                if (responseExtractor != null) {
                    return responseExtractor.extractData(response);
                }
                else {
                    return null;
                }
            }

      当使用带有负载均衡的功能时createRequest内有乾坤了

      

      

    public abstract class HttpAccessor {
    
        private ClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
    
        public void setRequestFactory(ClientHttpRequestFactory requestFactory) {
            Assert.notNull(requestFactory, "ClientHttpRequestFactory must not be null");
            this.requestFactory = requestFactory;
        }
    
        public ClientHttpRequestFactory getRequestFactory() {
            return this.requestFactory;
        }
    
        protected ClientHttpRequest createRequest(URI url, HttpMethod method) throws IOException {
            ClientHttpRequest request = getRequestFactory().createRequest(url, method);
            if (logger.isDebugEnabled()) {
                logger.debug("Created " + method.name() + " request for "" + url + """);
            }
            return request;
        }
    
    }

      getRequestFactory并不是当前HttpAccessor类中定义的,而是在子类InterceptingHttpAccessor中定义的。

    public abstract class InterceptingHttpAccessor extends HttpAccessor {
    
        private List<ClientHttpRequestInterceptor> interceptors = new ArrayList<ClientHttpRequestInterceptor>();
    
        public void setInterceptors(List<ClientHttpRequestInterceptor> interceptors) {
            this.interceptors = interceptors;
        }
    
        public List<ClientHttpRequestInterceptor> getInterceptors() {
            return interceptors;
        }
    
        @Override
        public ClientHttpRequestFactory getRequestFactory() {
            ClientHttpRequestFactory delegate = super.getRequestFactory();
            if (!CollectionUtils.isEmpty(getInterceptors())) {
                return new InterceptingClientHttpRequestFactory(delegate, getInterceptors());
            }
            else {
                return delegate;
            }
        }

      上一节我们分析了,通过RestTemplateCustomizer 注入拦截器到RestTemplate里,所以这里判断是存在拦截器的。

      在有拦截器注入的情况下,创建InterceptingClientHttpRequestFactory工厂,该工厂就是创建带拦截器的请求实例,因为注入了负载均衡拦截器,所以这里就从InterceptingClientHttpRequestFactory工厂创建。

    二  InterceptingClientHttpRequestFactory 

    public class InterceptingClientHttpRequestFactory extends AbstractClientHttpRequestFactoryWrapper {
    
        private final List<ClientHttpRequestInterceptor> interceptors;
    
        public InterceptingClientHttpRequestFactory(ClientHttpRequestFactory requestFactory,
                List<ClientHttpRequestInterceptor> interceptors) {
    
            super(requestFactory);
            this.interceptors = (interceptors != null ? interceptors : Collections.<ClientHttpRequestInterceptor>emptyList());
        }
    
    
        @Override
        protected ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod, ClientHttpRequestFactory requestFactory) {
            return new InterceptingClientHttpRequest(requestFactory, this.interceptors, uri, httpMethod);
        }
    
    }

      此时的请求已经是 InterceptingClientHttpRequest了,接下来我们看InterceptingClientHttpRequest的execute方法

    public abstract class AbstractClientHttpRequest implements ClientHttpRequest {
    
        private final HttpHeaders headers = new HttpHeaders();
    
        private boolean executed = false;
    
        @Override
        public final HttpHeaders getHeaders() {
            return (this.executed ? HttpHeaders.readOnlyHttpHeaders(this.headers) : this.headers);
        }
    
        @Override
        public final OutputStream getBody() throws IOException {
            assertNotExecuted();
            return getBodyInternal(this.headers);
        }
    
        @Override
        public final ClientHttpResponse execute() throws IOException {
            assertNotExecuted();
            ClientHttpResponse result = executeInternal(this.headers);
            this.executed = true;
            return result;
        }
    class InterceptingClientHttpRequest extends AbstractBufferingClientHttpRequest {
    
        //
    
        @Override
        protected final ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException {
            InterceptingRequestExecution requestExecution = new InterceptingRequestExecution();
            return requestExecution.execute(this, bufferedOutput);
        }
    
    
        private class InterceptingRequestExecution implements ClientHttpRequestExecution {
    
            private final Iterator<ClientHttpRequestInterceptor> iterator;
    
            public InterceptingRequestExecution() {
                this.iterator = interceptors.iterator();
            }
    
            @Override
            public ClientHttpResponse execute(HttpRequest request, byte[] body) throws IOException {
                if (this.iterator.hasNext()) {
                    ClientHttpRequestInterceptor nextInterceptor = this.iterator.next();
                    return nextInterceptor.intercept(request, body, this);
                }

    终于调用到了上一节开始提到的LoadBalancerInterceptor

    三 LoadBalancerInterceptor

    public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor {
    
        private LoadBalancerClient loadBalancer;
        private LoadBalancerRequestFactory requestFactory;
    
        public LoadBalancerInterceptor(LoadBalancerClient loadBalancer, LoadBalancerRequestFactory requestFactory) {
            this.loadBalancer = loadBalancer;
            this.requestFactory = requestFactory;
        }
    
        public LoadBalancerInterceptor(LoadBalancerClient loadBalancer) {
            // for backwards compatibility
            this(loadBalancer, new LoadBalancerRequestFactory(loadBalancer));
        }
    
        @Override
        public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,
                final ClientHttpRequestExecution execution) throws IOException {
            final URI originalUri = request.getURI();
            String serviceName = originalUri.getHost();
            Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri);
            return this.loadBalancer.execute(serviceName, requestFactory.createRequest(request, body, execution));
        }
    }

      在RibbonLoadBalancerClient的第一个execute方法以及getServer方法中可以看到,实际上是通过ILoadBalancer的负载均衡器实现类作的chooseServer方法选取一个服务,交给接下来的请求对象发起一个请求。

    这里的负载均衡实现类默认是ZoneAwareLoadBalancer区域感知负载均衡器实例,其内部通过均衡策略选择一个服务。

    public class RibbonLoadBalancerClient implements LoadBalancerClient {
        @Override
        public <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException {
            ILoadBalancer loadBalancer = getLoadBalancer(serviceId);
            Server server = getServer(loadBalancer);
            if (server == null) {
                throw new IllegalStateException("No instances available for " + serviceId);
            }
            RibbonServer ribbonServer = new RibbonServer(serviceId, server, isSecure(server,
                    serviceId), serverIntrospector(serviceId).getMetadata(server));
    
            return execute(serviceId, ribbonServer, request);
        }
    
        @Override
        public <T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request) throws IOException {
            Server server = null;
            if(serviceInstance instanceof RibbonServer) {
                server = ((RibbonServer)serviceInstance).getServer();
            }
            if (server == null) {
                throw new IllegalStateException("No instances available for " + serviceId);
            }
    
            RibbonLoadBalancerContext context = this.clientFactory
                    .getLoadBalancerContext(serviceId);
            RibbonStatsRecorder statsRecorder = new RibbonStatsRecorder(context, server);
    
            try {
                T returnVal = request.apply(serviceInstance);
                statsRecorder.recordStats(returnVal);
                return returnVal;
            }
            // catch IOException and rethrow so RestTemplate behaves correctly
            catch (IOException ex) {
                statsRecorder.recordStats(ex);
                throw ex;
            }
            catch (Exception ex) {
                statsRecorder.recordStats(ex);
                ReflectionUtils.rethrowRuntimeException(ex);
            }
            return null;
        }
           
        //
    
        protected Server getServer(ILoadBalancer loadBalancer) {
            if (loadBalancer == null) {
                return null;
            }
            return loadBalancer.chooseServer("default"); // TODO: better handling of key
        }

      总结下就是最终是通过ZoneAwareLoadBalancer从服务区注册中心选择服务来实现的负载均衡

  • 相关阅读:
    【梦话区】一直迷茫的net小伙
    【ASP.NET】登陆成功后如何跳转到上一个页面
    【C#】强类型DataSet实现登录次数限制
    【ASP.NET】ItemDataBound之repeater 和 listview
    【网页设计】框架的高度随框架里面的内容的多少而改变——转
    【连载】Scala程序设计:Java虚拟机多核编程实战——简介
    博客园图灵杯第五届博问大赛(2010.8.3~2010.9.2)
    【连载】高效人士的116个IT秘诀(第2版)——秘诀23早晨就来一次突破
    图灵2010.08书讯
    图灵五周年生日聚会圆满成功,多家媒体对此进行报道
  • 原文地址:https://www.cnblogs.com/juniorMa/p/14416520.html
Copyright © 2020-2023  润新知