不要问我阅读spring源码有什么用,问就是没有用,只是让我自己使用spring的过程中自信点!
spring-相关文章
1. ribbon是使用的RestTemplate,从表象看RestTemplate实现了负载均衡 2. RestTemplate之所有能实现负载均衡是因为RestTemplate添加了拦截器 复制代码
@Configuration public class AppConfig { @Bean //这个注解必须加,不加的话就是单纯的使用restTemplate @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } } @RequestMapping("test01") @RestController public class TestController01 { @Autowired private RestTemplate restTemplate; @RequestMapping("test01") public String test01() { //使用restTemplate 可以达到负载均衡的目的 service-ribbon-test01 为服务名 return restTemplate.getForObject("http://service-ribbon-test01/test01/test01", String.class); } } 复制代码
@Override @Nullable public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables) throws RestClientException { RequestCallback requestCallback = acceptHeaderRequestCallback(responseType); HttpMessageConverterExtractor<T> responseExtractor = new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger); return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables); } @Override @Nullable public <T> T execute(String url, HttpMethod method, @Nullable RequestCallback requestCallback, @Nullable ResponseExtractor<T> responseExtractor, Object... uriVariables) throws RestClientException { URI expanded = getUriTemplateHandler().expand(url, uriVariables); return doExecute(expanded, method, requestCallback, responseExtractor); } @Nullable protected <T> T doExecute(URI url, @Nullable HttpMethod method, @Nullable RequestCallback requestCallback, @Nullable ResponseExtractor<T> responseExtractor) throws RestClientException { Assert.notNull(url, "URI is required"); Assert.notNull(method, "HttpMethod is required"); ClientHttpResponse response = null; try { //获取ClientHttpRequest 判断依据就是看看是否存在拦截器 ClientHttpRequest request = createRequest(url, method); if (requestCallback != null) { requestCallback.doWithRequest(request); } response = request.execute(); handleResponse(url, method, response); return (responseExtractor != null ? responseExtractor.extractData(response) : null); } } protected ClientHttpRequest createRequest(URI url, HttpMethod method) throws IOException { //这里getRequestFactory 先获取工厂 ClientHttpRequest request = getRequestFactory().createRequest(url, method); initialize(request); if (logger.isDebugEnabled()) { logger.debug("HTTP " + method.name() + " " + url); } return request; } @Override public ClientHttpRequestFactory getRequestFactory() { //获取拦截器 这个拦截器就是我们上面提到过的 List<ClientHttpRequestInterceptor> interceptors = getInterceptors(); if (!CollectionUtils.isEmpty(interceptors)) { ClientHttpRequestFactory factory = this.interceptingRequestFactory; if (factory == null) { //创建ClientHttpRequestFactory , 并且把拦截器放入工厂中 factory = new InterceptingClientHttpRequestFactory(super.getRequestFactory(), interceptors); this.interceptingRequestFactory = factory; } return factory; } else { //假如没有拦截器就是用默认的工厂 return super.getRequestFactory(); } } //创建ClientHttpRequest @Override protected ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod, ClientHttpRequestFactory requestFactory) { //我们关注的是工厂的拦截器(就是上个方法的拦截器),放入了ClientHttpRequest return new InterceptingClientHttpRequest(requestFactory, this.interceptors, uri, httpMethod); } 复制代码
//org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration //LoadBalancerAutoConfiguration是个配置类 @Bean public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated( final ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers) { //restTemplateCustomizers是个函数是接口 //下面方法下看下 restTemplateCustomizers 是在什么时候创建的,返回的又是个什么东西 return () -> restTemplateCustomizers.ifAvailable(customizers -> { for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) { for (RestTemplateCustomizer customizer : customizers) { //循环我们注册的restTemplate 调用customizer.customize //假如这段代码的调用逻辑整不明白,建议先学习下 函数式接口lambda customizer.customize(restTemplate); } } }); } //org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration.LoadBalancerInterceptorConfig.restTemplateCustomizer(LoadBalancerInterceptor) @Bean @ConditionalOnMissingBean public RestTemplateCustomizer restTemplateCustomizer( final LoadBalancerInterceptor loadBalancerInterceptor) { return restTemplate -> { List<ClientHttpRequestInterceptor> list = new ArrayList<>( restTemplate.getInterceptors()); list.add(loadBalancerInterceptor); //看这里,,,把拦截器放入 restTemplate中 restTemplate.setInterceptors(list); }; } //看了上面的两个方法,大致能发现一个重要的问题吧 //那就是LoadBalancerAutoConfiguration.this.restTemplates非常重要 //里面有值 那就添加拦截器,然后restTemplate就能实现负载均衡,反之不能那我们就来看看 //org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration @LoadBalanced @Autowired(required = false) private List<RestTemplate> restTemplates = Collections.emptyList(); //restTemplates初始化为一个空的集合 //@Autowired(required = false)使用了依赖注入 //@LoadBalanced 加这个注解 //假如不加@LoadBalanced注解,restTemplates只要springioc容器中存在restTemplate就会被放进去 //就是因为加了@LoadBalanced注解,所以springioc容器依赖注入的时候判断下 //你的restTemplates的创建是否使用了了@LoadBalanced //也这是为什么我们创建restTemplate的时候要使用@LoadBalanced的原因,@LoadBalanced就像一个开关 //依赖注入请移步另一篇文章 复制代码
@Nullable protected <T> T doExecute(URI url, @Nullable HttpMethod method, @Nullable RequestCallback requestCallback, @Nullable ResponseExtractor<T> responseExtractor) throws RestClientException { Assert.notNull(url, "URI is required"); Assert.notNull(method, "HttpMethod is required"); ClientHttpResponse response = null; try { //在这里根据 是否存在拦截器获取不同的工厂,创建不同的ClientHttpRequest ClientHttpRequest request = createRequest(url, method); if (requestCallback != null) { requestCallback.doWithRequest(request); } //执行 response = request.execute(); handleResponse(url, method, response); return (responseExtractor != null ? responseExtractor.extractData(response) : null); } } @Override public final ClientHttpResponse execute() throws IOException { //判断时是否执行 assertNotExecuted(); //执行 ClientHttpResponse result = executeInternal(this.headers); //设置为已执行 this.executed = true; return result; } @Override protected ClientHttpResponse executeInternal(HttpHeaders headers) throws IOException { byte[] bytes = this.bufferedOutput.toByteArray(); if (headers.getContentLength() < 0) { headers.setContentLength(bytes.length); } //这里 ClientHttpResponse result = executeInternal(headers, bytes); this.bufferedOutput = new ByteArrayOutputStream(0); return result; } @Override protected final ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException { InterceptingRequestExecution requestExecution = new InterceptingRequestExecution(); //执行 return requestExecution.execute(this, bufferedOutput); } @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); } else { //不存在,走这里 HttpMethod method = request.getMethod(); Assert.state(method != null, "No standard HTTP method"); ClientHttpRequest delegate = requestFactory.createRequest(request.getURI(), method); request.getHeaders().forEach((key, value) -> delegate.getHeaders().addAll(key, value)); if (body.length > 0) { if (delegate instanceof StreamingHttpOutputMessage) { StreamingHttpOutputMessage streamingOutputMessage = (StreamingHttpOutputMessage) delegate; streamingOutputMessage.setBody(outputStream -> StreamUtils.copy(body, outputStream)); } else { StreamUtils.copy(body, delegate.getBody()); } } return delegate.execute(); } } @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); //如果说上面的方法都是spring提供的公用方法,下面的就是ribbon组件的了 //假如以后存在一个别的组件和ribbon的功能类似,整合的过程中,也是可以从这里开始提供具体实现的 return this.loadBalancer.execute(serviceName, this.requestFactory.createRequest(request, body, execution)); } //org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient //RibbonLoadBalancerClient是啥时候注册的这里就不提了 , 自己去 看吧 public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint) throws IOException { //下面的两个方法都挺重要 我们一个一个看 //获取loadBalancer //loadBalancer中包含服务列表 ILoadBalancer loadBalancer = getLoadBalancer(serviceId); //获取服务,里面包含负载均衡的策略 Server server = getServer(loadBalancer, hint); 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); } 复制代码
protected ILoadBalancer getLoadBalancer(String serviceId) { return this.clientFactory.getLoadBalancer(serviceId); } public ILoadBalancer getLoadBalancer(String name) { return getInstance(name, ILoadBalancer.class); } @Override public <C> C getInstance(String name, Class<C> type) { //这个方法里面其实就是根据传入的type去springioc中获取bena ILoadBalancer //ILoadBalancer 实现类为ZoneAwareLoadBalancer //有一个属性 包含了注册中心所有注册的服务详情 //现在看下ZoneAwareLoadBalancer在什么地方创建干了什么 C instance = super.getInstance(name, type); if (instance != null) { return instance; } IClientConfig config = getInstance(name, IClientConfig.class); return instantiateWithConfig(getContext(name), type, config); } 复制代码
//创建 @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); } //rule 为负载均衡策略 //serverList 为服务列表 只要实现ServerList即可 , nacos ,, eureka //serverListUpdater 为 跑定时 任务的。 //因为我这这边使用的是nacos 所以 类型为 : NacosServerList //具体 NacosServerList 是啥时候创建的 这么来的,不看了,等会面说nacos源码的时候在看看 //具体的 构造方法不看了 //还有定时任务刷新服务列表的。。。很多 return new ZoneAwareLoadBalancer<>(config, rule, ping, serverList, serverListFilter, serverListUpdater); } 复制代码
//ILoadBalancer 就是 ZoneAwareLoadBalancer protected Server getServer(ILoadBalancer loadBalancer, Object hint) { if (loadBalancer == null) { return null; } // Use 'default' on a null hint, or just pass it on? return loadBalancer.chooseServer(hint != null ? hint : "default"); } public Server chooseServer(Object key) { if (counter == null) { counter = createCounter(); } counter.increment(); if (rule == null) { return null; } else { try { //根据你传递的不同的策略规则选择不同的服务 return rule.choose(key); } catch (Exception e) { logger.warn("LoadBalancer [{}]: Error choosing server for key {}", name, key, e); return null; } } } //后续执行http请求 //结束 复制代码
1. 根据是否存在拦截器获取不同的request工厂,获取不同的request 2. 拦截器是保存在restTemplate中的 3. 拦截器是一直存在的,但是要看restTemplate是否被@LoadBalanced注释,只有注释了,才会把拦截器放入这个restTemplate 4. 获取服务列表 5. 根据rule策略选择具体的服务 6. http请求 复制代码