springcloud源码 ribbon(一)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yangyangiud/article/details/79955658

ribbon 源码分析

1 依赖配置

依赖

<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>

启动
通常我们直接调用请求是通过spring 的RestTemplate ,那么如果TestTemplate 是如何结合ribbon去做负载的?下面先看下如何去使用的

@SpringBootApplication
@RestController
public class Application  {

    @Autowired
    private RestTemplate template;

    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
    //标记为loadbalanced   
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
    
    @GetMapping("hellow")
    String hello(){
        Map<String,String> params = new HashMap<>();
        params.put("name","xieyang pang de  wangba");
        template.getForEntity("http://localhost:8080/getUser",User.class,params);
        return "hellow";
    }

    @GetMapping("getUser")
   public User getUser(String name){
        User user = new User();
        user.setName(name);
        return user;
    }
}

上面的restTemplate被 @LoadBalanced标记后是怎么样处理的?按以往的经验,不防设想RestTemplate与ribbon结合有两种方式,1 通过spring 容器生成RestTemplate 代理,且该该与ribbon相关组件类组合;2 RestTemplate 自身或其组合实现已提供相关的拦截接口,只要实现其拦截接口,并在该实现与ribbon 组合;带着上述设想去分析TestTemplate 与ribbon是如结合的?断点查看 注入的TestTemplate 是怎么样的?在这里插入图片描述
很明显TestTemplate与ribbon 是以上面设想的方式2去实现的;那么接下来要分析LoadBalancerInterceptor是怎么被创建及怎么怎么添加到RestTemplate里的?
在这里插入图片描述

2 RestTemplate 与ribbon 结合自动装配

LoadBalancerAutoConfiguration

@Configuration
//结合RestTemplate存在才初始化
@ConditionalOnClass(RestTemplate.class)
@ConditionalOnBean(LoadBalancerClient.class)
@EnableConfigurationProperties(LoadBalancerRetryProperties.class)
public class LoadBalancerAutoConfiguration {
      // 添RestTemplate 注入标识为@LoalBalance时,该实例将被添加下面的集合中
    @LoadBalanced
    @Autowired(required = false)
    private List<RestTemplate> restTemplates = Collections.emptyList();

    @Bean
    public SmartInitializingSingleton loadBalancedRestTemplateInitializer(
            final List<RestTemplateCustomizer> customizers) {
        return new SmartInitializingSingleton() {
            @Override
            public void afterSingletonsInstantiated() {
                //遍历所有自定议RestTemplate器,并调用customize方法,
                // 去修改restTemplate 里的一些内容实例,当然这个里是添加loalbalancerterceptor
                for (RestTemplate restTemplate : restTemplates) {
                    for (RestTemplateCustomizer customizer : customizers) {
                        customizer.customize(restTemplate);
                    }
                }
            }
        };
    }

    @Autowired(required = false)
    private List<LoadBalancerRequestTransformer> transformers = Collections.emptyList();

    @Bean
    @ConditionalOnMissingBean
    //他建负载请求工厂,每个请求都会封装成一个request实例
    public LoadBalancerRequestFactory loadBalancerRequestFactory(
            LoadBalancerClient loadBalancerClient) {
        return new LoadBalancerRequestFactory(loadBalancerClient, transformers);
    }

    @Configuration
    @ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate")
    static class LoadBalancerInterceptorConfig {
        @Bean //结合loadbalancerclient创建负截拦截器
        public LoadBalancerInterceptor ribbonInterceptor(
                LoadBalancerClient loadBalancerClient,
                LoadBalancerRequestFactory requestFactory) {
            return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);
        }

        @Bean
        @ConditionalOnMissingBean
        public RestTemplateCustomizer restTemplateCustomizer(
                final LoadBalancerInterceptor loadBalancerInterceptor) {
            //创建一个TestTemplate自定义器,并在customize方法中添加上面创建的拦截器
            return new RestTemplateCustomizer() {
                @Override
                public void customize(RestTemplate restTemplate) {
                    List<ClientHttpRequestInterceptor> list = new ArrayList<>(
                            restTemplate.getInterceptors());
                    list.add(loadBalancerInterceptor);
                    restTemplate.setInterceptors(list);
                }
            };
        }
    }
    //注入ZoneAwareLoadBalancer 负截均衡器
	@Bean
	@ConditionalOnMissingBean
	public ILoadBalancer ribbonLoadBalancer(IClientConfig config,
			ServerList<Server> serverList, ServerListFilter<Server> serverListFilter,
			IRule rule, IPing ping, ServerListUpdater serverListUpdater) {
		if (this.propertiesFactory.isSet(ILoadBalancer.class, name)) {
			return this.propertiesFactory.get(ILoadBalancer.class, config, name);
		}
		return new ZoneAwareLoadBalancer<>(config, rule, ping, serverList,
				serverListFilter, serverListUpdater);
	}

	@Bean
	@ConditionalOnMissingBean
	@SuppressWarnings("unchecked")
	public ServerListFilter<Server> ribbonServerListFilter(IClientConfig config) {
		if (this.propertiesFactory.isSet(ServerListFilter.class, name)) {
			return this.propertiesFactory.get(ServerListFilter.class, config, name);
		}
		ZonePreferenceServerListFilter filter = new ZonePreferenceServerListFilter();
		filter.initWithNiwsConfig(config);
		return filter;
	}

	@Bean
	@ConditionalOnMissingBean
	public RibbonLoadBalancerContext ribbonLoadBalancerContext(ILoadBalancer loadBalancer,
			IClientConfig config, RetryHandler retryHandler) {
		return new RibbonLoadBalancerContext(loadBalancer, config, retryHandler);
	}

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));
}

//实现ClientHttpRequestInterceptor intercept方法
@Override
public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,
                                    final ClientHttpRequestExecution execution) throws IOException {
    final URI originalUri = request.getURI();
    //截取serverName 后面作为serviceId key去获取服务实例表
    String serviceName = originalUri.getHost();
    Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri);
    //通过LoadBalancerClient 实例去调用去实例负载处理
    return this.loadBalancer.execute(serviceName, requestFactory.createRequest(request, body, execution));
}

}

回过头全分析RestTemplate是怎么样执行上面 interceptor的

  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 {
            //创建请求信息,createRequest比较关建
            //这里当前创建是的InterceptingClientRequest 内部会封loabalancelient一些信息
            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;
            }
        }
        catch (IOException ex) {
            String resource = url.toString();
            String query = url.getRawQuery();
            resource = (query != null ? resource.substring(0, resource.indexOf('?')) : resource);
            throw new ResourceAccessException("I/O error on " + method.name() +
                    " request for \"" + resource + "\": " + ex.getMessage(), ex);
        }
        finally {
            if (response != null) {
                response.close();
            }
        }
    }

在这里插入图片描述
从上面的截图可以看到接下来只要分析InterceptingClientHttpRequest的 excute方法
在这里插入图片描述
执行loabalacerInterceptor excute方法

 @Override
    protected final ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException {
        //他建执行器
        InterceptingClientHttpRequest.InterceptingRequestExecution requestExecution = new InterceptingClientHttpRequest.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 {
            //如果存在requestInterceptor 执行interceptor
            if (this.iterator.hasNext()) {
                //当前执行的的interceptor就是LoadBalancerInterceptor
                ClientHttpRequestInterceptor nextInterceptor = this.iterator.next();
                //再进入完全是ribbon的内容了
                return nextInterceptor.intercept(request, body, this);
            }
            else {
                //正常的http请求
                ClientHttpRequest delegate = requestFactory.createRequest(request.getURI(), request.getMethod());
                for (Map.Entry<String, List<String>> entry : request.getHeaders().entrySet()) {
                    List<String> values = entry.getValue();
                    for (String value : values) {
                        delegate.getHeaders().add(entry.getKey(), value);
                    }
                }
                if (body.length > 0) {
                    StreamUtils.copy(body, delegate.getBody());
                }
                return delegate.execute();
            }
        }
    }

在这里插入图片描述

3 LoadBalancerClient实例初始化

上面可以清晳的看到LoadBalancerInterceptor怎么装载进TestTemplate里的,但是还有一个非常重要的接口LoadBalancerClient实例没看到被初始化;

@Configuration
@ConditionalOnClass({ IClient.class, RestTemplate.class, AsyncRestTemplate.class, Ribbon.class})
@RibbonClients
@AutoConfigureAfter(name = "org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration")
@AutoConfigureBefore({LoadBalancerAutoConfiguration.class, AsyncLoadBalancerAutoConfiguration.class})
@EnableConfigurationProperties({RibbonEagerLoadProperties.class, ServerIntrospectorProperties.class})
public class RibbonAutoConfiguration {

	@Autowired(required = false)
	private List<RibbonClientSpecification> configurations = new ArrayList<>();
	
	@Autowired
	private RibbonEagerLoadProperties ribbonEagerLoadProperties;

	@Bean
	public HasFeatures ribbonFeature() {
		return HasFeatures.namedFeature("Ribbon", Ribbon.class);
	}

	@Bean
	public SpringClientFactory springClientFactory() {
		SpringClientFactory factory = new SpringClientFactory();
		factory.setConfigurations(this.configurations);
		return factory;
	}
     //创建ribbonloadbalanceclient
	@Bean
	@ConditionalOnMissingBean(LoadBalancerClient.class)
	public LoadBalancerClient loadBalancerClient() {
		return new RibbonLoadBalancerClient(springClientFactory());
	}
//去掉一堆代码
阅读更多

没有更多推荐了,返回首页