Spring Cloud Ribbon的原理
直接开撸代码,通过代码来看Ribbon是如何实现的。
1:RibbonAutoConfiguration配置生成RibbonLoadBalancerClient实例。
代码位置:org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguration
1 @Configuration 2 @Conditional({RibbonAutoConfiguration.RibbonClassesConditions.class}) 3 @RibbonClients 4 @AutoConfigureAfter( 5 name = {"org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration"} 6 ) 7 @AutoConfigureBefore({LoadBalancerAutoConfiguration.class, AsyncLoadBalancerAutoConfiguration.class}) 8 @EnableConfigurationProperties({RibbonEagerLoadProperties.class, ServerIntrospectorProperties.class}) 9 public class RibbonAutoConfiguration { 10 @Autowired( 11 required = false 12 ) 13 private List<RibbonClientSpecification> configurations = new ArrayList(); 14 @Autowired 15 private RibbonEagerLoadProperties ribbonEagerLoadProperties; 16 17 //...略 18 19 @Bean 20 @ConditionalOnMissingBean({LoadBalancerClient.class}) 21 public LoadBalancerClient loadBalancerClient() { 22 return new RibbonLoadBalancerClient(this.springClientFactory()); 23 } 24 25 // ....略 26 27 }
先看配置条件项,RibbonAutoConfiguration配置必须在LoadBalancerAutoConfiguration配置前执行,因为在LoadBalancerAutoConfiguration配置中会使用RibbonLoadBalancerClient实例。
RibbonLoadBalancerClient继承自LoadBalancerClient接口,是负载均衡客户端,也是负载均衡策略的调用方。
2.LoadBalancerInterceptorConfig配置生成:
1).负载均衡拦截器LoadBalancerInterceptor实例
包含:
LoadBalancerClient实现类的RibbonLoadBalancerClient实例
负载均衡的请求创建工厂LoadBalancerRequestFactory:实例
2).RestTemplate自定义的RestTemplateCustomizer实例
代码位置:org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration
1 @Configuration(proxyBeanMethods = false) 2 @ConditionalOnClass(RestTemplate.class) 3 @ConditionalOnBean(LoadBalancerClient.class) 4 @EnableConfigurationProperties(LoadBalancerRetryProperties.class) 5 public class LoadBalancerAutoConfiguration { 6 7 @LoadBalanced 8 @Autowired(required = false) 9 private List<RestTemplate> restTemplates = Collections.emptyList(); 10 11 @Autowired(required = false) 12 private List<LoadBalancerRequestTransformer> transformers = Collections.emptyList(); 13 14 @Bean 15 public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated( 16 final ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers) { 17 return () -> restTemplateCustomizers.ifAvailable(customizers -> { 18 for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) { 19 for (RestTemplateCustomizer customizer : customizers) { 20 customizer.customize(restTemplate); 21 } 22 } 23 }); 24 } 25 26 @Bean 27 @ConditionalOnMissingBean 28 public LoadBalancerRequestFactory loadBalancerRequestFactory( 29 LoadBalancerClient loadBalancerClient) { 30 return new LoadBalancerRequestFactory(loadBalancerClient, this.transformers); 31 } 32 33 @Configuration(proxyBeanMethods = false) 34 @ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate") 35 static class LoadBalancerInterceptorConfig { 36 37 @Bean 38 public LoadBalancerInterceptor ribbonInterceptor( 39 LoadBalancerClient loadBalancerClient, 40 LoadBalancerRequestFactory requestFactory) { 41 return new LoadBalancerInterceptor(loadBalancerClient, requestFactory); 42 } 43 44 @Bean 45 @ConditionalOnMissingBean 46 public RestTemplateCustomizer restTemplateCustomizer( 47 final LoadBalancerInterceptor loadBalancerInterceptor) { 48 return restTemplate -> { 49 List<ClientHttpRequestInterceptor> list = new ArrayList<>( 50 restTemplate.getInterceptors()); 51 list.add(loadBalancerInterceptor); 52 restTemplate.setInterceptors(list); 53 }; 54 } 55 56 } 57 58 // .....略 59 } 60 61
先看配置条件项:
要求在项目环境中必须要有RestTemplate类。
要求必须要有LoadBalancerClient接口的实现类的实例,也就是上一步生成的RibbonLoadBalancerClient。
3.通过上面一步创建的RestTemplateCustomizer配置所有RestTemplate实例,就是将负载均衡拦截器设置给RestTemplate实例。
1 @Configuration(proxyBeanMethods = false) 2 @ConditionalOnClass(RestTemplate.class) 3 @ConditionalOnBean(LoadBalancerClient.class) 4 @EnableConfigurationProperties(LoadBalancerRetryProperties.class) 5 public class LoadBalancerAutoConfiguration { 6 7 @LoadBalanced 8 @Autowired(required = false) 9 private List<RestTemplate> restTemplates = Collections.emptyList(); 10 11 @Autowired(required = false) 12 private List<LoadBalancerRequestTransformer> transformers = Collections.emptyList(); 13 14 @Bean 15 public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated( 16 final ObjectProvider<List<RestTemplateCustomizer>> restTemplateCustomizers) { 17 return () -> restTemplateCustomizers.ifAvailable(customizers -> { 18 for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) { 19 for (RestTemplateCustomizer customizer : customizers) { 20 customizer.customize(restTemplate); 21 } 22 } 23 }); 24 } 25 26 @Bean 27 @ConditionalOnMissingBean 28 public LoadBalancerRequestFactory loadBalancerRequestFactory( 29 LoadBalancerClient loadBalancerClient) { 30 return new LoadBalancerRequestFactory(loadBalancerClient, this.transformers); 31 } 32 33 @Configuration(proxyBeanMethods = false) 34 @ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate") 35 static class LoadBalancerInterceptorConfig { 36 37 @Bean 38 public LoadBalancerInterceptor ribbonInterceptor( 39 LoadBalancerClient loadBalancerClient, 40 LoadBalancerRequestFactory requestFactory) { 41 return new LoadBalancerInterceptor(loadBalancerClient, requestFactory); 42 } 43 44 @Bean 45 @ConditionalOnMissingBean 46 public RestTemplateCustomizer restTemplateCustomizer( 47 final LoadBalancerInterceptor loadBalancerInterceptor) { 48 return restTemplate -> { 49 List<ClientHttpRequestInterceptor> list = new ArrayList<>( 50 restTemplate.getInterceptors()); 51 list.add(loadBalancerInterceptor); 52 restTemplate.setInterceptors(list); 53 }; 54 } 55 56 } 57 58 // ...略 59 }
restTemplate.setInterceptors(list)这个地方就是注入负载均衡拦截器的地方LoadBalancerInterceptor。
从这个地方实际上也可以猜出来,RestTemplate可以通过注入的拦截器来构建相应的请求实现负载均衡。
也能看出来可以自定义拦截器实现其他目的。
4.RibbonClientConfiguration配置生成ZoneAwareLoadBalancer实例
代码位置:org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration
1 @Configuration(proxyBeanMethods = false) 2 @EnableConfigurationProperties 3 @Import({ HttpClientConfiguration.class, OkHttpRibbonConfiguration.class, 4 RestClientRibbonConfiguration.class, HttpClientRibbonConfiguration.class }) 5 public class RibbonClientConfiguration { 6 7 8 // ...略 9 10 @Bean 11 @ConditionalOnMissingBean 12 public ILoadBalancer ribbonLoadBalancer(IClientConfig config, 13 ServerList<Server> serverList, ServerListFilter<Server> serverListFilter, 14 IRule rule, IPing ping, ServerListUpdater serverListUpdater) { 15 if (this.propertiesFactory.isSet(ILoadBalancer.class, name)) { 16 return this.propertiesFactory.get(ILoadBalancer.class, config, name); 17 } 18 return new ZoneAwareLoadBalancer<>(config, rule, ping, serverList, 19 serverListFilter, serverListUpdater); 20 } 21 22 // ...略 23 }
ZoneAwareLoadBalancer继承自ILoadBalancer接口,该接口有一个方法:
1 /** 2 * Choose a server from load balancer. 3 * 4 * @param key An object that the load balancer may use to determine which server to return. null if 5 * the load balancer does not use this parameter. 6 * @return server chosen 7 */ 8 public Server chooseServer(Object key);
ZoneAwareLoadBalancer就是一个具体的负载均衡实现类,也是默认的负载均衡类,通过对chooseServer方法的实现选取某个服务实例。
拦截&请求
1.使用RestTemplate进行Get、Post等各种请求,都是通过doExecute方法实现
代码位置:org.springframework.web.client.RestTemplate
1 public class RestTemplate extends InterceptingHttpAccessor implements RestOperations { 2 3 // ....略
14 @Nullable 15 protected <T> T doExecute(URI url, @Nullable HttpMethod method, @Nullable RequestCallback requestCallback, 16 @Nullable ResponseExtractor<T> responseExtractor) throws RestClientException { 17 18 Assert.notNull(url, "URI is required"); 19 Assert.notNull(method, "HttpMethod is required"); 20 ClientHttpResponse response = null; 21 try { 22 ClientHttpRequest request = createRequest(url, method); 23 if (requestCallback != null) { 24 requestCallback.doWithRequest(request); 25 } 26 response = request.execute(); 27 handleResponse(url, method, response); 28 return (responseExtractor != null ? responseExtractor.extractData(response) : null); 29 } 30 catch (IOException ex) { 31 String resource = url.toString(); 32 String query = url.getRawQuery(); 33 resource = (query != null ? resource.substring(0, resource.indexOf('?')) : resource); 34 throw new ResourceAccessException("I/O error on " + method.name() + 35 " request for \"" + resource + "\": " + ex.getMessage(), ex); 36 } 37 finally { 38 if (response != null) { 39 response.close(); 40 } 41 } 42 } 43 44 }
可以看出来其实底层也是通过HTTP请求来进行实现的服务请求。
支持的各种http请求方法最终都是调用doExecute方法,该方法内调用创建方法创建请求实例,并执行请求得到响应对象。
2.生成请求实例创建工厂
上一步代码中,调用createRequest方法创建请求实例,这个方法是定义在父类中。
先整理出主要的继承关系:
createRequest方法实际是定义在HttpAccessor抽象类中。
1 public abstract class HttpAccessor { 2 3 // ...略 4 5 protected ClientHttpRequest createRequest(URI url, HttpMethod method) throws IOException { 6 ClientHttpRequest request = getRequestFactory().createRequest(url, method); 7 initialize(request); 8 if (logger.isDebugEnabled()) { 9 logger.debug("HTTP " + method.name() + " " + url); 10 } 11 return request; 12 } 13 14 }
在createRequest方法中调用getRequestFactory方法获得请求实例创建工厂,实际上getRequestFactory并不是当前HttpAccessor类中定义的,而是在子类InterceptingHttpAccessor中定义的。
1 public abstract class InterceptingHttpAccessor extends HttpAccessor { 2 3 // ...略 4 5 @Override 6 public ClientHttpRequestFactory getRequestFactory() { 7 List<ClientHttpRequestInterceptor> interceptors = getInterceptors(); 8 if (!CollectionUtils.isEmpty(interceptors)) { 9 ClientHttpRequestFactory factory = this.interceptingRequestFactory; 10 if (factory == null) { 11 factory = new InterceptingClientHttpRequestFactory(super.getRequestFactory(), interceptors); 12 this.interceptingRequestFactory = factory; 13 } 14 return factory; 15 } 16 else { 17 return super.getRequestFactory(); 18 } 19 } 20 21 }
在这里做了个小动作,首先还是通过HttpAccessor类创建并获得SimpleClientHttpRequestFactory工厂,这个工厂主要就是在没有拦截器的时候创建基本请求实例。
其次,在有拦截器注入的情况下,创建InterceptingClientHttpRequestFactory工厂,该工厂就是创建带拦截器的请求实例,因为注入了负载均衡拦截器,所以这里就从InterceptingClientHttpRequestFactory工厂创建。
3.通过工厂创建请求实例
创建实例就看工厂的createRequest方法。
1 public class InterceptingClientHttpRequestFactory extends AbstractClientHttpRequestFactoryWrapper { 2 3 private final List<ClientHttpRequestInterceptor> interceptors; 4 5 6 /** 7 * Create a new instance of the {@code InterceptingClientHttpRequestFactory} with the given parameters. 8 * @param requestFactory the request factory to wrap 9 * @param interceptors the interceptors that are to be applied (can be {@code null}) 10 */ 11 public InterceptingClientHttpRequestFactory(ClientHttpRequestFactory requestFactory, 12 @Nullable List<ClientHttpRequestInterceptor> interceptors) { 13 14 super(requestFactory); 15 this.interceptors = (interceptors != null ? interceptors : Collections.emptyList()); 16 } 17 18 19 @Override 20 protected ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod, ClientHttpRequestFactory requestFactory) { 21 return new InterceptingClientHttpRequest(requestFactory, this.interceptors, uri, httpMethod); 22 } 23 24 }
就是new了个InterceptingClientHttpRequest实例,并且把拦截器、基本请求实例创建工厂注进去。
4.请求实例调用配置阶段注入的负载均衡拦截器的拦截方法intercept
可从第1步看出,创建完请求实例后,通过执行请求实例的execute方法执行请求。
1 ClientHttpRequest request = createRequest(url, method); 2 if (requestCallback != null) { 3 requestCallback.doWithRequest(request); 4 } 5 response = request.execute();
实际请求实例是InterceptingClientHttpRequest,execute实际是在它的父类中。
类定义位置:org.springframework.http.client.InterceptingClientHttpRequest
看一下它们的继承关系。
在execute方法中实际调用了子类实现的executeInternal方法。
1 public abstract class AbstractClientHttpRequest implements ClientHttpRequest { 2 3 private final HttpHeaders headers = new HttpHeaders(); 4 5 private boolean executed = false; 6 7 8 @Override 9 public final HttpHeaders getHeaders() { 10 return (this.executed ? HttpHeaders.readOnlyHttpHeaders(this.headers) : this.headers); 11 } 12 13 @Override 14 public final OutputStream getBody() throws IOException { 15 assertNotExecuted(); 16 return getBodyInternal(this.headers); 17 } 18 19 @Override 20 public final ClientHttpResponse execute() throws IOException { 21 assertNotExecuted(); 22 ClientHttpResponse result = executeInternal(this.headers); 23 this.executed = true; 24 return result; 25 } 26 27 /** 28 * Assert that this request has not been {@linkplain #execute() executed} yet. 29 * @throws IllegalStateException if this request has been executed 30 */ 31 protected void assertNotExecuted() { 32 Assert.state(!this.executed, "ClientHttpRequest already executed"); 33 } 34 35 36 /** 37 * Abstract template method that returns the body. 38 * @param headers the HTTP headers 39 * @return the body output stream 40 */ 41 protected abstract OutputStream getBodyInternal(HttpHeaders headers) throws IOException; 42 43 /** 44 * Abstract template method that writes the given headers and content to the HTTP request. 45 * @param headers the HTTP headers 46 * @return the response object for the executed request 47 */ 48 protected abstract ClientHttpResponse executeInternal(HttpHeaders headers) throws IOException; 49 50 }
其实就是InterceptingClientHttpRequest类的executeInternal方法,其中,又调用了一个执行器InterceptingRequestExecution的execute,通关判断如果有拦截器注入进来过,就调用拦截器的intercept方法。
这里的拦截器实际上就是在配置阶段注入进RestTemplate实例的负载均衡拦截器LoadBalancerInterceptor实例,可参考上面配置阶段的第2步。
1 class InterceptingClientHttpRequest extends AbstractBufferingClientHttpRequest { 2 3 private final ClientHttpRequestFactory requestFactory; 4 5 private final List<ClientHttpRequestInterceptor> interceptors; 6 7 private HttpMethod method; 8 9 private URI uri; 10 11 12 protected InterceptingClientHttpRequest(ClientHttpRequestFactory requestFactory, 13 List<ClientHttpRequestInterceptor> interceptors, URI uri, HttpMethod method) { 14 15 this.requestFactory = requestFactory; 16 this.interceptors = interceptors; 17 this.method = method; 18 this.uri = uri; 19 } 20 21 22 @Override 23 public HttpMethod getMethod() { 24 return this.method; 25 } 26 27 @Override 28 public String getMethodValue() { 29 return this.method.name(); 30 } 31 32 @Override 33 public URI getURI() { 34 return this.uri; 35 } 36 37 @Override 38 protected final ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException { 39 InterceptingRequestExecution requestExecution = new InterceptingRequestExecution(); 40 return requestExecution.execute(this, bufferedOutput); 41 } 42 43 44 private class InterceptingRequestExecution implements ClientHttpRequestExecution { 45 46 private final Iterator<ClientHttpRequestInterceptor> iterator; 47 48 public InterceptingRequestExecution() { 49 this.iterator = interceptors.iterator(); 50 } 51 52 @Override 53 public ClientHttpResponse execute(HttpRequest request, byte[] body) throws IOException { 54 if (this.iterator.hasNext()) { 55 ClientHttpRequestInterceptor nextInterceptor = this.iterator.next(); 56 return nextInterceptor.intercept(request, body, this); 57 } 58 else { 59 HttpMethod method = request.getMethod(); 60 Assert.state(method != null, "No standard HTTP method"); 61 ClientHttpRequest delegate = requestFactory.createRequest(request.getURI(), method); 62 request.getHeaders().forEach((key, value) -> delegate.getHeaders().addAll(key, value)); 63 if (body.length > 0) { 64 if (delegate instanceof StreamingHttpOutputMessage) { 65 StreamingHttpOutputMessage streamingOutputMessage = (StreamingHttpOutputMessage) delegate; 66 streamingOutputMessage.setBody(outputStream -> StreamUtils.copy(body, outputStream)); 67 } 68 else { 69 StreamUtils.copy(body, delegate.getBody()); 70 } 71 } 72 return delegate.execute(); 73 } 74 } 75 } 76 77 }
5.负载均衡拦截器调用负载均衡客户端
在负载均衡拦截器LoadBalancerInterceptor类的intercept方法中,又调用了负载均衡客户端LoadBalancerClient实现类的execute方法。
1 public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor { 2 3 private LoadBalancerClient loadBalancer; 4 5 private LoadBalancerRequestFactory requestFactory; 6 7 public LoadBalancerInterceptor(LoadBalancerClient loadBalancer, 8 LoadBalancerRequestFactory requestFactory) { 9 this.loadBalancer = loadBalancer; 10 this.requestFactory = requestFactory; 11 } 12 13 public LoadBalancerInterceptor(LoadBalancerClient loadBalancer) { 14 // for backwards compatibility 15 this(loadBalancer, new LoadBalancerRequestFactory(loadBalancer)); 16 } 17 18 @Override 19 public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, 20 final ClientHttpRequestExecution execution) throws IOException { 21 final URI originalUri = request.getURI(); 22 String serviceName = originalUri.getHost(); 23 Assert.state(serviceName != null, 24 "Request URI does not contain a valid hostname: " + originalUri); 25 return this.loadBalancer.execute(serviceName, 26 this.requestFactory.createRequest(request, body, execution)); 27 } 28 29 }
在配置阶段的第1步,可以看到实现类是RibbonLoadBalancerClient。
6.负载均衡客户端调用负载均衡策略选取目标服务实例并发起请求
在RibbonLoadBalancerClient的第一个execute方法以及getServer方法中可以看到,实际上是通过ILoadBalancer的负载均衡器实现类作的chooseServer方法选取一个服务,交给接下来的请求对象发起一个请求。
这里的负载均衡实现类默认是ZoneAwareLoadBalancer区域感知负载均衡器实例,其内部通过均衡策略选择一个服务。
ZoneAwareLoadBalancer的创建可以参考配置阶段的第4步。
1 public class RibbonLoadBalancerClient implements LoadBalancerClient { 2 3 private SpringClientFactory clientFactory; 4 5 public RibbonLoadBalancerClient(SpringClientFactory clientFactory) { 6 this.clientFactory = clientFactory; 7 } 8 9 @Override 10 public URI reconstructURI(ServiceInstance instance, URI original) { 11 Assert.notNull(instance, "instance can not be null"); 12 String serviceId = instance.getServiceId(); 13 RibbonLoadBalancerContext context = this.clientFactory 14 .getLoadBalancerContext(serviceId); 15 16 URI uri; 17 Server server; 18 if (instance instanceof RibbonServer) { 19 RibbonServer ribbonServer = (RibbonServer) instance; 20 server = ribbonServer.getServer(); 21 uri = updateToSecureConnectionIfNeeded(original, ribbonServer); 22 } 23 else { 24 server = new Server(instance.getScheme(), instance.getHost(), 25 instance.getPort()); 26 IClientConfig clientConfig = clientFactory.getClientConfig(serviceId); 27 ServerIntrospector serverIntrospector = serverIntrospector(serviceId); 28 uri = updateToSecureConnectionIfNeeded(original, clientConfig, 29 serverIntrospector, server); 30 } 31 return context.reconstructURIWithServer(server, uri); 32 } 33 34 @Override 35 public ServiceInstance choose(String serviceId) { 36 return choose(serviceId, null); 37 } 38 39 /** 40 * New: Select a server using a 'key'. 41 * @param serviceId of the service to choose an instance for 42 * @param hint to specify the service instance 43 * @return the selected {@link ServiceInstance} 44 */ 45 public ServiceInstance choose(String serviceId, Object hint) { 46 Server server = getServer(getLoadBalancer(serviceId), hint); 47 if (server == null) { 48 return null; 49 } 50 return new RibbonServer(serviceId, server, isSecure(server, serviceId), 51 serverIntrospector(serviceId).getMetadata(server)); 52 } 53 54 @Override 55 public <T> T execute(String serviceId, LoadBalancerRequest<T> request) 56 throws IOException { 57 return execute(serviceId, request, null); 58 } 59 60 /** 61 * New: Execute a request by selecting server using a 'key'. The hint will have to be 62 * the last parameter to not mess with the `execute(serviceId, ServiceInstance, 63 * request)` method. This somewhat breaks the fluent coding style when using a lambda 64 * to define the LoadBalancerRequest. 65 * @param <T> returned request execution result type 66 * @param serviceId id of the service to execute the request to 67 * @param request to be executed 68 * @param hint used to choose appropriate {@link Server} instance 69 * @return request execution result 70 * @throws IOException executing the request may result in an {@link IOException} 71 */ 72 public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint) 73 throws IOException { 74 ILoadBalancer loadBalancer = getLoadBalancer(serviceId); 75 Server server = getServer(loadBalancer, hint); 76 if (server == null) { 77 throw new IllegalStateException("No instances available for " + serviceId); 78 } 79 RibbonServer ribbonServer = new RibbonServer(serviceId, server, 80 isSecure(server, serviceId), 81 serverIntrospector(serviceId).getMetadata(server)); 82 83 return execute(serviceId, ribbonServer, request); 84 } 85 86 @Override 87 public <T> T execute(String serviceId, ServiceInstance serviceInstance, 88 LoadBalancerRequest<T> request) throws IOException { 89 Server server = null; 90 if (serviceInstance instanceof RibbonServer) { 91 server = ((RibbonServer) serviceInstance).getServer(); 92 } 93 if (server == null) { 94 throw new IllegalStateException("No instances available for " + serviceId); 95 } 96 97 RibbonLoadBalancerContext context = this.clientFactory 98 .getLoadBalancerContext(serviceId); 99 RibbonStatsRecorder statsRecorder = new RibbonStatsRecorder(context, server); 100 101 try { 102 T returnVal = request.apply(serviceInstance); 103 statsRecorder.recordStats(returnVal); 104 return returnVal; 105 } 106 // catch IOException and rethrow so RestTemplate behaves correctly 107 catch (IOException ex) { 108 statsRecorder.recordStats(ex); 109 throw ex; 110 } 111 catch (Exception ex) { 112 statsRecorder.recordStats(ex); 113 ReflectionUtils.rethrowRuntimeException(ex); 114 } 115 return null; 116 } 117 118 private ServerIntrospector serverIntrospector(String serviceId) { 119 ServerIntrospector serverIntrospector = this.clientFactory.getInstance(serviceId, 120 ServerIntrospector.class); 121 if (serverIntrospector == null) { 122 serverIntrospector = new DefaultServerIntrospector(); 123 } 124 return serverIntrospector; 125 } 126 127 private boolean isSecure(Server server, String serviceId) { 128 IClientConfig config = this.clientFactory.getClientConfig(serviceId); 129 ServerIntrospector serverIntrospector = serverIntrospector(serviceId); 130 return RibbonUtils.isSecure(config, serverIntrospector, server); 131 } 132 133 // Note: This method could be removed? 134 protected Server getServer(String serviceId) { 135 return getServer(getLoadBalancer(serviceId), null); 136 } 137 138 protected Server getServer(ILoadBalancer loadBalancer) { 139 return getServer(loadBalancer, null); 140 } 141 142 protected Server getServer(ILoadBalancer loadBalancer, Object hint) { 143 if (loadBalancer == null) { 144 return null; 145 } 146 // Use 'default' on a null hint, or just pass it on? 147 return loadBalancer.chooseServer(hint != null ? hint : "default"); 148 } 149 150 protected ILoadBalancer getLoadBalancer(String serviceId) { 151 return this.clientFactory.getLoadBalancer(serviceId); 152 } 153 154 /** 155 * Ribbon-server-specific {@link ServiceInstance} implementation. 156 */ 157 public static class RibbonServer implements ServiceInstance { 158 159 private final String serviceId; 160 161 private final Server server; 162 163 private final boolean secure; 164 165 private Map<String, String> metadata; 166 167 public RibbonServer(String serviceId, Server server) { 168 this(serviceId, server, false, Collections.emptyMap()); 169 } 170 171 public RibbonServer(String serviceId, Server server, boolean secure, 172 Map<String, String> metadata) { 173 this.serviceId = serviceId; 174 this.server = server; 175 this.secure = secure; 176 this.metadata = metadata; 177 } 178 179 @Override 180 public String getInstanceId() { 181 return this.server.getId(); 182 } 183 184 @Override 185 public String getServiceId() { 186 return this.serviceId; 187 } 188 189 @Override 190 public String getHost() { 191 return this.server.getHost(); 192 } 193 194 @Override 195 public int getPort() { 196 return this.server.getPort(); 197 } 198 199 @Override 200 public boolean isSecure() { 201 return this.secure; 202 } 203 204 @Override 205 public URI getUri() { 206 return DefaultServiceInstance.getUri(this); 207 } 208 209 @Override 210 public Map<String, String> getMetadata() { 211 return this.metadata; 212 } 213 214 public Server getServer() { 215 return this.server; 216 } 217 218 @Override 219 public String getScheme() { 220 return this.server.getScheme(); 221 } 222 223 @Override 224 public String toString() { 225 final StringBuilder sb = new StringBuilder("RibbonServer{"); 226 sb.append("serviceId='").append(serviceId).append('\''); 227 sb.append(", server=").append(server); 228 sb.append(", secure=").append(secure); 229 sb.append(", metadata=").append(metadata); 230 sb.append('}'); 231 return sb.toString(); 232 } 233 234 } 235 236 }
代码撸完,总结下。
普通使用RestTemplate请求其他服务时,内部使用的就是常规的http请求实例发送请求。
为RestTemplate增加了@LoanBalanced 注解后,实际上通过配置,为RestTemplate注入负载均衡拦截器,让负载均衡器选择根据其对应的策略选择合适的服务后,再发送请求。