東莞手機(jī)網(wǎng)站建設(shè)網(wǎng)站怎么優(yōu)化關(guān)鍵詞
背景
從SpringCloud 2020 版本之后,組件移除了除 Eureka 以外,所有 Netflix 的相關(guān),包括最常用的 Ribbon Hystrix 等,所以 SpringCloud 在 spring-cloud-commons 提供了Loadbalancer 用來替代 Ribbon。本系列就來介紹Loadbalancer 的執(zhí)行流程
項(xiàng)目版本:
Spring-Boot
2.6.13Spring-Cloud
2021.0.5spring-cloud-alibaba
2021.0.5.0Loadbalancer
3.1.5
從項(xiàng)目中最常用的Feign來當(dāng)做入口,不了解Feign的原理也沒有關(guān)系,直接從Feign和Loadbalancer 的集成部分分析即可
分析
入口處
FeignBlockingLoadBalancerClient
public class FeignBlockingLoadBalancerClient implements Client {private static final Log LOG = LogFactory.getLog(FeignBlockingLoadBalancerClient.class);private final Client delegate;private final LoadBalancerClient loadBalancerClient;private final LoadBalancerClientFactory loadBalancerClientFactory;@Overridepublic Response execute(Request request, Request.Options options) throws IOException {//請求路徑final URI originalUri = URI.create(request.url());//獲取到要調(diào)用的服務(wù)idString serviceId = originalUri.getHost();DefaultRequest<RequestDataContext> lbRequest = new DefaultRequest<>(new RequestDataContext(buildRequestData(request), hint)); Set<LoadBalancerLifecycle> supportedLifecycleProcessors = LoadBalancerLifecycleValidator.getSupportedLifecycleProcessors(//在這步創(chuàng)建了每個(gè)服務(wù)的子容器 loadBalancerClientFactory.getInstances(serviceId, LoadBalancerLifecycle.class),RequestDataContext.class, ResponseData.class, ServiceInstance.class);supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onStart(lbRequest)); //執(zhí)行l(wèi)oadBalancer的負(fù)載均衡策略,返回將過濾后的服務(wù),非常重要ServiceInstance instance = loadBalancerClient.choose(serviceId, lbRequest);org.springframework.cloud.client.loadbalancer.Response<ServiceInstance> lbResponse = new DefaultResponse(instance);//省略...//將ServiceInstance進(jìn)行解析后,轉(zhuǎn)換為真正的http方式進(jìn)行遠(yuǎn)程調(diào)用服務(wù)String reconstructedUrl = loadBalancerClient.reconstructURI(instance, originalUri).toString();Request newRequest = buildRequest(request, reconstructedUrl);LoadBalancerProperties loadBalancerProperties = loadBalancerClientFactory.getProperties(serviceId);return executeWithLoadBalancerLifecycleProcessing(delegate, options, newRequest, lbRequest, lbResponse,supportedLifecycleProcessors, loadBalancerProperties.isUseRawStatusCodeInResponseData());}protected Request buildRequest(Request request, String reconstructedUrl) {return Request.create(request.httpMethod(), reconstructedUrl, request.headers(), request.body(),request.charset(), request.requestTemplate());}private String getHint(String serviceId) {LoadBalancerProperties properties = loadBalancerClientFactory.getProperties(serviceId);String defaultHint = properties.getHint().getOrDefault("default", "default");String hintPropertyValue = properties.getHint().get(serviceId);return hintPropertyValue != null ? hintPropertyValue : defaultHint;}}
可以看到,在OpenFeign中調(diào)用了loadBalancerClient.choose(serviceId, lbRequest)
來實(shí)現(xiàn)負(fù)載均衡策略,然后返回過濾后的服務(wù)ServiceInstance
,也就是服務(wù)的對象。我們要重點(diǎn)分析此過程
首先分析loadBalancerClient
是怎么注入進(jìn)來的呢,我們先看下其結(jié)構(gòu)
ServiceInstanceChooser
public interface ServiceInstanceChooser {ServiceInstance choose(String serviceId);<T> ServiceInstance choose(String serviceId, Request<T> request);}
LoadBalancerClient
public interface LoadBalancerClient extends ServiceInstanceChooser {<T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException;<T> T execute(String serviceId, ServiceInstance serviceInstance, LoadBalancerRequest<T> request) throws IOException;URI reconstructURI(ServiceInstance instance, URI original);}
可以看到ServiceInstanceChooser
定義了負(fù)載均衡的方法, LoadBalancerClient
則繼承了ServiceInstanceChooser
額外定義了execute
執(zhí)行和reconstructURI
構(gòu)建真正http請求的方法
那么LoadBalancerClient
的實(shí)現(xiàn)是誰呢,剛才的疑問中又是怎么被注入的呢,其實(shí)LoadBalancerClient
的實(shí)現(xiàn)是BlockingLoadBalancerClient
,在配置類BlockingLoadBalancerClientAutoConfiguration
中被注入
這里既然提到了自動(dòng)裝配配置類,那么我們就需要看下其結(jié)構(gòu),來了解各個(gè)作用
# AutoConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.loadbalancer.config.LoadBalancerAutoConfiguration,\
org.springframework.cloud.loadbalancer.config.BlockingLoadBalancerClientAutoConfiguration,\
org.springframework.cloud.loadbalancer.config.LoadBalancerCacheAutoConfiguration,\
org.springframework.cloud.loadbalancer.security.OAuth2LoadBalancerClientAutoConfiguration,\
org.springframework.cloud.loadbalancer.config.LoadBalancerStatsAutoConfiguration
LoadBalancerAutoConfiguration
是最核心最重要的配置,隨后會(huì)詳細(xì)的分析BlockingLoadBalancerClientAutoConfiguration
上文中提高的LoadBalancerClient
的實(shí)現(xiàn)類BlockingLoadBalancerClient
就是在此裝配的
BlockingLoadBalancerClientAutoConfiguration
@Configuration(proxyBeanMethods = false)
@LoadBalancerClients
@AutoConfigureAfter(LoadBalancerAutoConfiguration.class)
@AutoConfigureBefore({ org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration.class,AsyncLoadBalancerAutoConfiguration.class })
@ConditionalOnClass(RestTemplate.class)
public class BlockingLoadBalancerClientAutoConfiguration {@Bean@ConditionalOnBean(LoadBalancerClientFactory.class)@ConditionalOnMissingBeanpublic LoadBalancerClient blockingLoadBalancerClient(LoadBalancerClientFactory loadBalancerClientFactory) {return new BlockingLoadBalancerClient(loadBalancerClientFactory);}//省略}
可以看到注入了LoadBalancerClient
的實(shí)現(xiàn)類BlockingLoadBalancerClient
。但此自動(dòng)配置類的裝配有很多的規(guī)則:
@LoadBalancerClients
此注解非常重要,實(shí)現(xiàn)每個(gè)服務(wù)間的負(fù)載均衡配置隔離就是通過此注解,后面會(huì)詳細(xì)的分析@AutoConfigureAfter(LoadBalancerAutoConfiguration.class)
在LoadBalancerAutoConfiguration
之后進(jìn)行裝配,LoadBalancerAutoConfiguration
也很重要,后面也會(huì)詳細(xì)的分析@AutoConfigureBefore({ org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration.class, AsyncLoadBalancerAutoConfiguration.class })
在org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration
和AsyncLoadBalancerAutoConfiguration
之前進(jìn)行裝配。注意:2和3中的LoadBalancerAutoConfiguration不是一個(gè)對象,2中的是在spring-cloud-loadbalancer模塊中,3中的是在spring-cloud-commons模塊中,這也是有步驟2的原因,畢竟肯定是要先裝配本模塊下的@ConditionalOnClass(RestTemplate.class)
這個(gè)不是重點(diǎn),可以略過@ConditionalOnBean(LoadBalancerClientFactory.class)
在注入時(shí)依賴了LoadBalancerClientFactory
,LoadBalancerClientFactory
也非常的重要,后面也會(huì)進(jìn)行詳細(xì)的分析
上面多次提到了LoadBalancerAutoConfiguration
,自動(dòng)裝配中也有它,那么現(xiàn)在就來分析下其流程
LoadBalancerAutoConfiguration
@Configuration(proxyBeanMethods = false)
@LoadBalancerClients
@EnableConfigurationProperties(LoadBalancerClientsProperties.class)
@AutoConfigureBefore({ ReactorLoadBalancerClientAutoConfiguration.class,LoadBalancerBeanPostProcessorAutoConfiguration.class })
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.enabled", havingValue = "true", matchIfMissing = true)
public class LoadBalancerAutoConfiguration {//依賴了LoadBalancerClientSpecification類型的對象集合private final ObjectProvider<List<LoadBalancerClientSpecification>> configurations;public LoadBalancerAutoConfiguration(ObjectProvider<List<LoadBalancerClientSpecification>> configurations) {this.configurations = configurations;}@Bean@ConditionalOnMissingBeanpublic LoadBalancerZoneConfig zoneConfig(Environment environment) {return new LoadBalancerZoneConfig(environment.getProperty("spring.cloud.loadbalancer.zone"));}@ConditionalOnMissingBean@Beanpublic LoadBalancerClientFactory loadBalancerClientFactory(LoadBalancerClientsProperties properties) {LoadBalancerClientFactory clientFactory = new LoadBalancerClientFactory(properties);//LoadBalancerClientSpecification類型的配置類集合對象注入到NamedContextFactory,實(shí)現(xiàn)個(gè)性化配置clientFactory.setConfigurations(this.configurations.getIfAvailable(Collections::emptyList));return clientFactory;}}
可以看到此配置類的裝配規(guī)則也比較復(fù)雜,但大部分都和本系列要分析的內(nèi)容關(guān)聯(lián)性不大,直接略過即可,我們只關(guān)心兩個(gè)地方
@LoadBalancerClients
這個(gè)注解出現(xiàn)多次,我們會(huì)做詳細(xì)的分析- 注入了
loadBalancerClientFactory
,這個(gè)也非常的重要,隨后會(huì)做詳細(xì)的分析
到這里我們要解決的三個(gè)重點(diǎn):
@LoadBalancerClients
的作用ObjectProvider<List<LoadBalancerClientSpecification>> configurations
的作用LoadBalancerClientFactory
的作用,別忘了負(fù)載均衡的執(zhí)行對象BlockingLoadBalancerClient
在生成時(shí),將此對象注入了進(jìn)去
下一篇文章我們進(jìn)行詳細(xì)分析