[Spring Cloud] 2.Spring Cloud Native Application

Spring Cloud Native Application 原生應用

原生應用:是一種程序開發風格,是連續交付(持續集成)和值驅動領域的最佳實踐。html

12-factors

與12-Factor (SaaS)應用,有着相似的目標: (12-Factor 爲構建以下的 SaaS 應用提供了方法論):java

  • 使用標準化流程自動配置,從而使新的開發者花費最少的學習成本加入這個項目。
  • 和操做系統之間儘量的劃清界限,在各個系統中提供最大的可移植性。
  • 適合部署在現代的雲計算平臺,從而在服務器和系統管理方面節省資源。
  • 將開發環境和生產環境的差別降至最低,並使用持續交付實施敏捷開發。
  • 能夠在工具、架構和開發流程不發生明顯變化的前提下實現擴展。

這套理論適用於任意語言和後端服務(數據庫、消息隊列、緩存等)開發的應用程序。正則表達式

12-factors 包含:spring

  • I. 基準代碼 一份基準代碼,多份部署
  • II. 依賴 顯式聲明依賴關係
  • III. 配置 按不一樣的運行環境,對配置信息進行獨立的存放 / 使用
  • IV. 後端服務 把後端服務看成附加資源
  • V. 構建,發佈,運行 嚴格分離構建和運行
  • VI. 進程 以一個或多個無狀態進程運行應用
  • VII. 端口綁定 經過端口綁定提供服務
  • VIII. 併發 經過進程模型進行擴展
  • IX. 易處理 快速啓動和優雅終止可最大化健壯性
  • X. 開發環境與線上環境等價 儘量的保持開發,預發佈,線上環境相同
  • XI. 日誌 把日誌看成事件流
  • XII. 管理進程 後臺管理任務看成一次性進程運行

Spring Cloud 提供一種途徑,使得可以方便快捷並按需的搭建一個可用的分佈式應用。docker

在使用Spring Cloud 時不少特性是基於Spring Boot的, 另外還有兩個庫:Spring Cloud ContextSpring Cloud Commons數據庫

Spring Cloud Context

提供一些工具,以及Spring Cloud應用(ApplicationContext)的基礎服務。如:引導上下文;加解密;做用域重建;環境()bootstrap

Spring Cloud Commons

是一個不一樣Spring Cloud實現的抽象層以及通用類集合。 如:Spring Cloud Netflix;Spring Cloud Consul後端


若是出現「Illegal key size」錯誤,那表示須要更新JCE策略文件,以得到更高的權限api


1 Spring Cloud Context: Application Context Services

Spring Boot 提供了一套固定的套路來使用spring構建應用,用一種約定俗成的方式來進行配置,並提供一套通用的管理、監控方式。 Spring Cloud 在此基礎之上,增長一些能夠按需配置的功能。緩存

1.1 The Bootstrap Application Context 引導上下文

一個Spring Cloud應用,首先會建立一個引導上下文來做爲主應用上下文的父級。 負責從外部加載配置源。兩個上下文共享一個Environment來作爲Spring應用的外部配置源。

默認的引導屬性擁有更高的優先級,所以,不能被本地配置所覆蓋。

引導上下文使用了一個和Spring Boot主應用不一樣的約定方式來加載配置。引導上下文使用bootstrap.yml(或者properties)來配置,經過這樣很好的與主應用配置分離開來。

bootstrap.yml

spring:
  application:
    name: foo
  cloud:
    config:
      uri: ${SPRING_CONFIG_URI:http://localhost:8888}

引導上下文也能夠經過在系統屬性中配置:spring.cloud.bootstrap.enabled=false來關閉。

1.2 Application Context Hierarchies 應用上下文層級

若是使用 SpringApplication 或者 SpringApplicationBuilder 來構建上下文時,那麼會添加一個 引導上下文(BootstrapContext)會做爲父級上下文。

子級上下文會從父級上下文繼承配置源以及配置文件,所以主應用會包含額外的配置來源。

額外的配置源包括:

  • "bootstrap":若是有任何非空PropertySourceLocators被發現,那會生成一個優先級更高的CompositePropertySource
  • "applicationConfig:[classpath:bootstrap.yml]":若是配置了bootstrap.ymlproperties,那麼他們的配置項將被用於引導上下文(BootstrapContext),這樣也會被子級上下文引用到。他們比application.yml的優先級低。

因爲加載順序使得bootstrap配置源會先被掃描,可是,注意:因爲處於一個很是低的優先級,因此並無立刻加載bootstrap.yml中的數據,也正是這個緣由,一般被用來看成默認配置實用

能夠設置父級上下文(ApplicationContext)來本身擴展上下文層級。 能夠本身實現接口,也能夠經過SpringApplicationBuilder提供的幾個方便的工具方法(parent(),parent(),parent())。 不論自定義了多少上下文層級,bootstrap引導上下文都處於最高級。 在這個層級中的每個上下文都能訪問到引導上下文的配置源,使用時須要注意避免無心的配置覆蓋狀況。 層級中的每個上下文原則上都應該有一個不一樣的spring.application.name,所以當有配置服務器時,就會有一個不一樣的遠程配置源。

普通的上下文,有一個區分配置的規則:子級上下文中的屬性會覆蓋父級上下文中的屬性,覆蓋條件包含屬性名和配置源名。也就是說能夠對整個配置源進行覆蓋。

注意:SpringApplicationBuilder容許在整個上下文層級中共享Environment,但此功能默認關閉。所以,當須要時,同級別的上下文不須要去包含同一個配置源,他們能夠和父級上下文共享這些配置。


1.3 Changing the Location of Bootstrap Properties 改變引導上下文配置路徑

能夠經過配置spring.cloud.bootstrap.name來改變默認的引導上下文配置文件名。(默認值bootstrap)。

也能夠經過配置spring.cloud.bootstrap.location來改變默認的引導上下文配置的掃描路徑。(默認值

經過系統屬性來改變以上兩個配置項

配置文件中spring.config.*等配置項是被用於引導上下文的配置,並被加載到Environment中。

若是配置了spring.profiles.active或者經過Environment的api來指定一個特定配置項,那麼這個特定配置文件也會被加載,就如同一個Spring Boot應用同樣。

1.4 Overriding the Values of Remote Properties 覆蓋遠程配置項

被引導上下文加載的配置源一般都是一個遠程的(例如:Config Server),默認狀況下遠程配置項不能被本地配置所覆蓋。

若是應用想要覆蓋遠程配置項,則須要遠程配置源經過配置spring.cloud.config.allowOverride=true來受權。一旦開啓此功能,則能夠在本地配置下面兩個配置項來控制細節:

  • spring.cloud.config.overrideNone=true 覆蓋本地全部配置源;
  • spring.cloud.config.overrideSystemProperties=false僅覆蓋系統屬性和環境變量,而不覆蓋本地配置文件。

1.5 Customizing the Bootstrap Configuration 定製引導配置

能夠在/META-INF/spring.factories中添加org.springframework.cloud.bootstrap.BootstrapConfiguration配置,來指定任何想要添加到引導上下文中的配置類(@Configuration),若是有多個能夠用逗號分隔。任何想要在主應用中自動裝配的spring bean 均可以經過這些配置類來定義。 配置類也能夠是一個包含@BeansApplicationContextInitializer對象。 當配置類有必定依賴順序時,能夠經過@Order來指定順序,默認:last


注意: 當使用自定義BootstrapConfiguration時,在主應用時要當心使用@ComponentScanned 防止沒必要要的加載。最好使用一個特定的包名來放置那些自定義配置類,來避免與@ComponentScan,@SpringBootApplication重疊。


當引導處理結束時會自動注入到主應用的SpringApplication實例中。 在啓動以前,引導上下文會找到spring.factories中的配置類以及全部被標記@BeansApplicationContextInitializer對象加入到主應用S上下文(SpringApplication

1.6 Customizing the Bootstrap Property Sources 定製引導上下文的配置源

默認狀況下外部配置源是一個Config Server,固然也能夠在spring.factories中配置PropertySourceLocator對象來手動添加外部配置源(其餘Config Server;數據庫等)

例如:

@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"));
    }

}

任何一個ApplicationContext都會創一個Environment對象,它包含了外部配置源。它也相似一個普通Spring Boot配置源,所以你能夠經過它來定製本地配置項。(例如:spring.application.name

若是jar中包含上面代碼中的class,而且在META-INF/spring.factories包含:

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

那麼,這個自定義配置源將會在classpath下全部的應用中被使用。


1.7 Environment Changes 改變環境

應用會監聽EnvironmentChangedEvent事件,能夠經過ApplicationListeners來響應這個事件。

當配置項發生變更時,EnvironmentChangedEvent事件被拋出。 此時,應用會作出:

  • 重建上下文中全部的@ConfigurationProperties對象
  • 對全部的日誌屬性logging.level.*進行設定
  • 注意: Config Client默認不會主動去檢測Environment的改變,不過能夠經過一個定時任務(@Scheduled)去輪詢。可是,一般來講並不建議用這樣的方式。最好,經過廣播EnvironmentChangedEvent事件這種方式來處理。(例如使用:Spring Cloud Bus

因爲EnvironmentChangedEvent事件是經過Spring標準API來完成的,這就致使當Environment發生改變時,會有大量的對象刷新。 例如:動態配置一個DataSource的鏈接池的maxPoolSize,當maxPoolSize發生改變時,致使整個ApplicationContext進入一個阻塞的重建@ConfigurationProperties階段。 爲了解決這個問題,須要使用@RefreshScope

1.8 Refresh Scope 刷新範圍

能夠在@Bean 上標記一個@Refresh Scope 來指定這個Bean須要在配置改變時刷新。

Refresh scope 對象都是延遲代理初始化的,調用方法獲取值時都是從初始化值得緩存中獲取的。從新初始化其實也就是初始化緩存。

RefreshScoperefreshAll()方法能夠刷新所有目標緩存。refresh(String)方法能夠指定名字的緩存。這個功能會經過/refresh暴露到外部(如:HTTP,JMX

注意: @RefreshScope工做於@Configuration類,這樣就會致使一個特殊的狀況:互相依賴的Bean也會被刷新重建,並從新注入,這樣@Configuration也就被從新初始化


1.9 Encryption and Decryption 加解密

Spring Cloud 爲Environment提供了一個本地解密屬性的預處理過程。 此過程,會使用幾個擴展配置:encrypt.* 這樣就能夠經過{cipher}*來使用加密數據了。

若是須要使用這個特性,那就須要引入Spring Security RSA 到classpath。

一樣這也須要對JCE進行擴展。

1.10 Endpoints 入口

對於一個基於Spring Boot Actuator應用,Spring Cloud原生應用擴展幾個管理入口:

  • /env(POST) : 用於 更新Environment;重建@ConfigurationProperties;日誌級別
  • /refresh: 從新加載引導上下文;刷新@RefreshScope對象。
  • /restart:重啓ApplicationContext,此功能默認不可用
  • /pause/resume : 調用 Lifecycle 方法 (至關於ApplicationContextstop()start()方法)

2 Spring Cloud Commons: Common Abstractions 共用抽象層

如服務發現,負載均衡,斷路器等模式都是以一個共用抽象層提供給全部的Spring Cloud客戶端獨立使用。

2.1 Spring RestTemplate as a Load Balancer Client 負載均衡

RestTemplate可使用@LoadBalanced在對應的@Bean進行連帶的配置,就能夠作成負載均衡。

注意: RestTemplate再也不自動建立了,須要時,須要本身建立特定的應用

@Configuration
public class MyConfiguration {

    @LoadBalanced
    @Bean
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

public class MyClass {
    @Autowired
    private RestTemplate restTemplate;

    public String doOtherStuff() {
        String results = restTemplate.getForObject("http://stores/stores", String.class);
        return results;
    }
}

2.2 Multiple RestTemplate objects 多重RestTemplat

若是RestTemplate不想要負載均衡,那就建立一個普通RestTemplate正常注入就好了。 若是須要負載均衡,在建立@Bean時加上@LoadBalanced限定就行。

若是須要混用的話,能夠參見下面的例子:

@Configuration
public class MyConfiguration {

    @LoadBalanced
    @Bean
    RestTemplate loadBalanced() {
        return new RestTemplate();
    }

    @Primary
    @Bean
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

public class MyClass {
    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    @LoadBalanced
    private RestTemplate loadBalanced;

    public String doOtherStuff() {
        return loadBalanced.getForObject("http://stores/stores", String.class);
    }

    public String doStuff() {
        return restTemplate.getForObject("http://example.com", String.class);
    }
}

使用@Primary限定,避免@Autowired混淆。 若是上面的代碼在進行RestOperations操做時,出現java.lang.IllegalArgumentException異常,能夠設置spring.aop.proxyTargetClass=true來解決。

2.3 Ignore Network Interfaces 忽略網絡接口

有的時候須要忽略某個名字的網絡接口,把他們排除在服務發現註冊以外。(如:運行於Docker容器) 能夠設置一組正則表達式來對接口名進行匹配,來進行忽略這些接口:

application.yml

spring:
  cloud:
    inetutils:
      ignoredInterfaces:
        - docker0
        - veth.*
相關文章
相關標籤/搜索