您好,登錄后才能下訂單哦!
Ribbon——A ribbon is a long, narrow piece of cloth that you use for tying things together or as a decoration.
Ribbon是一個(gè)工具類框架,不需要獨(dú)立部署。
負(fù)載均衡設(shè)備/負(fù)載均衡軟件模塊都會(huì)維護(hù)一個(gè)可用的服務(wù)清單,通過(guò)心跳檢測(cè)來(lái)剔除故障節(jié)點(diǎn),保證清單中都是可用節(jié)點(diǎn)。
客戶端負(fù)載均衡,由客戶端節(jié)點(diǎn)維護(hù)要訪問(wèn)的服務(wù)清單,服務(wù)清單來(lái)自于注冊(cè)中心。
如前所示,使用客戶端負(fù)載均衡調(diào)用分兩步:
1. 服務(wù)提供者注冊(cè)到服務(wù)中心。
2. 服務(wù)消費(fèi)者通過(guò)標(biāo)有@LoadBalanced注解的RestTemplate進(jìn)行服務(wù)調(diào)用。
在service-consumer服務(wù)中,通過(guò)調(diào)用RestTemplate的getForEntity方法,GET調(diào)用hello-service的/hello接口。
RestTemplate
GET
RestTemplate有兩類GET實(shí)現(xiàn):getForEntity和getForObject。
getForEntity()有三個(gè)重載實(shí)現(xiàn),均返回ResponseEntity,
// url為請(qǐng)求地址,responseType為響應(yīng)體body的類型,uriVariables為url參數(shù)
// uriVariables配合url中的占位符進(jìn)行動(dòng)態(tài)傳參,如:
// entity = getForEntity("http://user-serivce/user?name={1}", String.class, "John");,將John傳給參數(shù)name
public ResponseEntity getForEntity(String url, Class responseType, Object... uriVariables) throws RestClientException {
RequestCallback requestCallback = acceptHeaderRequestCallback(responseType); // new AcceptHeaderRequestCallback(responseType)
ResponseExtractor> responseExtractor = responseEntityExtractor(responseType); // new ResponseEntityResponseExtractor<>(responseType)
return nonNull(execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables));
}
// uriVariables為Map類型,key需要與url中的占位符對(duì)應(yīng),如:
// params.put("myname", "John");
// entity = getForEntity("http://user-service/user?name={myname}", String.class, params); 將key為myname對(duì)應(yīng)的value——John傳給name
public ResponseEntity getForEntity(String url, Class responseType, Map uriVariables);
// 使用URI對(duì)象代替url和uriVariables
public ResponseEntity getForEntity(URI url, Class responseType);
// 使用:
ResponseEntity entity = restTemplate.getForEntity(url, String.class, "John");
String body = entity.getBody();
ResponseEntity entity = restTemplate.getForEntity(url, User.class, "John");
User body = entity.getBody();
getForObject()也有三個(gè)重載實(shí)現(xiàn),傳入execute方法的不是ResponseExtractor,而是HttpMessageConverterExtractor,返回的則是對(duì)象類型,三個(gè)重載和getForEntity的三個(gè)重載關(guān)系類似:
public T getForObject(String url, Class responseType, Object... uriVariables) throws RestClientException {
RequestCallback requestCallback = acceptHeaderRequestCallback(responseType); // new AcceptHeaderRequestCallback(responseType)
HttpMessageConverterExtractor responseExtractor = new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger);
return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables);
}
public T getForObject(String url, Class responseType, Map uriVariables);
public T getForObject(URI url, Class responseType);
// 使用:
String result = restTemplate.getForObject(url, String.class, "John");
User user = restTempleate.getForObject(url, User.class, "John");
// 使用getForObject可以省略從response中獲取body的步驟
POST
RestTemplate有三類POST實(shí)現(xiàn):postForEntity和postForObject,postForLocation。
postForEntity()有三個(gè)重載實(shí)現(xiàn),均返回ResponseEntity,
// 相較于getForEntity,新增參數(shù)Object request,reqeust如果是HttpEntity對(duì)象,RestTemplate將其當(dāng)作完整的http請(qǐng)求對(duì)象處理,request中包含了header和body的內(nèi)容。如果request是普通對(duì)象,RestTemplate將其轉(zhuǎn)換為HttpEntity來(lái)處理,request作為body。
// if (request instanceof HttpEntity){this.requestEntity = (HttpEntity) request; }
// else if (requestBody != null) { this.requestEntity = new HttpEntity<>(request); }
// else { this.requestEntity = HttpEntity.EMPTY; }
// 使用:
// User user = new User("didi", 30);
// entity = postForEntity("http://user-serivce/user", user, String.class, "John");,將John傳給參數(shù)name
public ResponseEntity postForEntity(String url, Object request, Class responseType, Object... uriVariables) throws RestClientException {
RequestCallback requestCallback = httpEntityCallback(request, responseType); // new HttpEntityRequestCallback(requestBody, responseType)
ResponseExtractor> responseExtractor = responseEntityExtractor(responseType); // new ResponseEntityResonseExtracor<>(responseType)
return nonNull(execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables));
}
public ResponseEntity postForEntity(String url, Object request, Class responseType, Map uriVariables);
public ResponseEntity postForEntity(URI url, Object request, Class responseType);
postForObject()也有三個(gè)重載實(shí)現(xiàn),傳入execute方法的不是ResponseExtractor,而是HttpMessageConverterExtractor,返回的則是對(duì)象類型,三個(gè)重載和postForEntity的三個(gè)重載關(guān)系類似:
public T postForObject(String url, Object request, Class responseType, Object... uriVariables) throws RestClientException {
RequestCallback requestCallback = httpEntityCallback(request, responseType);
HttpMessageConverterExtractor responseExtractor = new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger);
return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables);
}
public T postForObject(String url, Object request, Class responseType, Map uriVariables);
public T postForObject(URI url, Object request, Class responseType);
postForLocation()用于發(fā)送post請(qǐng)求,返回新資源的URI,有三個(gè)重載實(shí)現(xiàn),均返回URI對(duì)象,
public URI postForLocation(String url, Object request, Object... uriVariables) throws RestClientException {
RequestCallback requestCallback = httpEntityCallback(request); // new HttpEntityRequestCallback(request, null)
HttpHeaders headers = execute(url, HttpMethod.POST, requestCallback, headersExtractor(), uriVariables); // new HeadersExtractor()
return (headers != null ? headers.getLocation() : null);
}
public URI postForLocation(String url, Object request, Map uriVariables);
public URI postForLocation(URI url, Object ruquest);
execute
RestTemplate中,不同的請(qǐng)求方式,最終會(huì)調(diào)用到execute的三個(gè)重載實(shí)現(xiàn)上來(lái)
// ------------------------------------
public T execute(String url, HttpMethod method, RequestCallback requestCallback, ResponseExtractor responseExtractor, Object... uriVariables) {
URI expanded = getUriTemplateHandler().expand(url, uriVariables);
return doExecute(expanded, method, requestCallback, responseExtractor);
}
public T execute(String url, HttpMethod method, RequestCallback requestCallback, ResponseExtractor responseExtractor, Map uriVariables);
public T execute(URI url, HttpMethod method, RequestCallback requestCallback, ResponseExtractor responseExtractor);
execute()的三個(gè)重載實(shí)現(xiàn),都會(huì)調(diào)用doExecute()方法,去執(zhí)行請(qǐng)求
protected T doExecute(URI url, HttpMethod method, RequestCallback requestCallback, ResponseExtractor responseExtractor) throws RestClientException {
ClientHttpResponse response = null;
ClientHttpRequest request = createRequest(url, method);
if (requestCallback != null) { requestCallback.doWithRequest(request); }
response = request.execute();// 此處執(zhí)行前會(huì)被攔截
handleResponse(url, method, response);
return (responseExtractor != null ? responseExtractor.extractData(response) : null);
}
doExecute()方法接收的參數(shù)中,有RequestCallback和ResponseExtractor。
RequestCallback
AcceptHeaderRequestCallback implements RequestCallback // AcceptHeaderRequestCallback用于GET請(qǐng)求
HttpEntityRequestCallback extends AcceptHeaderRequestCallback // HttpEntityRequestCallback 用于POST、PUT等請(qǐng)求
ResponseEntity
// ResponseEntity擴(kuò)展自HttpEntity,增加了http的status(http請(qǐng)求狀態(tài)碼)
package org.springframework.http;
public class ResponseEntity extends HttpEntity {
private final Object status; // status為int或HttpStatus類型
// getter/setter...
}
// HttpEntity表示http的request或response的entity,包含headers(http請(qǐng)求的頭信息)和body(http請(qǐng)求的請(qǐng)求體)
package org.springframework.http;
public class HttpEntity {
private final HttpHeaders headers;
private final T body;
// getter/setter...
}
@LoadBalanced
在服務(wù)消費(fèi)者中,給RestTemplate添加了@LoadBalanced注解,根據(jù)注釋,該注解用于標(biāo)記RestTemplate使用LoadBalancerClient來(lái)配置,即客戶端負(fù)載均衡器。
// Annotation to mark a RestTemplate bean to be configured to use a LoadBalancerClient.
public @interface LoadBalanced {}
LoadBalancerClient
客戶端負(fù)載均衡器,具有如下能力:
// Represents a client-side load balancer. 即客戶端負(fù)載均衡器
interface LoadBalancerClient extends ServiceInstanceChooser {
// 使用serviceId服務(wù)執(zhí)行request請(qǐng)求
T execute(String serviceId, LoadBalancerRequest request) throws IOException;
T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest request) throws IOException;
// 將邏輯服務(wù)名http://myservice/path/to/service 替換為host:port的形式
URI reconstructURI(ServiceInstance instance, URI original);
}
// 選擇一個(gè)server用來(lái)發(fā)送請(qǐng)求的實(shí)現(xiàn)接口
interface ServiceInstanceChooser {
// 根據(jù)serviceId,從負(fù)載均衡器選擇一個(gè)服務(wù)實(shí)例ServiceInstance
ServiceInstance choose(String serviceId);
}
LoadBalancerClient有一個(gè)實(shí)現(xiàn)類RibbonLoadBalancerClient。
在RestTemplate的doExecute()方法中,調(diào)用request.execute()之前,會(huì)被LoadBalancerInterceptor攔截。該攔截器中有一個(gè)LoadBalancerClient實(shí)例,此外該攔截器在LoadBalancerAutoConfiguration中被創(chuàng)建。而LoadBalancerAutoConfiguration有兩個(gè)特殊的注解@ConditionalOnClass(RestTemplate.class)和@ConditionalOnBean(LoadBalancerClient.class),且注釋明確說(shuō)明LoadBalancerAutoConfiguration為Ribbon的自動(dòng)化配置類。
spring-cloud-commons的loadbalancer包中的配置類,以2.1.2為例
LoadBalancerAutoConfiguration:創(chuàng)建LoadBalancerInterceptor、創(chuàng)建RestTemplateCustomizer(匿名內(nèi)部類)、創(chuàng)建LoadBalancerRequestFactory、創(chuàng)建SmartInitializingSingleton(匿名內(nèi)部類)
AsyncLoadBalancerAutoConfiguration:針對(duì)AsyncRestTemplate做的類似配置
spring-cloud-netflix-ribbon中的幾個(gè)配置類,以2.1.2為例
RibbonClientConfiguration:創(chuàng)建IClientConfig、創(chuàng)建IRule,創(chuàng)建IPing,創(chuàng)建ServerList,創(chuàng)建ServerListUpdater,創(chuàng)建ILoadBalancer(使用ZoneAwareLoadBalancer實(shí)現(xiàn)),創(chuàng)建ServerListFilter、創(chuàng)建RibbonLoadBalancerContext,創(chuàng)建RetryHandler,創(chuàng)建ServerIntrospector
RibbonAutoConfiguration:創(chuàng)建HasFeatures,創(chuàng)建SpringClientFactory,創(chuàng)建LoadBalancerClient(使用RibbonLoadBalancerClient實(shí)現(xiàn)),創(chuàng)建LoadBalancedRetryFactory(使用RibbonLoadBalancedRetryFactory實(shí)現(xiàn)),創(chuàng)建PropertiesFactory,創(chuàng)建RibbonApplicationContextInitializer,創(chuàng)建RestTemplateCustomizer(使用匿名內(nèi)部類),創(chuàng)建RibbonClientHttpRequestFactory
RestCilentRibbonConfiguration:創(chuàng)建RestClient
LoadBalancerAutoConfiguration
Ribbon的自動(dòng)化配置類:
@Configuration
@ConditionalOnClass(RestTemplate.class) // 需要RestTemplate類在classpath中
@ConditionalOnBean(LoadBalancerClient.class) // 需要LoadBalancerClient的實(shí)現(xiàn)Bean在BeanFactory中
@EnableConfigurationProperties(LoadBalancerRetryProperties.class)
class LoadBalancerAutoConfiguration {
@LoadBalanced
@Autowired(required = false)
// 工程中注冊(cè)的RestTemplate的Bean會(huì)在此被加載
private List restTemplates = Collections.emptyList();
@Autowired(required = false)
private List transformers = Collections.emptyList();
// 創(chuàng)建SmartInitializingSingleton的Bean,負(fù)責(zé)用每個(gè)Customizer去修飾每個(gè)RestTemplate
@Bean
public SmartInitializingSingleton loadBalancedRestTemplateInitializerDeprecated(
ObjectProvider> restTemplateCustomizers) {
return () -> restTemplateCustomizers.ifAvailable(customizers -> {
for (RestTemplate restTemplate : LoadBalancerAutoConfiguration.this.restTemplates) {
for (RestTemplateCustomizer customizer : customizers) {
customizer.customize(restTemplate);
}
}
});
}
@Configuration
@ConditionalOnMissingClass("org.springframework.retry.support.RetryTemplate")
static class LoadBalancerInterceptorConfig {
// 創(chuàng)建攔截器Bean,入?yún)榭蛻舳素?fù)載均衡器
@Bean
public LoadBalancerInterceptor ribbonInterceptor(LoadBalancerClient loadBalancerClient, LoadBalancerRequestFactory requestFactory) {
return new LoadBalancerInterceptor(loadBalancerClient, requestFactory);
}
// 創(chuàng)建一個(gè)RestTemplateCustomizer的Bean,負(fù)責(zé)將負(fù)載均衡攔截器加到入?yún)estTemplate的攔截器列表中,添加方式為get、add、set
@Bean
@ConditionalOnMissingBean
public RestTemplateCustomizer restTemplateCustomizer(final LoadBalancerInterceptor loadBalancerInterceptor) {
return restTemplate -> {
List list = new ArrayList<>(restTemplate.getInterceptors());
list.add(loadBalancerInterceptor);
restTemplate.setInterceptors(list);
}
}
}
}
LoadBalancerInterceptor
負(fù)載均衡攔截器,用于在請(qǐng)求最終執(zhí)行前進(jìn)行攔截,在攔截器的intercept()方法中,首先從request中獲取服務(wù)名稱serviceName,然后調(diào)用request工廠的createRequest()方法,創(chuàng)建一個(gè)負(fù)載均衡的request——LoadBalancerRequest實(shí)例,最后將其連同serviceName一起作為L(zhǎng)oadBalancerClient的execute()方法的入?yún)ⅰ?/p>
class LoadBalancerInterceptor implements ClientHttpRequestInterceptor {
LoadBalancerClient loadBalancer;
LoadBalancerRequestFactory requestFactory;
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) {
// 此處調(diào)用request的getURI方法,
final URI originalUri = request.getURI();
String serviceName = originalUri.getHost();
return this.loadBalancer.execute(serviceName, this.requestFactory.createRequest(request, body, execution));
}
}
LoadBalancerRequestFactory——?jiǎng)?chuàng)建LoadBalancerRequest的工廠
public LoadBalancerRequest createRequest(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) {
// 返回LoadBalancerRequest的匿名內(nèi)部類
return instance -> {
// 該LoadBalancerRequest的匿名內(nèi)部類實(shí)現(xiàn),先創(chuàng)建一個(gè)ServiceRequestWrapper的request,然后調(diào)用execution的execute方法執(zhí)行請(qǐng)求
HttpRequest serviceRequest = new ServiceRequestWrapper(request, instance, this.loadBalancer);
return execution.execute(serviceRequest, body);
};
}
LoadBalancerRequest
LoadBalancerRequest使用該接口的apply()的方法,為request添加處理動(dòng)作
interface LoadBalancerRequest {
T apply(ServiceInstance instance);
}
ServiceRequestWrapper
ServiceRequestWrapper繼承自HttpRequestWrapper,HttpRequestWrapper對(duì)外提供了獲取一個(gè)request的method、URI、headers、methodValue等信息的方法。
ServiceRequestWrapper改寫了默認(rèn)的getURI()方法,使用客戶端負(fù)載均衡器LoadBalancerClient的重構(gòu)URI的方法,將入?yún)equest的URI進(jìn)行重構(gòu),其具體實(shí)現(xiàn)在LoadBalancerClient的實(shí)現(xiàn)類RibbonLoadBalancerClient中。
class ServiceRequestWrapper extends HttpRequestWrapper {
private final ServiceInstance instance;
private final LoadBalancerClient loadBalancer;
public ServiceRequestWrapper(HttpRequest request, ServiceInstance instance, LoadBalancerClient loadBalancer) {}
@Override
public URI getURI() {
// 調(diào)用loadBalancer的reconstructURI方法,進(jìn)行URI重構(gòu),改寫成host:port的形式,具體實(shí)現(xiàn)在RibbonLoadBalancerClient中
return this.loadBalancer.reconstructURI(this.instance, getRequest().getURI());
}
}
RibbonLoadBalancerClient
RibbonLoadBalancerClient實(shí)現(xiàn)了LoadBalancerClient和ServiceInstanceChooser中的execute、reconstructURI、choose方法,完成了請(qǐng)求執(zhí)行、URI重構(gòu)和選擇服務(wù)實(shí)例的任務(wù),execute
class RibbonLoadBalancerClient implements LoadBalancerClient {
SpringClientFactory clientFactory;
@Override
public URI reconstructURI(ServiceInstance instance, URI original) {
String serviceId = instance.getServiceId();
RibbonLoadBalancerContext context = this.clientFactory.getLoadBalancerContext(serviceId);
URI uri; Server server;
if (instance instanceof RibbonServer) {
server = ((RibbonServer) instance).getServer();
uri = updateToSecureConnectionIfNeeded(original, ribbonServer);
} else {
server = new Server(instance.getScheme(), instance.getHost(), instance.getPort());
IClientConfig clientConfig = clientFactory.getClientConfig(serviceId);
ServerIntrospector serverIntrospector = serverIntrospector(serviceId);
uri = updateToSecureConnectionIfNeeded(original, clientConfig, serverIntrospector, server);
}
// 用server中的host、port等替換原始uri
return context.reconstructURIWithServer(server, uri);
}
public ServiceInstance choose(String serviceId, Object hint) {
// 先調(diào)用getLoadBalancer方法,根據(jù)serviceId,獲取一個(gè)ILoadBalancer
// 然后調(diào)用getServer(ILoadBalancer loadBalancer, Object hint),使用loadBalancer選擇一個(gè)Server,hint默認(rèn)為"default"
Server server = getServer(getLoadBalancer(serviceId), hint);
if (server == null) { return null; }
// 用入?yún)erviceId、選擇的Server,構(gòu)造一個(gè)RibbonServer
return new RibbonServer(serviceId, server, isSecure(server, serviceId), serverIntrospector(serviceId).getMetadata(server));
}
public T execute(String serviceId, LoadBalancerRequest request, Object hint) {
// 首先選擇一個(gè)RibbonServer,該部分流程與choose相同
Server server = getServer(getLoadBalancer(serviceId), hint);
RibbonServer ribbonServer = new RibbonServer(serviceId, server, isSecure(server, serviceId), serverIntrospector(serviceId).getMetadata(server));
// 調(diào)用execute的重載實(shí)現(xiàn),執(zhí)行請(qǐng)求
return execute(serviceId, ribbonServer, request);
}
public T execute(String serviceId, ServiceInstance serviceIntance, LoadBalancerRequest request) {
Server server = null;
if (serviceInstance instanceof RibbonServer) {
server = ((RibbonServer) serviceInstance).getServer();
}
RibbonLoadBalancerContext context = this.clientFactory.getLoadBalancerContext(serviceId);
RibbonStatsRecorder statsRecorder = new RibbonStatsRecorder(context, server);
try { 無(wú)錫做人流手術(shù)多少錢 http://www.ytsg029.com/
// 調(diào)用apply,向服務(wù)實(shí)例發(fā)起請(qǐng)求
T returnVal = request.apply(serviceInstance);
statsRecorder.recordStats(returnVal);
return returnVal;
} catch (IOException ex) {
statsRecorder.recordStats(ex); throw ex;
} catch (Exception ex) {
statsRecorder.recordStats(ex); throw ex;
}
return null;
}
// Ribbon 實(shí)現(xiàn)了ServiceInstance接口,即服務(wù)實(shí)例接口
public static class RibbonServer implements ServiceInstance {
private final String serviceId;
private final Server server;
private final boolean secure;
private Map metadata;
// @Override方法
}
}
ILoadBalancer
在RibbonLoadBalancerClient的choose()和execute()方法中,都是通過(guò)調(diào)用ILoadBalancer的chooseServer()方法,來(lái)選擇一個(gè)服務(wù)實(shí)例Server的,該ILoadBalancer接口是由Ribbon定義的。
在ILoadBalancer接口中,定義了軟件負(fù)載均衡器的操作:一個(gè)服務(wù)實(shí)例的集合、標(biāo)記一個(gè)服務(wù)停止、選擇服務(wù)
package com.netflix.loadbalancer;
interface ILoadBalancer {
void addServers(List newServers); // 初始化、后續(xù)添加服務(wù)列表
Server chooseServer(Object key); // 從負(fù)載均衡器選擇一個(gè)服務(wù)實(shí)例
void markServerDown(Server server); // 標(biāo)記并通知某個(gè)服務(wù)實(shí)例已經(jīng)停止
List getReachableServers(); // up/reachable狀態(tài)的服務(wù)實(shí)例,可以提供正常服務(wù)
List getAllServers(); // 所有已知的服務(wù)實(shí)例,reachable/unreachable都包括
}
其中的Server,代表一個(gè)服務(wù)端節(jié)點(diǎn),包含了一個(gè)服務(wù)的基本信息:host、port、scheme、id、zone、元數(shù)據(jù)等等。
在RibbonLoadBalancerClient的choose()和execute()方法中,通過(guò)getLoadBalancer()方法,來(lái)根據(jù)serviceId獲取ILoadBalancer的實(shí)例,然后將其包裝成RibbonServer。
配置類RibbonClientConfiguration創(chuàng)建ILoadBalancer時(shí)如果配置文件里有配置,則使用配置的實(shí)現(xiàn),否則默認(rèn)使用ZoneAwareLoadBalancer實(shí)現(xiàn)。
ClientHttpRequestExecution
RibbonLoadBalancerClient的execute()方法中,調(diào)用了入?yún)oadBalancerRequest的apply方法,execute()方法在LoadBlancerInterceptor的intercept方法中調(diào)用,并傳入LoadBalancerRequestFactory.createRequest創(chuàng)建的LoadBalancerRequest實(shí)現(xiàn),其實(shí)現(xiàn)中最終使用ClientHttpRequestExecution的execute方法執(zhí)行請(qǐng)求。
總結(jié)
使用時(shí),注冊(cè)一個(gè)使用@LoadBalanced注解修飾的RestTemplate,在需要發(fā)起請(qǐng)求的地方調(diào)用RestTemplate的相應(yīng)的請(qǐng)求方法,最終調(diào)用到其doExecute方法。
@LoadBalanced注解關(guān)聯(lián)了LoadBalancerClient。
配置類LoadBalancerAutoConfiguration注冊(cè)了如下Bean:
SmartInitializingSingleton:遍歷restTemplates、遍歷customizers,并customizer.customize(restTemplate)
LoadBalancerRequestFactory:使用LoadBalancerClient構(gòu)造
LoadBalancerInterceptor:使用LoadBalancerClient和LoadBalancerRequestFactory創(chuàng)建
RestTemplateCustomizer:使用LoadBalancerInterceptor構(gòu)造一個(gè)匿名類,將注冊(cè)的LoadBalancerInterceptor添加進(jìn)restTemplate的interceptors列表中
攔截器LoadBalancerInterceptor的intercept方法從原始請(qǐng)求中獲取URI,然后使用LoadBalancerClient的execute方法執(zhí)行請(qǐng)求,接收兩個(gè)參數(shù):serviceName即host和請(qǐng)求工廠創(chuàng)建的request
請(qǐng)求工廠LoadBalancerRequestFactory的createRequest方法,由原始請(qǐng)求創(chuàng)建一個(gè)LoadBalancerRequest的匿名實(shí)現(xiàn)
負(fù)載均衡請(qǐng)求LoadBalancerRequest接口只有apply方法,其匿名實(shí)現(xiàn)創(chuàng)建HttpRequest的實(shí)現(xiàn)類ServcieRequestWrapper的實(shí)例,然后由ClientHttpRequestExecution的execute方法執(zhí)行請(qǐng)求,返回響應(yīng)ClientHttpResponse
ServiceRequestWrapper重寫了父類HttpRequestWrapper的getURI方法,返回LoadBalancerClient的reconstructURI方法重構(gòu)的URI
ClientHttpRequestExecution的實(shí)現(xiàn)類是InterceptingClientHttpRequest的內(nèi)部類IntercpetingRequestExecution,其execute方法遍歷interceptors,如果有攔截器,就執(zhí)行攔截方法,如果沒(méi)有了,就執(zhí)行請(qǐng)求。
在4中,LoadBalancerClient的execute方法執(zhí)行請(qǐng)求,其實(shí)現(xiàn)類是RibbonLoadBalancerClient。execute 先通過(guò)serviceId獲取ILoadBalancer,然后調(diào)用ILoadBalancer的chooseServer方法,選擇一個(gè)Server,并將之轉(zhuǎn)換成RibbonServer,RibbonServer是ServiceInstance的子類,最后調(diào)用LoadBalancerRequest的apply方法,執(zhí)行請(qǐng)求,返回響應(yīng)。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。