原文檔鏈接:https://cloud.spring.io/spring-cloud-static/Greenwich.SR2/multi/multi_spring-cloud.html
特性
Spring Cloud專注於爲典型用例提供良好的開箱即用的經驗,併爲其他用例提供可擴展機制。
- Distributed/versioned configuration 分佈式/版本化配置
- Service registration and discovery 服務註冊與發現
- Routing 路由
- Service-to-service calls 服務之間的調用
- Load balancing 負載均衡
- Circuit Breakers 斷路器
- Distributed messaging 分佈式消息
第一部分. 雲原生應用程序(Cloud Native Applications)
1. 雲原生應用程序(Cloud Native Application)
Cloud Native是一種應用程序開發風格,鼓勵在持續交付和價值驅動開發領域,更容易地採用最佳實踐。 一個相關的訓練是,建立12因素應用程序。它主張將開發實踐與交付和運營目標保持一致 - 例如,將編碼和管理與監控同時進行。 Spring Cloud以多種特定的方式促進這些風格的開發。 它的出發點是提供一組分佈式系統中的所有組件都能輕鬆訪問到的功能。
Spring Cloud建立在Spring Boot包含的諸多功能之上。 Spring Cloud將功能劃分爲兩個庫:Spring Cloud Context和Spring Cloud Commons。 Spring Cloud Context爲Spring Cloud應用程序的ApplicationContext(引導上下文,加密,刷新範圍和環境端點)提供工具和特殊服務。 Spring Cloud Commons是一組用於不同Spring Cloud實現的抽象和公共類(例如Spring Cloud Netflix和Spring Cloud Consul)。
如果您遇到“Illegal key size”的異常並且使用的是Sun的JDK,那麼您需要安裝Java Cryptography Extension(JCE)Unlimited Strength Jurisdiction Policy Files。 更多信息,請參閱以下鏈接:
無論您使用哪種版本的JRE / JDK x64 / x86,將文件解壓縮到JDK/jre/lib/security文件夾中。
注意:Spring Cloud是在非限制性Apache 2.0許可下發布的。 如果您想爲文檔的這一部分做出貢獻,或者如果發現錯誤,您可以在github上找到項目的源代碼和問題跟蹤器。
2. Spring Cloud Context:應用程序上下文服務
Spring Boot有一個關於如何使用Spring構建應用程序的觀點。 例如,它爲通用配置文件指定了假定的位置,並具有用於常見管理和監視任務的端點。 Spring Cloud構建於此之上,並添加了一些功能,這些是系統中的所有組件都可能使用或偶爾需要的功能。
2.1 引導程序上下文(Bootstrap Application Context)
Spring Cloud應用程序通過創建一個Bootstrap Context來運行,該上下文是主應用程序的父上下文。 它負責從外部源加載配置屬性以及解密本地外部配置文件中的屬性。 這兩個上下文共享一個Environment,它是任何Spring應用程序的外部屬性的來源。 默認情況下,引導屬性(不是bootstrap.properties,而是在引導階段加載的屬性)以高優先級添加,因此本地配置無法覆蓋它們。
Bootstrap Context使用特殊的約定來定位外部配置文件,而不採用主應用程序的上下文。 您可以使用bootstrap.yml代替application.yml(或.properties),使引導程序的外部配置和主應用程序的上下文保持完全分離。 以下清單舉了一個示例:
bootstrap.yml.
spring:
application:
name: foo
cloud:
config:
uri: ${SPRING_CONFIG_URI:http://localhost:8888}
如果您的應用程序需要來自服務器的任何特定於應用程序的配置,則最好設置spring.application.name(在bootstrap.yml或application.yml中)。 爲了將屬性spring.application.name用作應用程序的上下文ID,必須在bootstrap中設置它[.properties | .yml]。
您可以通過設置spring.cloud.bootstrap.enabled = false來完全禁用引導過程(例如,在system properties中)。
2.2 應用程序上下文層級(Application Context Hierarchies)
如果您從SpringApplication或SpringApplicationBuilder構建應用程序上下文,那麼Bootstrap上下文就會被添加爲該上下文的父級。 Spring的一個特性是子上下文從其父級繼承屬性源和配置文件,因此與構建沒有Spring Cloud Config的上下文相比,“主”應用程序上下文包含其他屬性源。其他屬性來源是:
- “bootstrap”: 如果在Bootstrap上下文中找到任何PropertySourceLocators,並且它們具有非空屬性,則會出現具有高優先級的可選CompositePropertySource。一個例子是來源於Spring Cloud Config Server的屬性。有關如何自定義此屬性源內容的說明,請參見“第2.6節”,“自定義Bootstrap屬性源”。
- “applicationConfig: [classpath:bootstrap.yml]”(以及相關文件,如果Spring profiles處於活動狀態):如果您有bootstrap.yml(或.properties),則這些屬性用於配置Bootstrap上下文。然後,如果設置了父級時,它們將被添加到子上下文中。它們的優先級低於application.yml(或.properties)以及作爲創建Spring Boot應用程序過程的正常部分添加到子級的任何其他屬性源。有關如何自定義這些屬性源的內容的說明,請參見“2.3節”,“更改Bootstrap屬性的位置”。
由於屬性源的排序規則,“bootstrap”條目優先。但請注意,這些數據不包含來自bootstrap.yml的任何數據,它具有非常低的優先級,但可用於設置默認值。
您可以通過設置您創建的任何ApplicationContext的父上下文來擴展上下文層次結構 - 例如,通過使用自己的接口或SpringApplicationBuilder便捷方法(parent(),child()和sibling())。引導上下文是您自己創建的最高級祖先的父級。層次結構中的每個上下文都有自己的“引導程序”(可能是空的)屬性源,這可以避免從父級到其後代無意中提升某些值。如果存在Config Server,則層次結構中的每個上下文(原則上)也可以具有不同的spring.application.name,因此具有不同的遠程屬性源。普通的Spring應用程序上下文行爲規則適用於屬性解析:來自子上下文的屬性按名稱和屬性源名稱覆蓋父級中的屬性。 (如果子項具有與父項具有相同名稱的屬性源,則父項中的值不包含在子項中)。
請注意,SpringApplicationBuilder允許您在整個層次結構中共享Environment(
但這不是默認設置)。因此,同級上下文,不需要再添加相同的配置文件或屬性來源,即使他們可能與父上下文有同樣的值。
2.3更改Bootstrap屬性的位置
可以通過在System properties中設置spring.cloud.bootstrap.name
(默認值:bootstrap
)或spring.cloud.bootstrap.location
(默認值:空)來指定bootstrap.yml
(或.properties
)位置。
這些屬性的行爲類似於具有相同名稱的spring.config.*
變量。實際上,可以在Environment中設置這些屬性來設置引導程序
ApplicationContext
。如果有一個活動的配置文件(來源於spring.profiles.active
或通過你創建的上下文中的Environment
API),則在加載配置文件屬性的同時,SpringBoot應用程序也加載了這些屬性。例如,從bootstrap-development.properties
加載一個development profile
。
2.4 覆蓋遠程屬性的值
引導上下文添加到應用程序的屬性源通常是“ 遠程 ”(例如,來自Spring Cloud Config Server)。默認情況下,它們無法在本地覆被蓋。如果要讓應用程序使用自己的系統屬性或配置文件覆蓋遠程屬性,則遠程屬性源必須通過設置授予它權限spring.cloud.config.allowOverride=true
(在本地設置它將不起作用)。設置該標誌後,兩個更細粒度的設置將控制遠程屬性相對於系統屬性和應用程序本地配置的位置:
spring.cloud.config.overrideNone=true
:允許任何本地屬性源覆蓋。spring.cloud.config.overrideSystemProperties=false
:只有系統屬性,命令行參數和環境變量(但不是本地配置文件)可以覆蓋遠程設置。
2.5 自定義Bootstrap配置
通過在/META-INF/spring.factories
中名爲org.springframework.cloud.bootstrap.BootstrapConfiguration
的key下添加條目,可以讓引導上下文執行任何操作。
它包含以逗號分隔的Spring @Configuration
類的列表,這些類用於創建上下文。您可以在此處創建任意可以在主應用程序上下文自動裝配的Bean。對於ApplicationContextInitializer類型的
@Beans
有一種特殊的約定。如果要控制啓動順序,可以使用@Order註解
標記類(默認順序爲last
)。
添加自定義BootstrapConfiguration時
,請注意不要讓這些類通過@ComponentScanned
錯誤地進入您的“ 主 ”應用程序上下文。請給引導配置類使用單獨的程序包名稱,並確保您的@ComponentScan不包含這個包,或者不要用給這些類添加
@SpringBootApplication
註解。
引導過程在將初始化程序注入主SpringApplication
實例時結束(這是正常的Spring Boot啓動順序,無論是作爲獨立應用程序運行還是部署在應用程序服務器中)。首先,從spring.factories
中找到的類來創建引導上下文。然後,在啓動之前將所有ApplicationContextInitializer類型的@Beans
添加到main SpringApplication
。
2.6 自定義Bootstrap屬性源
引導過程添加的外部配置的默認屬性源是Spring Cloud Config Server,但您可以通過給引導上下文增加PropertySourceLocator類型的bean
來添加其他配置源(通過spring.factories)。例如,您可以從其他服務器或數據庫插入其他屬性。
例如,請考慮以下自定義Locator:
@Configuration
public class CustomPropertySourceLocator implements PropertySourceLocator {
@Override
public PropertySource<?> locate(Environment environment) {
return new MapPropertySource("customProperty",
Collections.<String, Object>singletonMap("property.from.sample.custom.source", "worked as intended"));
}
}
該Environment
傳遞進來的屬性將用於ApplicationContext的
創建。換句話說,爲我們提供了其他的屬性來源。它已經具有正常的Spring Boot提供的屬性源,因此您可以使用它們來定位特定於此的屬性源Environment
(例如,通過鍵入它spring.application.name
,就像在默認的Spring Cloud Config Server屬性源定位器中所做的那樣)。
如果您在其中創建一個包含此類的jar,然後添加一個META-INF/spring.factories
包含
org.springframework.cloud.bootstrap.BootstrapConfiguration=sample.custom.CustomPropertySourceLocator
,那麼customProperty
PropertySource將
會出現在任何其類路徑中包含該jar的應用程序中。
2.7 記錄配置
如果要使用Spring Boot配置日誌設置,並且想讓它應用於所有event,則應將此配置放在bootstrap.[yml | properties]中。
要使Spring Cloud正確初始化日誌記錄配置,您不能使用自定義前綴。例如, |
2.8環境變化
應用程序監聽EnvironmentChangeEvent事件,並且
以幾種標準方式響應變化(可以給自定義ApplicationListeners以正常的方式添加
@Beans註解
)。當一個EnvironmentChangeEvent事件被
觀察到時,它有一個已變化的鍵值列表,應用程序使用它們:
- 在上下文中重新綁定任何
@ConfigurationProperties註解的
bean - 在
logging.level.*中
設置任何屬性的logger級別
請注意,默認情況下,Config Client不會輪詢Environment中的變化
。通常,我們不建議使用這種方法來檢測被變化(儘管您可以使用 @Scheduled
註釋進行設置)。如果您有一個可擴展的客戶端應用程序,最好廣播EnvironmentChangeEvent
到所有實例,而不是讓它們輪詢變化(例如,使用Spring Cloud Bus)。
EnvironmentChangeEvent事件
涵蓋一大類刷新用例,只要你確實對Environment做了改變並
發佈的事件。(請注意,這些API是公共的,並且是核心Spring的一部分)。您可以通過訪問/configprops
端點(一個正常的Spring Boot Actuator功能)來驗證更改是否綁定到@ConfigurationProperties註解的
bean 。例如,一個DataSource可能
有個maxPoolSize屬性
在運行時更改(Spring Boot創建的默認DataSource
是@ConfigurationProperties註解的
bean)並動態增加容量。重新綁定@ConfigurationProperties
不包括另一大類用例,在這些用例中,您需要更多地控制刷新並且需要將更改變爲對於整體ApplicationContext是
原子的。爲了解決這些問題,我們有@RefreshScope
。
2.9 刷新範圍
當配置發生變化時,@RefreshScope註解的
@Bean
將獲得特殊處理。此功能解決了有狀態bean的問題,只有在初始化時纔會注入其配置。例如,如果一個DataSource用幾個open的連接,這時
數據庫URL通過Environment變化了
,您可能希望這些連接的持有者能夠完成他們正在執行的操作。然後,下次從池中借用連接時,它會獲得一個帶有新URL的連接。
有時,甚至可能必須應用@RefreshScope
註解在一些只能初始化一次的bean上。如果bean是“不可變的”,則必須使用@RefreshScope
在bean上註釋或在屬性spring.cloud.refresh.extra-refreshable下
指定該類名 。
重要 | |
---|---|
如果您 |
刷新範圍bean採用lazy模式(即,使用它們時才初始化),並且範圍充當初始化值的緩存。要強制bean在下一個方法調用時重新初始化,必須使其緩存條目無效。
RefreshScope
是上下文中的一個bean,它有一個公共refreshAll()
方法,通過清除目標緩存來刷新scope中的所有bean。/refresh
端點暴露該功能(通過HTTP或JMX)。要按名稱刷新單個bean,還有一個refresh(String)
方法。
要公開/refresh
端點,您需要將以下配置添加到您的應用程序:
management:
endpoints:
web:
exposure:
include: refresh
|
2.10 加密和解密
Spring Cloud有一個Environment
預處理器,用於在本地解密屬性值。它遵循與Config Server相同的規則,並具有相同的外部配置encrypt.*
。因此,您可以用{cipher}*
的形式使用加密值,只要有有效密鑰,它們就會在主應用程序上下文獲取Environment
設置之前被解密。要在應用程序中使用加密功能,您需要在類路徑中包含Spring Security RSA(Maven座標:“org.springframework.security:spring-security-rsa”),並且還需要全面的JCE擴展在你的JVM中。
如果遇到“Illegal key size”異常並且您使用Sun的JDK,則需要安裝Java Cryptography Extension(JCE)Unlimited Strength Jurisdiction Policy Files。有關更多信息,請參閱以下鏈接:
無論您使用哪種版本的JRE / JDK x64 / x86,都要將文件解壓縮到JDK / jre / lib / security文件夾中。
2.11端點
對於Spring Boot Actuator應用程序,可以使用一些其他管理端點。您可以使用:
POST到
/actuator/env去
更新Environment
並重新綁定@ConfigurationProperties和log levels
。/actuator/refresh
重新加載引導上下文並刷新@RefreshScope
bean。/actuator/restart
關閉ApplicationContext
並重新啓動它(默認情況下禁用)。/actuator/pause
和/actuator/resume
調用Lifecycle
方法(在ApplicationContext上的
stop()
和start()
)。
如果禁用 |