Spring 原始碼解析十五:SpringCloud 的基礎元件
SpringCloud
並不是只有一個專案,而是很多專案構成的生態體系總稱,如
- spring-cloud-netflix: 對 https://github.com/netflix 開源元件的整合
- spring-cloud-gateway: 閘道器
- spring-cloud-kubernetes: 對 kubernetes 的整合
- spring-cloud-config: 分散式配置
- spring-cloud-sleuth: 分散式鏈路跟蹤
- spring-cloud-openfeign: 服務呼叫
但這些專案都依賴一個基礎專案 spring-cloud-commons,
spring-cloud-commons
主要有 3 個模組
spring-cloud-context
:構建一個 Bootstrap 容器,並讓其成為原有的 SpringBoot 程式構建的容器的父容器,所以使用 SpringCloud 的方式與 SpringBoot 是差不多的spring-cloud-commons
:對微服務中的服務註冊與發現、負載均衡、熔斷器等功能提供一個抽象層程式碼,這個抽象層與具體的實現無關,這些功能可以採用不同的技術去實現spring-cloud-loadbalancer
:一個客戶端負載均衡器,類似於 Ribbon,用於替換 Ribbon(Ribbon 已經進入維護模式)
1. spring-cloud-context
元件的載入仍然是通過 Spring Factories 擴充套件載入機制載入的,定在 spring.factories
# 屬性自動裝配
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration,\
org.springframework.cloud.autoconfigure.LifecycleMvcEndpointAutoConfiguration,\
org.springframework.cloud.autoconfigure.RefreshAutoConfiguration,\
org.springframework.cloud.autoconfigure.RefreshEndpointAutoConfiguration,\
org.springframework.cloud.autoconfigure.WritableEnvironmentEndpointAutoConfiguration
# 應用監聽器
org.springframework.context.ApplicationListener=\
org.springframework.cloud.bootstrap.BootstrapApplicationListener,\
org.springframework.cloud.bootstrap.LoggingSystemShutdownListener,\
org.springframework.cloud.context.restart.RestartListener
# Spring Cloud 初始化元件
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration,\
org.springframework.cloud.bootstrap.encrypt.EncryptionBootstrapConfiguration,\
org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration,\
org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration
# Spring Boot 初始化註冊
org.springframework.boot.BootstrapRegistryInitializer=\
org.springframework.cloud.bootstrap.RefreshBootstrapRegistryInitializer,\
org.springframework.cloud.bootstrap.TextEncryptorConfigBootstrapper
# 環境後置處理
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.cloud.bootstrap.encrypt.DecryptEnvironmentPostProcessor,\
org.springframework.cloud.util.random.CachedRandomPropertySourceEnvironmentPostProcessor
- ConfigurationPropertiesRebinderAutoConfiguration
ConfigurationPropertiesRebinder
的自動配置裝配 - LifecycleMvcEndpointAutoConfiguration
一些 MVC 終端元件的自動配置裝配 - RefreshAutoConfiguration
自動裝配spring.cloud.refresh
配置 - RefreshEndpointAutoConfiguration
一些可重新整理上下文資料終端元件的自動配置裝配 - WritableEnvironmentEndpointAutoConfiguration
WritableEnvironmentEndpoint
的自動配置裝配 - BootstrapApplicationListener
Cloud 應用初始化 - LoggingSystemShutdownListener
日誌擴充套件處理 - RestartListener
應用重新啟動的資訊記錄 - PropertySourceBootstrapConfiguration
Cloud 應用初始化時的配置屬性處理 - EncryptionBootstrapConfiguration
對加密傳輸的初始化配置 - RefreshBootstrapRegistryInitializer
嚮應用上下文物件ApplicationContext
新增BootstrapContext
Cloud 初始化上下文物件 - TextEncryptorConfigBootstrapper
文字加密配置初始化 - DecryptEnvironmentPostProcessor
傳輸中加密資訊的解密處理 - CachedRandomPropertySourceEnvironmentPostProcessor
對配置中隨機值屬性源random.xxx
的支援
下面主要解析一下 BootstrapApplicationListener
與 PropertySourceBootstrapConfiguration
1.1. BootstrapApplicationListener
BootstrapApplicationListener
的主要功能是擴充套件配置檔案的載入位置、新增 spring.factories
的載入元件
public class BootstrapApplicationListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent>, Ordered {
@Override
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
// ... 程式碼省略
// 初始化上下文環境
context = bootstrapServiceContext(environment, event.getSpringApplication(), configName);
// ... 程式碼省略
}
// 初始化上下文環境
private ConfigurableApplicationContext bootstrapServiceContext(ConfigurableEnvironment environment,
final SpringApplication application, String configName) {
// ... 程式碼省略
String configLocation = environment.resolvePlaceholders("${spring.cloud.bootstrap.location:}");
String configAdditionalLocation = environment
.resolvePlaceholders("${spring.cloud.bootstrap.additional-location:}");
Map<String, Object> bootstrapMap = new HashMap<>();
// 擴充套件 spring.cloud.bootstrap.location 配置到 spring.config.location 中
if (StringUtils.hasText(configLocation)) {
bootstrapMap.put("spring.config.location", configLocation);
}
// 擴充套件 spring.cloud.bootstrap.additional-location 配置到 spring.config.additional-location 中
if (StringUtils.hasText(configAdditionalLocation)) {
bootstrapMap.put("spring.config.additional-location", configAdditionalLocation);
}
// ... 程式碼省略
// 通過 BootstrapImportSelector 新增 `spring.factories` 的載入元件 `org.springframework.cloud.bootstrap.BootstrapConfiguration`
builder.sources(BootstrapImportSelectorConfiguration.class);
}
}
public class BootstrapImportSelector implements EnvironmentAware, DeferredImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
// ... 程式碼省略
// 通過 SpringFactoriesLoader 載入 `org.springframework.cloud.bootstrap.BootstrapConfiguration` 指定的元件
List<String> names = new ArrayList<>(
SpringFactoriesLoader.loadFactoryNames(BootstrapConfiguration.class, classLoader));
// 配置中的 spring.cloud.bootstrap.sources 也當做 BootstrapConfiguration 元件載入
names.addAll(Arrays.asList(StringUtils
.commaDelimitedListToStringArray(this.environment.getProperty("spring.cloud.bootstrap.sources", ""))));
// ... 程式碼省略
}
}
1.2. PropertySourceBootstrapConfiguration
PropertySourceBootstrapConfiguration
的主要功能是針對 SpringCloud 的日誌、Profile、配置處理
public class PropertySourceBootstrapConfiguration
implements ApplicationContextInitializer<ConfigurableApplicationContext>, Ordered {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
// ... 程式碼省略
MutablePropertySources propertySources = environment.getPropertySources();
// ... 程式碼省略
// 載入自定義的配置載入處理,spring-cloud-config 的分散式配置功能就有賴於此
insertPropertySources(propertySources, composite);
// 處理 logging.config 指定的日誌配置
String logConfig = environment.resolvePlaceholders("${logging.config:}");
LogFile logFile = LogFile.get(environment);
reinitializeLoggingSystem(environment, logConfig, logFile);
// 設定日誌記錄等級
setLogLevels(applicationContext, environment);
// 處理 spring.profiles.active 啟用的環境
handleIncludedProfiles(environment);
}
}
1.3. @BootstrapConfiguration
這個註解是 spring-cloud-context
主要的註解,用於初始化 Spring Cloud 元件
// 通過前面介紹的 `BootstrapImportSelector` 來實現自動載入在 `spring.factories` 中使用
// `org.springframework.cloud.bootstrap.BootstrapConfiguration` 配置的類
public @interface BootstrapConfiguration {}
2. spring-cloud-commons
元件的載入仍然是通過 Spring Factories 擴充套件載入機制載入的,定在 spring.factories
# 屬性自動裝配
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.client.CommonsClientAutoConfiguration,\
org.springframework.cloud.client.ReactiveCommonsClientAutoConfiguration,\
org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClientAutoConfiguration,\
org.springframework.cloud.client.discovery.composite.reactive.ReactiveCompositeDiscoveryClientAutoConfiguration,\
org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration,\
org.springframework.cloud.client.discovery.simple.reactive.SimpleReactiveDiscoveryClientAutoConfiguration,\
org.springframework.cloud.client.hypermedia.CloudHypermediaAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.AsyncLoadBalancerAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.reactive.LoadBalancerBeanPostProcessorAutoConfiguration,\
org.springframework.cloud.client.loadbalancer.reactive.ReactorLoadBalancerClientAutoConfiguration,\
org.springframework.cloud.client.serviceregistry.ServiceRegistryAutoConfiguration,\
org.springframework.cloud.commons.httpclient.HttpClientConfiguration,\
org.springframework.cloud.commons.util.UtilAutoConfiguration,\
org.springframework.cloud.configuration.CompatibilityVerifierAutoConfiguration,\
org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration,\
org.springframework.cloud.commons.security.ResourceServerTokenRelayAutoConfiguration
# 環境後置處理
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.cloud.client.HostInfoEnvironmentPostProcessor
# 錯誤分析
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.cloud.configuration.CompatibilityNotMetFailureAnalyzer
- CommonsClientAutoConfiguration
DiscoveryClient
與LoadBalancerClient
的自動配置裝配 - ReactiveCommonsClientAutoConfiguration
ReactiveDiscoveryClient
與ReactiveLoadBalancer
的自動配置裝配 - CompositeDiscoveryClientAutoConfiguration
CompositeDiscoveryClient
的自動配置裝配 - ReactiveCompositeDiscoveryClientAutoConfiguration
ReactiveCompositeDiscoveryClient
的自動配置裝配 - SimpleDiscoveryClientAutoConfiguration
SimpleDiscoveryClient
的自動配置裝配 - SimpleReactiveDiscoveryClientAutoConfiguration
SimpleReactiveDiscoveryClient
的自動配置裝配 - CloudHypermediaAutoConfiguration
spring.cloud.hypermedia
的自動配置裝配 - AsyncLoadBalancerAutoConfiguration
非同步負載均衡的自動配置裝配 - LoadBalancerAutoConfiguration
阻塞負載均衡的自動配置裝配 - LoadBalancerBeanPostProcessorAutoConfiguration
負載均衡後置處理的自動配置裝配 - ReactorLoadBalancerClientAutoConfiguration
Reactive 負載均衡的自動配置裝配 - ServiceRegistryAutoConfiguration
註冊ServiceRegistryEndpoint
- HttpClientConfiguration
Http 客戶端配置 - UtilAutoConfiguration
spring.cloud.util
的自動配置裝配 - CompatibilityVerifierAutoConfiguration
spring.cloud.compatibility-verifier
的自動配置裝配 - AutoServiceRegistrationAutoConfiguration
spring.cloud.service-registry.auto-registration
的自動配置裝配 - ResourceServerTokenRelayAutoConfiguration
spring.cloud.mvc.token-relay
的自動配置裝配 - HostInfoEnvironmentPostProcessor
自動加上spring.cloud.client.hostname
與spring.cloud.client.ip-address
配置屬性 - CompatibilityNotMetFailureAnalyzer
Cloud 錯誤分析處理
2.1. @EnableDiscoveryClient & @LoadBalanced
這兩個註解是 spring-cloud-commons
主要的註解,@EnableDiscoveryClient
用於新增服務發現客戶端,@LoadBalanced
用於標誌請求是負載均衡的
// 自動例項化 `EnableDiscoveryClientImportSelector`,並載入Spring IOC容器
// 例項化 `@EnableDiscoveryClient` 註解的類,但不做實際註冊、發現處理
@Import(EnableDiscoveryClientImportSelector.class)
public @interface EnableDiscoveryClient {}
// 沒有任何處理,只是定義註解
public @interface LoadBalanced {}
@EnableDiscoveryClient
與 @LoadBalanced
都沒有實質上的處理,只是定義好註解規範,留待其他元件實現
3. spring-cloud-loadbalancer
元件的載入仍然是通過 Spring Factories 擴充套件載入機制載入的,定在 spring.factories
# 屬性自動裝配
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
spring.cloud.loadbalancer
的自動配置裝配 - BlockingLoadBalancerClientAutoConfiguration
阻塞負載均衡客戶端的自動配置裝配 - LoadBalancerCacheAutoConfiguration
spring.cloud.loadbalancer.cache
的自動配置裝配 - OAuth2LoadBalancerClientAutoConfiguration
spring.cloud.oauth2.load-balanced
的自動配置裝配 - LoadBalancerStatsAutoConfiguration
spring.cloud.loadbalancer.stats
的自動配置裝配
這裡主要解析一下 LoadBalancerAutoConfiguration
3.1. LoadBalancerAutoConfiguration
LoadBalancerAutoConfiguration
的主要功能是完成 spring.cloud.loadbalancer
的自動配置裝配,並例項化負載均衡元件
// 繼承 `LoadBalancerClients` 的註解
@LoadBalancerClients
// 自動裝配 `spring.cloud.loadbalancer` 配置
@EnableConfigurationProperties(LoadBalancerProperties.class)
// 使用 `spring.cloud.loadbalancer.enabled` 來啟動此元件
@ConditionalOnProperty(value = "spring.cloud.loadbalancer.enabled", havingValue = "true", matchIfMissing = true)
public class LoadBalancerAutoConfiguration {
// ... 程式碼省略
}
因為 LoadBalancerAutoConfiguration
繼承了 LoadBalancerClients
的註解,所以來看看 LoadBalancerClients
// 自動例項化 `LoadBalancerClientConfigurationRegistrar`,並載入Spring IOC容器
@Import(LoadBalancerClientConfigurationRegistrar.class)
public @interface LoadBalancerClients {
// ... 程式碼省略
}
再來看看 LoadBalancerClientConfigurationRegistrar
public class LoadBalancerClientConfigurationRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
// 獲取 @LoadBalancerClients 註解
Map<String, Object> attrs = metadata.getAnnotationAttributes(LoadBalancerClients.class.getName(), true);
if (attrs != null && attrs.containsKey("value")) {
// 獲取註解中 value 指定的值,並註冊bean元件定義
AnnotationAttributes[] clients = (AnnotationAttributes[]) attrs.get("value");
for (AnnotationAttributes client : clients) {
registerClientConfiguration(registry, getClientName(client), client.get("configuration"));
}
}
// ... 程式碼省略
// 獲取 @LoadBalancerClient 註解
Map<String, Object> client = metadata.getAnnotationAttributes(LoadBalancerClient.class.getName(), true);
// 獲取註解中 name/value 指定的值,並註冊bean元件定義
String name = getClientName(client);
if (name != null) {
registerClientConfiguration(registry, name, client.get("configuration"));
}
}
}
3.2. @LoadBalancerClients & @LoadBalancerClient
這兩個註解是 spring-cloud-loadbalancer
主要的註解,用於新增負載均衡客戶端
// 自動例項化 `LoadBalancerClientConfigurationRegistrar`,並載入Spring IOC容器
// 自動處理標記有 `@LoadBalancerClients` & `@LoadBalancerClient` 註解的類
@Import(LoadBalancerClientConfigurationRegistrar.class)
public @interface LoadBalancerClients {
// ... 程式碼省略
}
// 自動例項化 `LoadBalancerClientConfigurationRegistrar`,並載入Spring IOC容器
// 自動處理標記有 `@LoadBalancerClients` & `@LoadBalancerClient` 註解的類
@Import(LoadBalancerClientConfigurationRegistrar.class)
public @interface LoadBalancerClient {
// ... 程式碼省略
}
後續
更多部落格,檢視 https://github.com/senntyou/blogs
版權宣告:自由轉載-非商用-非衍生-保持署名(創意共享 3.0 許可證)