SpringCloud入門之應用程序上下文服務(Spring Cloud Context)詳解

構建分佈式系統很是複雜且容易出錯。Spring Cloud爲最多見的分佈式系統模式提供了簡單易用的編程模型,幫助開發人員構建彈性,可靠和協調的應用程序。Spring Cloud構建於Spring Boot之上,使開發人員能夠輕鬆入門並快速提升工做效率。Spring Boot對於如何使用Spring構建應用程序有一個見解:例如它具備常規配置文件的常規位置,以及用於常見管理和監視任務的端點。Spring Cloud創建在此之上,並添加了一些可能系統中全部組件將使用或偶爾須要的功能。html

引導應用程序上下文

一個Spring Cloud應用程序經過建立一個「引導」上下文來進行操做,這個上下文是主應用程序的父上下文。開箱即用,負責從外部源加載配置屬性,還解密本地外部配置文件中的屬性。這兩個上下文共享一個Environment,這是任何Spring應用程序的外部屬性的來源。Bootstrap屬性的優先級高,所以默認狀況下不能被本地配置覆蓋。java

引導上下文使用與主應用程序上下文不一樣的外部配置約定,所以使用bootstrap.yml application.yml(或.properties)代替引導和主上下文的外部配置。關於配置文件bootstrap.yml與application.yml區別的深刻分析詳見SpringCloud入門之經常使用的配置文件 application.yml和 bootstrap.yml區別spring

例:數據庫

bootstrap.yml
spring:
  application:
    name: order
  cloud:
    config:
      uri: ${SPRING_CONFIG_URI:http://localhost:8888}

若是您的應用程序須要服務器上的特定於應用程序的配置,那麼設置spring.application.name(在bootstrap.ymlapplication.yml)中是個好主意。編程

您能夠經過設置spring.cloud.bootstrap.enabled=false(例如在系統屬性中)來徹底禁用引導過程。bootstrap

應用程序上下文層次結構

若是您從SpringApplicationSpringApplicationBuilder構建應用程序上下文,則將Bootstrap上下文添加爲該上下文的父級。這是一個Spring的功能,即子上下文從其父進程繼承屬性源和配置文件,所以與不使用Spring Cloud Config構建相同上下文相比,「主」應用程序上下文將包含其餘屬性源。額外的資產來源是:緩存

  • 若是您從SpringApplication或SpringApplicationBuilder構建應用程序上下文,則將Bootstrap上下文添加爲該上下文的父級。Spring的一個特性是子上下文從其父級繼承屬性源和配置文件,所以與構建沒有Spring Cloud Config的相同上下文相比,「主」應用程序上下文包含其餘屬性源。其餘財產來源是:安全

    • 「bootstrap」:若是PropertySourceLocators在Bootstrap上下文中找到任何內容,而且它們具備非空屬性,CompositePropertySource則會顯示具備高優先級的可選項一個例子是Spring Cloud Config Server的屬性。
    • 「applicationConfig:[classpath:bootstrap.yml]」(以及相關文件,若是Spring配置文件處於活動狀態):若是您有bootstrap.yml(或.properties),則使用這些屬性配置Bootstrap上下文。而後,在設置其父級時,它們將添加到子上下文中。它們的優先級低於application.yml(或.properties)以及做爲建立Spring Boot應用程序過程的正常部分添加到子級的任何其餘屬性源。有關如何自定義這些屬性源的內容的說明

因爲屬性源的排序規則,「引導」條目優先,但請注意,這些條目不包含來自bootstrap.yml的任何數據,它具備很是低的優先級,但可用於設置默認值。服務器

您能夠經過簡單地設置您建立的任何ApplicationContext的父上下文來擴展上下文層次結構,例如使用本身的界面,或使用SpringApplicationBuilder方便方法(parent()child()sibling())。引導環境將是您建立本身的最高級祖先的父級。層次結構中的每一個上下文都將有本身的「引導」屬性源(可能爲空),以免無心中將值從父級升級到其後代。層次結構中的每一個上下文(原則上)也能夠具備不一樣的spring.application.name,所以若是存在配置服務器,則不一樣的遠程屬性源。普通的Spring應用程序上下文行爲規則適用於屬性解析:子環境中的屬性經過名稱和屬性源名稱覆蓋父項中的屬性(若是子級具備與父級名稱相同的屬性源,一個來自父母的孩子不包括在孩子中)。併發

請注意,SpringApplicationBuilder容許您在整個層次結構中共享Environment,但這不是默認值。所以,兄弟情境尤爲不須要具備相同的資料或財產來源,儘管它們與父母共享共同點。

改變引導位置Properties

可使用spring.cloud.bootstrap.name(默認「引導」)或spring.cloud.bootstrap.location(默認爲空)指定bootstrap.yml(或.properties)位置,例如在系統屬性中。這些屬性的行爲相似於具備相同名稱的spring.config.*變體,實際上它們用於經過在其Environment中設置這些屬性來設置引導ApplicationContext若是在正在構建的上下文中有活動的配置文件(來自spring.profiles.active或經過Environment API)),則該配置文件中的屬性也將被加載,就像常規的Spring Boot應用程序,例如來自bootstrap-development.properties的「開發」簡介。

覆蓋遠程Properties的值

經過引導上下文添加到應用程序的屬性源一般是「遠程」(例如從配置服務器),而且默認狀況下,不能在本地覆蓋,除了在命令行上。若是要容許您的應用程序使用本身的系統屬性或配置文件覆蓋遠程屬性,則遠程屬性源必須經過設置spring.cloud.config.allowOverride=true(在本地設置自己不起做用)授予權限。一旦設置了該標誌,就會有一些更精細的設置來控制遠程屬性與系統屬性和應用程序本地配置的位置:spring.cloud.config.overrideNone=true覆蓋任何本地屬性源,spring.cloud.config.overrideSystemProperties=false若是隻有系統屬性和env var應該覆蓋遠程設置,而不是本地配置文件。

自定義引導配置

能夠經過在org.springframework.cloud.bootstrap.BootstrapConfiguration鍵下添加條目/META-INF/spring.factories來訓練引導上下文來執行任何您喜歡的操做。這是用於建立上下文的Spring @Configuration類的逗號分隔列表。您能夠在此處建立要用於自動裝配的主應用程序上下文的任何bean,而且還有ApplicationContextInitializer類型的@Beans的特殊合同。若是要控制啓動順序(默認順序爲「最後」),可使用@Order標記類。

警告
添加自定義BootstrapConfiguration時,請注意,您添加的類不是錯誤的@ComponentScanned到您的「主」應用程序上下文中,可能不須要它們。對於您的@ComponentScan@SpringBootApplication註釋配置類還沒有涵蓋的啓動配置類,請使用單獨的包名稱。

引導過程經過將初始化器注入主SpringApplication實例(即正常的Spring Boot啓動順序,不管是做爲獨立應用程序運行仍是部署在應用程序服務器中)結束。首先,從spring.factories中找到的類建立引導上下文,而後在ApplicationContextInitializer類型的全部@Beans添加到主SpringApplication開始以前。

自定義引導屬性源

引導過程添加的外部配置的默認屬性源是Config Server,但您能夠經過將PropertySourceLocator類型的bean添加到引導上下文(經過spring.factories)添加其餘源。您可使用此方法從其餘服務器或數據庫中插入其餘屬性。

做爲一個例子,請考慮如下微不足道的自定義定位器:

@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是要建立的ApplicationContextEnvironment,即爲咱們提供額外的屬性來源的。它將已經具備正常的Spring Boot提供的資源來源,所以您可使用它們來定位特定於此Environment的屬性源(例如經過將其綁定在spring.application.name上,如在默認狀況下所作的那樣Config Server屬性源定位器)。

若是你在這個類中建立一個jar,而後添加一個META-INF/spring.factories包含:

org.springframework.cloud.bootstrap.BootstrapConfiguration=sample.custom.CustomPropertySourceLocator

那麼「customProperty」PropertySource將顯示在其類路徑中包含該jar的任何應用程序中。

環境變化

應用程序將收聽EnvironmentChangeEvent,並以幾種標準方式進行更改(用戶能夠以常規方式添加ApplicationListeners附加ApplicationListeners)。當觀察到EnvironmentChangeEvent時,它將有一個已更改的鍵值列表,應用程序將使用如下內容:

  • 從新綁定上下文中的任何@ConfigurationProperties bean

  • logging.level.*中的任何屬性設置記錄器級別

請注意,配置客戶端不會經過默認輪詢查找Environment中的更改,一般咱們不建議檢測更改的方法(儘管可使用@Scheduled註釋進行設置)。若是您有一個擴展的客戶端應用程序,那麼最好將EnvironmentChangeEvent廣播到全部實例,而不是讓它們輪詢更改

EnvironmentChangeEvent涵蓋了大量的刷新用例,只要您真的能夠更改Environment併發布事件(這些API是公開的,部份內核爲Spring)。您能夠經過訪問/configprops端點(普通Spring Boot執行器功能)來驗證更改是否綁定到@ConfigurationProperties bean。例如,DataSource能夠在運行時更改其maxPoolSize(由Spring Boot建立的默認DataSource是一個@ConfigurationProperties bean),而且動態增長容量。從新綁定@ConfigurationProperties不會覆蓋另外一大類用例,您須要更多的控制刷新,而且您須要更改在整個ApplicationContext上是原子的。爲了解決這些擔心,咱們有@RefreshScope

刷新範圍

當配置更改時,標有@RefreshScope的Spring @Bean將獲得特殊處理。這解決了狀態bean在初始化時只注入配置的問題。例如,若是經過Environment更改數據庫URL時DataSource有開放鏈接,那麼咱們可能但願這些鏈接的持有人可以完成他們正在作的工做。而後下一次有人從游泳池借用一個鏈接,他獲得一個新的URL。

刷新範圍bean是在使用時初始化的懶惰代理(即當調用一個方法時),而且做用域做爲初始值的緩存。要強制bean從新初始化下一個方法調用,您只須要使其緩存條目無效。

RefreshScope是上下文中的一個bean,它有一個公共方法refreshAll()來清除目標緩存中的範圍內的全部bean。還有一個refresh(String)方法能夠按名稱刷新單個bean。此功能在/refresh端點(經過HTTP或JMX)中公開。

注意
@RefreshScope(技術上)在@Configuration類上工做,但可能會致使使人驚訝的行爲:例如,這並不 意味着該類中定義的全部@Beans自己都是@RefreshScope具體來講,任何取決於這些bean的東西都不能依賴它們在刷新啓動時被更新,除非它自己在@RefreshScope(在其中將從新刷新並從新注入其依賴關係),那麼它們將從刷新的@Configuration)從新初始化。

加密和解密

Spring Cloud具備一個用於在本地解密屬性值的Environment預處理器。它遵循與Config Server相同的規則,並經過encrypt.*具備相同的外部配置。所以,您可使用{cipher}*格式的加密值,只要有一個有效的密鑰,那麼在主應用程序上下文獲取Environment以前,它們將被解密。要在應用程序中使用加密功能,您須要在您的類路徑中包含Spring安全性RSA(Maven協調「org.springframework.security:spring-security-rsa」),而且還須要全面強大的JCE擴展你的JVM

若是因爲「非法密鑰大小」而致使異常,而且您正在使用Sun的JDK,則須要安裝Java加密擴展(JCE)無限強度管理策略文件。有關詳細信息,請參閱如下連接:

將文件解壓縮到JDK / jre / lib / security文件夾(不管您使用的是哪一個版本的JRE / JDK x64 / x86)。

端點

端點

對於Spring Boot Actuator應用程序,可使用一些其餘管理端點。您可使用:

  • POST/actuator/env更新Environment並從新綁定@ConfigurationProperties並記錄水平。
  • /actuator/refresh從新加載引導帶上下文並刷新@RefreshScopebean。
  • /actuator/restart關閉ApplicationContext並從新啓動它(默認狀況下禁用)。
  • /actuator/pause/actuator/resume調用的Lifecycle方法(stop()start()ApplicationContext)。
[Note]

若是禁用/actuator/restart端點,那麼端點/actuator/pause/actuator/resume端點也將被禁用,由於它們只是一個特例/actuator/restart

相關文章
相關標籤/搜索