Spring Cloud Config(配置中心)

Spring Cloud Config

目錄

1.3.0.RELEASE

Spring Cloud Config為分布式系統(tǒng)中的外部配置提供服務(wù)器和客戶(hù)端支持。使用Config Server政供,您可以在所有環(huán)境中管理應(yīng)用程序的外部屬性悠咱“杀ⅲ客戶(hù)端和服務(wù)器上的概念映射與Spring EnvironmentPropertySource抽象相同滚婉,因此它們與Spring應(yīng)用程序非常契合,但可以與任何以任何語(yǔ)言運(yùn)行的應(yīng)用程序一起使用责嚷。隨著應(yīng)用程序通過(guò)從開(kāi)發(fā)人員到測(cè)試和生產(chǎn)的部署流程莱睁,您可以管理這些環(huán)境之間的配置,并確定應(yīng)用程序具有遷移時(shí)需要運(yùn)行的一切颁虐。服務(wù)器存儲(chǔ)后端的默認(rèn)實(shí)現(xiàn)使用git蛮原,因此它輕松支持標(biāo)簽版本的配置環(huán)境,以及可以訪(fǎng)問(wèn)用于管理內(nèi)容的各種工具另绩∪逶桑可以輕松添加替代實(shí)現(xiàn)花嘶,并使用Spring配置將其插入。

快速開(kāi)始

90%高可用的千億級(jí)微服務(wù)架構(gòu)之道深入學(xué)習(xí)一線(xiàn)大廠必備微服務(wù)架構(gòu)技術(shù)蹦漠。VIP 教程限時(shí)免費(fèi)領(lǐng)取椭员。 ? 立即查看

啟動(dòng)服務(wù)器:

$ cd spring-cloud-config-server
$ ../mvnw spring-boot:run

該服務(wù)器是一個(gè)Spring Boot應(yīng)用程序,所以你可以從IDE運(yùn)行它笛园,而不是喜歡(主類(lèi)是ConfigServerApplication)隘击。然后嘗試一個(gè)客戶(hù)端:

$ curl localhost:8888/foo/development
{"name":"development","label":"master","propertySources":[
  {"name":"https://github.com/scratches/config-repo/foo-development.properties","source":{"bar":"spam"}},
  {"name":"https://github.com/scratches/config-repo/foo.properties","source":{"foo":"bar"}}
]}

定位資源的默認(rèn)策略是克隆一個(gè)git倉(cāng)庫(kù)(在spring.cloud.config.server.git.uri),并使用它來(lái)初始化一個(gè)迷你SpringApplication喘沿。迷你應(yīng)用程序的Environment用于枚舉屬性源并通過(guò)JSON端點(diǎn)發(fā)布闸度。

HTTP服務(wù)具有以下格式的資源:

/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties

其中“應(yīng)用程序”作為SpringApplication中的spring.config.name注入(即常規(guī)Spring Boot應(yīng)用程序中通常為“應(yīng)用程序”),“配置文件”是活動(dòng)配置文件(或逗號(hào)分隔列表)的屬性)蚜印,“l(fā)abel”是可選的git標(biāo)簽(默認(rèn)為“master”)莺禁。

Spring Cloud Config服務(wù)器從git存儲(chǔ)庫(kù)中提取遠(yuǎn)程客戶(hù)端的配置(必須提供):

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo

客戶(hù)端使用

要在應(yīng)用程序中使用這些功能,只需將其構(gòu)建為依賴(lài)于spring-cloud-config-client的Spring Boot應(yīng)用程序(例如窄赋,查看配置客戶(hù)端或示例應(yīng)用程序的測(cè)試用例)哟冬。添加依賴(lài)關(guān)系的最方便的方法是通過(guò)Spring Boot啟動(dòng)器org.springframework.cloud:spring-cloud-starter-config。還有一個(gè)Maven用戶(hù)的父pom和BOM(spring-cloud-starter-parent)和用于Gradle和Spring CLI用戶(hù)的Spring IO版本管理屬性文件忆绰。示例Maven配置:

的pom.xml

   <parent>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-parent</artifactId>
       <version>1.3.5.RELEASE</version>
       <relativePath /> <!-- lookup parent from repository -->
   </parent>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Brixton.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-config</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

<build>
    <plugins>
           <plugin>
               <groupId>org.springframework.boot</groupId>
               <artifactId>spring-boot-maven-plugin</artifactId>
           </plugin>
    </plugins>
</build>

   <!-- repositories also needed for snapshots and milestones -->

那么你可以創(chuàng)建一個(gè)標(biāo)準(zhǔn)的Spring Boot應(yīng)用程序浩峡,就像這個(gè)簡(jiǎn)單的HTTP服務(wù)器:

@SpringBootApplication
@RestController
public class Application {

    @RequestMapping("/")
    public String home() {
        return "Hello World!";
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

當(dāng)它運(yùn)行它將從端口8888上的默認(rèn)本地配置服務(wù)器接收外部配置,如果它正在運(yùn)行错敢。要修改啟動(dòng)行為翰灾,您可以使用bootstrap.properties(如application.properties,但是應(yīng)用程序上下文的引導(dǎo)階段)更改配置服務(wù)器的位置稚茅,例如

spring.cloud.config.uri: http://myconfigserver.com

引導(dǎo)屬性將在/env端點(diǎn)中顯示為高優(yōu)先級(jí)屬性源纸淮,例如

$ curl localhost:8080/env
{
  "profiles":[],
  "configService:https://github.com/spring-cloud-samples/config-repo/bar.properties":{"foo":"bar"},
  "servletContextInitParams":{},
  "systemProperties":{...},
  ...
}

(名為“configService:<遠(yuǎn)程存儲(chǔ)庫(kù)的URL> / <文件名>”的屬性源包含值為“bar”的屬性“foo”,是最高優(yōu)先級(jí))亚享。

|

注意

| 屬性源名稱(chēng)中的URL是git存儲(chǔ)庫(kù)咽块,而不是配置服務(wù)器URL。 |

Spring Cloud Config服務(wù)器

90%高可用的千億級(jí)微服務(wù)架構(gòu)之道深入學(xué)習(xí)一線(xiàn)大廠必備微服務(wù)架構(gòu)技術(shù)欺税。VIP 教程限時(shí)免費(fèi)領(lǐng)取侈沪。 ? 立即查看

服務(wù)器為外部配置(名稱(chēng)值對(duì)或等效的YAML內(nèi)容)提供了基于資源的HTTP。服務(wù)器可以使用@EnableConfigServer注釋輕松嵌入到Spring Boot應(yīng)用程序中晚凿。所以這個(gè)應(yīng)用程序是一個(gè)配置服務(wù)器:

ConfigServer.java

@SpringBootApplication
@EnableConfigServer
public class ConfigServer {
  public static void main(String[] args) {
    SpringApplication.run(ConfigServer.class, args);
  }
}

像所有默認(rèn)情況下在端口8080上運(yùn)行的所有Spring Boot應(yīng)用程序一樣亭罪,但您可以通過(guò)各種方式將其切換到常規(guī)端口8888。最簡(jiǎn)單的設(shè)置默認(rèn)配置存儲(chǔ)庫(kù)是通過(guò)使用spring.config.name=configserver啟動(dòng)(在Config Server jar中有一個(gè)configserver.yml)晃虫。另一個(gè)是使用你自己的application.properties皆撩,例如

application.properties

server.port: 8888
spring.cloud.config.server.git.uri: file://${user.home}/config-repo

其中${user.home}/config-repo是包含YAML和屬性文件的git倉(cāng)庫(kù)。

|

注意

| 在Windows中,如果文件URL為絕對(duì)帶有驅(qū)動(dòng)器前綴扛吞,例如[file:///${user.home}/config-repo](file:///${user.home}/config-repo)前塔,則需要額外的“/”孤钦。 |

|

提示

|

以下是上面示例中創(chuàng)建git倉(cāng)庫(kù)的方法:

$ cd $HOME
$ mkdir config-repo
$ cd config-repo
$ git init .
$ echo info.foo: bar > application.properties
$ git add -A .
$ git commit -m "Add application.properties"

|

|

警告

| 使用本地文件系統(tǒng)進(jìn)行g(shù)it存儲(chǔ)庫(kù)僅用于測(cè)試。使用服務(wù)器在生產(chǎn)環(huán)境中托管配置庫(kù)。 |

|

警告

| 如果您只保留文本文件潘靖,則配置庫(kù)的初始克隆將會(huì)快速有效夺脾。如果您開(kāi)始存儲(chǔ)二進(jìn)制文件疗隶,尤其是較大的文件摔握,則可能會(huì)遇到服務(wù)器中第一個(gè)配置請(qǐng)求和/或內(nèi)存不足錯(cuò)誤的延遲。 |

環(huán)境庫(kù)

您要在哪里存儲(chǔ)配置服務(wù)器的配置數(shù)據(jù)寺滚?管理此行為的策略是EnvironmentRepository柑营,服務(wù)于Environment對(duì)象。這個(gè)Environment是Spring Environment(包括propertySources作為主要功能)的域的淺層副本村视。Environment資源由三個(gè)變量參數(shù)化:

  • {application}映射到客戶(hù)端的“spring.application.name”;

  • {profile}映射到客戶(hù)端上的“spring.profiles.active”(逗號(hào)分隔列表); 和

  • {label}這是一個(gè)服務(wù)器端功能官套,標(biāo)記“版本”的一組配置文件。

存儲(chǔ)庫(kù)實(shí)現(xiàn)通常表現(xiàn)得像一個(gè)Spring Boot應(yīng)用程序從“spring.config.name”等于{application}參數(shù)加載配置文件蚁孔,“spring.profiles.active”等于{profiles}參數(shù)奶赔。配置文件的優(yōu)先級(jí)規(guī)則也與常規(guī)啟動(dòng)應(yīng)用程序中的相同:活動(dòng)配置文件優(yōu)先于默認(rèn)配置,如果存在多個(gè)配置文件杠氢,則最后一個(gè)配置文件(例如向Map添加條目))站刑。

示例:客戶(hù)端應(yīng)用程序具有此引導(dǎo)配置:

bootstrap.yml

spring:
  application:
    name: foo
  profiles:
    active: dev,mysql

(像往常一樣使用Spring Boot應(yīng)用程序,這些屬性也可以設(shè)置為環(huán)境變量或命令行參數(shù))鼻百。

如果存儲(chǔ)庫(kù)是基于文件的绞旅,則服務(wù)器將從application.yml創(chuàng)建Environment(在所有客戶(hù)端之間共享),foo.yml(以foo.yml優(yōu)先))温艇。如果YAML文件在其中具有指向Spring配置文件的文檔玻靡,則應(yīng)用較高優(yōu)先級(jí)(按照列出的配置文件的順序),并且如果存在特定于配置文件的YAML(或?qū)傩裕┪募斜矗敲催@些文件也應(yīng)用的優(yōu)先級(jí)高于默認(rèn)值。較高優(yōu)先級(jí)轉(zhuǎn)換為Environment之前列出的PropertySource臼朗。(這些規(guī)則與獨(dú)立的Spring Boot應(yīng)用程序相同邻寿。)

Git后端

EnvironmentRepository的默認(rèn)實(shí)現(xiàn)使用Git后端,這對(duì)于管理升級(jí)和物理環(huán)境以及審核更改非常方便视哑。要更改存儲(chǔ)庫(kù)的位置绣否,可以在Config Server中設(shè)置“spring.cloud.config.server.git.uri”配置屬性(例如application.yml)。如果您使用file:前綴進(jìn)行設(shè)置挡毅,則應(yīng)從本地存儲(chǔ)庫(kù)中運(yùn)行蒜撮,以便在沒(méi)有服務(wù)器的情況下快速方便地啟動(dòng),但在這種情況下,服務(wù)器將直接在本地存儲(chǔ)庫(kù)中進(jìn)行操作段磨,而不會(huì)克隆它如果它不是裸機(jī)取逾,因?yàn)榕渲梅?wù)器永遠(yuǎn)不會(huì)更改“遠(yuǎn)程”資源庫(kù))。要擴(kuò)展Config Server并使其高度可用苹支,您需要將服務(wù)器的所有實(shí)例指向同一個(gè)存儲(chǔ)庫(kù)砾隅,因此只有共享文件系統(tǒng)才能正常工作。即使在這種情況下债蜜,最好使用共享文件系統(tǒng)存儲(chǔ)庫(kù)的ssh:協(xié)議晴埂,以便服務(wù)器可以將其克隆并使用本地工作副本作為緩存。

該存儲(chǔ)庫(kù)實(shí)現(xiàn)將HTTP資源的{label}參數(shù)映射到git標(biāo)簽(提交ID寻定,分支名稱(chēng)或標(biāo)簽)儒洛。如果git分支或標(biāo)簽名稱(chēng)包含斜杠(“/”),則應(yīng)使用特殊字符串“(_)”指定HTTP URL中的標(biāo)簽狼速,以避免與其他URL路徑模糊琅锻。例如,如果標(biāo)簽是foo/bar唐含,則替換斜杠將導(dǎo)致類(lèi)似于foo(_)bar的標(biāo)簽浅浮。如果您使用像curl這樣的命令行客戶(hù)端(例如使用引號(hào)將其從shell中轉(zhuǎn)出來(lái)),請(qǐng)小心URL中的方括號(hào)捷枯。

Git URI中的占位符

Spring Cloud Config服務(wù)器支持一個(gè)Git倉(cāng)庫(kù)URL滚秩,其中包含{application}{profile}(以及{label})的占位符,如果需要淮捆,請(qǐng)記住郁油,標(biāo)簽應(yīng)用為git標(biāo)簽)。因此攀痊,您可以使用(例如)輕松支持“每個(gè)應(yīng)用程序的一個(gè)repo”策略:

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/myorg/{application}

或使用類(lèi)似模式“{一個(gè)回報(bào)每個(gè)配置文件”策略桐腌,但使用{profile}

模式匹配和多個(gè)存儲(chǔ)庫(kù)

還可以通過(guò)應(yīng)用程序和配置文件名稱(chēng)的模式匹配來(lái)支持更復(fù)雜的需求苟径。模式格式是帶有通配符的{application}/{profile}名稱(chēng)的逗號(hào)分隔列表(其中以通配符開(kāi)頭的模式可能需要引用)案站。例:

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          repos:
            simple: https://github.com/simple/config-repo
            special:
              pattern: special*/dev*,*special*/dev*
              uri: https://github.com/special/config-repo
            local:
              pattern: local*
              uri: file:/home/configsvc/config-repo

如果{application}/{profile}不匹配任何模式,它將使用在“spring.cloud.config.server.git.uri”下定義的默認(rèn)uri棘街。在上面的例子中蟆盐,對(duì)于“簡(jiǎn)單”存儲(chǔ)庫(kù),模式是simple/*(即所有配置文件中只匹配一個(gè)名為“簡(jiǎn)單”的應(yīng)用程序)遭殉∈遥“本地”存儲(chǔ)庫(kù)與所有配置文件中以“l(fā)ocal”開(kāi)頭的所有應(yīng)用程序名稱(chēng)匹配(將/*后綴自動(dòng)添加到任何沒(méi)有配置文件匹配器的模式)。

|

注意

| 在上述“簡(jiǎn)單”示例中使用的“單行”快捷方式只能在唯一要設(shè)置的屬性為URI的情況下使用险污。如果您需要設(shè)置其他任何內(nèi)容(憑據(jù)痹愚,模式等),則需要使用完整的表單。 |

repo中的pattern屬性實(shí)際上是一個(gè)數(shù)組拯腮,因此您可以使用屬性文件中的YAML數(shù)組(或[0]窖式,[1]等后綴)綁定到多個(gè)模式。如果要運(yùn)行具有多個(gè)配置文件的應(yīng)用程序疾瓮,則可能需要執(zhí)行此操作脖镀。例:

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          repos:
            development:
              pattern:
                - */development
                - */staging
              uri: https://github.com/development/config-repo
            staging:
              pattern:
                - */qa
                - */production
              uri: https://github.com/staging/config-repo

|

注意

| Spring Cloud將猜測(cè)包含不在*中的配置文件的模式意味著您實(shí)際上希望匹配從該模式開(kāi)始的配置文件列表(所以*/staging["*/staging", "*/staging,*"]的快捷方式) 。這是常見(jiàn)的狼电,您需要在本地的“開(kāi)發(fā)”配置文件中運(yùn)行應(yīng)用程序蜒灰,但也可以遠(yuǎn)程運(yùn)行“云”配置文件。 |

每個(gè)存儲(chǔ)庫(kù)還可以選擇將配置文件存儲(chǔ)在子目錄中肩碟,搜索這些目錄的模式可以指定為searchPaths强窖。例如在頂層:

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          searchPaths: foo,bar*

在此示例中,服務(wù)器搜索頂級(jí)和“foo /”子目錄以及名稱(chēng)以“bar”開(kāi)頭的任何子目錄中的配置文件削祈。

默認(rèn)情況下翅溺,首次請(qǐng)求配置時(shí),服務(wù)器克隆遠(yuǎn)程存儲(chǔ)庫(kù)髓抑。服務(wù)器可以配置為在啟動(dòng)時(shí)克隆存儲(chǔ)庫(kù)咙崎。例如在頂層:

spring:
  cloud:
    config:
      server:
        git:
          uri: https://git/common/config-repo.git
          repos:
            team-a:
                pattern: team-a-*
                cloneOnStart: true
                uri: http://git/team-a/config-repo.git
            team-b:
                pattern: team-b-*
                cloneOnStart: false
                uri: http://git/team-b/config-repo.git
            team-c:
                pattern: team-c-*
                uri: http://git/team-a/config-repo.git

在此示例中,服務(wù)器在啟動(dòng)之前克隆了team-a的config-repo吨拍,然后它接受任何請(qǐng)求褪猛。所有其他存儲(chǔ)庫(kù)將不被克隆,直到請(qǐng)求從存儲(chǔ)庫(kù)配置羹饰。

|

注意

| 在配置服務(wù)器啟動(dòng)時(shí)設(shè)置要克隆的存儲(chǔ)庫(kù)可以幫助在配置服務(wù)器啟動(dòng)時(shí)快速識(shí)別錯(cuò)誤配置的源(例如伊滋,無(wú)效的存儲(chǔ)庫(kù)URI)。配置源不啟用cloneOnStart時(shí)队秩,配置服務(wù)器可能啟動(dòng)成功配置錯(cuò)誤或無(wú)效的配置源笑旺,并且不會(huì)檢測(cè)到錯(cuò)誤,直到應(yīng)用程序從該配置源請(qǐng)求配置為止馍资。 |

認(rèn)證

要在遠(yuǎn)程存儲(chǔ)庫(kù)上使用HTTP基本身份驗(yàn)證筒主,請(qǐng)分別添加“username”和“password”屬性(不在URL中),例如

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          username: trolley
          password: strongpassword

如果您不使用HTTPS和用戶(hù)憑據(jù)鸟蟹,則在將密鑰存儲(chǔ)在默認(rèn)目錄(~/.ssh)中物舒,并且uri指向SSH位置時(shí),SSH也應(yīng)該開(kāi)箱即用戏锹,例如“ git@github.com:配置/云配置”。重要的是火诸,Git服務(wù)器的條目存在于~/.ssh/known_hosts文件中锦针,并且格式為ssh-rsa。不支持其他格式(如ecdsa-sha2-nistp256)。為了避免意外奈搜,您應(yīng)該確保Git服務(wù)器的known_hosts文件中只有一個(gè)條目存在悉盆,并且與您提供給配置服務(wù)器的URL匹配。如果您在URL中使用了一個(gè)主機(jī)名馋吗,那么您希望在known_hosts文件中具有該主機(jī)名焕盟,而不是IP。使用JGit訪(fǎng)問(wèn)存儲(chǔ)庫(kù)宏粤,因此您發(fā)現(xiàn)的任何文檔都應(yīng)適用脚翘。HTTPS代理設(shè)置可以~/.git/config設(shè)置,也可以通過(guò)系統(tǒng)屬性(-Dhttps.proxyHost-Dhttps.proxyPort)與任何其他JVM進(jìn)程相同绍哎。

|

提示

| 如果您不知道~/.git目錄在何處使用git config --global操縱設(shè)置(例如git config --global http.sslVerify false)来农。 |

使用AWS CodeCommit進(jìn)行認(rèn)證

AWS CodeCommit認(rèn)證也可以完成。當(dāng)從命令行使用Git時(shí)崇堰,AWS CodeCommit使用身份驗(yàn)證助手沃于。該幫助器不與JGit庫(kù)一起使用,因此如果Git URI與AWS CodeCommit模式匹配海诲,則將創(chuàng)建用于AWS CodeCommit的JGit CredentialProvider繁莹。AWS CodeCommit URI始終看起來(lái)像 https://git-codecommit.{AWS_REGION} .amazonaws.com / {repopath}

如果您使用AWS CodeCommit URI提供用戶(hù)名和密碼特幔,那么這些URI必須 是用于訪(fǎng)問(wèn)存儲(chǔ)庫(kù)的AWS accessKeyId和 secretAccessKey咨演。如果不指定用戶(hù)名和密碼,則將使用AWS默認(rèn)憑據(jù)提供程序鏈檢索accessKeyId和secretAccessKey 敬辣。

如果您的Git URI與CodeCommit URI模式(上述)匹配雪标,則必須在用戶(hù)名和密碼或默認(rèn)憑據(jù)提供程序鏈支持的某個(gè)位置中提供有效的AWS憑據(jù)。AWS EC2實(shí)例可以使用EC2實(shí)例的 IAM角色溉跃。

注意:aws-java-sdk-core jar是一個(gè)可選的依賴(lài)關(guān)系村刨。如果aws-java-sdk-core jar不在您的類(lèi)路徑上,則無(wú)論git服務(wù)器URI如何撰茎,都將不會(huì)創(chuàng)建AWS代碼提交憑據(jù)提供程序嵌牺。

Git搜索路徑中的占位符

Spring Cloud Config服務(wù)器還支持{application}{profile}(以及{label}(如果需要))占位符的搜索路徑。例:

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          searchPaths: '{application}'

在資源庫(kù)中搜索與目錄(以及頂級(jí))相同名稱(chēng)的文件龄糊。通配符在具有占位符的搜索路徑中也是有效的(搜索中包含任何匹配的目錄)逆粹。

力拉入Git存儲(chǔ)庫(kù)

如前所述Spring Cloud Config服務(wù)器克隆遠(yuǎn)程git存儲(chǔ)庫(kù),如果某種方式本地副本變臟(例如炫惩,由操作系統(tǒng)進(jìn)程更改文件夾內(nèi)容)僻弹,則Spring Cloud Config服務(wù)器無(wú)法從遠(yuǎn)程存儲(chǔ)庫(kù)更新本地副本。

要解決這個(gè)問(wèn)題他嚷,有一個(gè)force-pull屬性將使Spring Cloud Config Server強(qiáng)制從遠(yuǎn)程存儲(chǔ)庫(kù)中提取蹋绽,如果本地副本是臟的芭毙。例:

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo
          force-pull: true

如果您有多個(gè)存儲(chǔ)庫(kù)配置,則可以為每個(gè)存儲(chǔ)庫(kù)配置force-pull屬性卸耘。例:

spring:
  cloud:
    config:
      server:
        git:
          uri: https://git/common/config-repo.git
          force-pull: true
          repos:
            team-a:
                pattern: team-a-*
                uri: http://git/team-a/config-repo.git
                force-pull: true
            team-b:
                pattern: team-b-*
                uri: http://git/team-b/config-repo.git
                force-pull: true
            team-c:
                pattern: team-c-*
                uri: http://git/team-a/config-repo.git

|

注意

| force-pull屬性的默認(rèn)值為false退敦。 |

版本控制后端文件系統(tǒng)使用

|

警告

| 使用基于VCS的后端(git,svn)文件被檢出或克隆到本地文件系統(tǒng)蚣抗。默認(rèn)情況下侈百,它們放在系統(tǒng)臨時(shí)目錄中,前綴為config-repo-翰铡。在linux上钝域,例如可以是/tmp/config-repo-<randomid>。一些操作系統(tǒng)會(huì)定期清除臨時(shí)目錄两蟀。這可能會(huì)導(dǎo)致意外的行為网梢,例如缺少屬性。為避免此問(wèn)題赂毯,請(qǐng)通過(guò)將spring.cloud.config.server.git.basedirspring.cloud.config.server.svn.basedir設(shè)置為不在系統(tǒng)臨時(shí)結(jié)構(gòu)中的目錄來(lái)更改Config Server所使用的目錄战虏。 |

文件系統(tǒng)后端

配置服務(wù)器中還有一個(gè)不使用Git的“本機(jī)”配置文件,只是從本地類(lèi)路徑或文件系統(tǒng)加載配置文件(您想要指向的任何靜態(tài)URL“spring.cloud.config.server .native.searchLocations“)党涕。要使用本機(jī)配置文件烦感,只需使用“spring.profiles.active = native”啟動(dòng)Config Server。

|

注意

| 記住使用file:前綴的文件資源(缺省沒(méi)有前綴通常是classpath)膛堤。與任何Spring Boot配置一樣手趣,您可以嵌入${}樣式的環(huán)境占位符,但請(qǐng)記住肥荔,Windows中的絕對(duì)路徑需要額外的“/”绿渣,例如[file:///${user.home}/config-repo](file:///${user.home}/config-repo) |

|

警告

| searchLocations的默認(rèn)值與本地Spring Boot應(yīng)用程序(所以[classpath:/, classpath:/config, file:./, file:./config])相同。這不會(huì)將application.properties從服務(wù)器暴露給所有客戶(hù)端燕耿,因?yàn)樵诎l(fā)送到客戶(hù)端之前中符,服務(wù)器中存在的任何屬性源都將被刪除。 |

|

提示

| 文件系統(tǒng)后端對(duì)于快速入門(mén)和測(cè)試是非常好的誉帅。要在生產(chǎn)中使用它淀散,您需要確保文件系統(tǒng)是可靠的,并在配置服務(wù)器的所有實(shí)例中共享蚜锨。 |

搜索位置可以包含{application}档插,{profile}{label}的占位符。以這種方式亚再,您可以隔離路徑中的目錄郭膛,并選擇一個(gè)有用的策略(例如每個(gè)應(yīng)用程序的子目錄或每個(gè)配置文件的子目錄)。

如果您不在搜索位置使用占位符氛悬,則該存儲(chǔ)庫(kù)還將HTTP資源的{label}參數(shù)附加到搜索路徑上的后綴饲鄙,因此屬性文件將從每個(gè)搜索位置加載具有相同名稱(chēng)的子目錄作為標(biāo)簽(標(biāo)簽屬性在Spring環(huán)境中優(yōu)先)凄诞。因此,沒(méi)有占位符的默認(rèn)行為與添加以/{label}/. For examplefile:/tmp/config結(jié)尾的搜索位置的添加與file:/tmp/config,file:/tmp/config/{label}`相同

Vault后端

Spring Cloud Config服務(wù)器還支持Vault作為后端忍级。

Vault是安全訪(fǎng)問(wèn)秘密的工具。一個(gè)秘密是你想要嚴(yán)格控制訪(fǎng)問(wèn)的任何東西伪朽,如API密鑰轴咱,密碼,證書(shū)等等烈涮。Vault為任何秘密提供統(tǒng)一的界面朴肺,同時(shí)提供嚴(yán)格的訪(fǎng)問(wèn)控制和記錄詳細(xì)的審核日志。

有關(guān)Vault的更多信息坚洽,請(qǐng)參閱Vault快速入門(mén)指南戈稿。

要使配置服務(wù)器使用Vault后端,必須使用vault配置文件運(yùn)行配置服務(wù)器讶舰。例如在配置服務(wù)器的application.properties中鞍盗,您可以添加spring.profiles.active=vault

默認(rèn)情況下跳昼,配置服務(wù)器將假定您的Vault服務(wù)器正在運(yùn)行[http://127.0.0.1:8200](http://127.0.0.1:8200)般甲。它還將假設(shè)后端名稱(chēng)為secret,密鑰為application鹅颊。所有這些默認(rèn)值都可以在配置服務(wù)器的application.properties中配置敷存。以下是可配置的Vault屬性表。所有屬性前綴為spring.cloud.config.server.vault堪伍。

<colgroup><col style="width: 50%;"> <col style="width: 50%;"></colgroup>

名稱(chēng) 默認(rèn)值
主辦 127.0.0.1
港口 8200
方案 HTTP
后端 秘密
defaultKey 應(yīng)用
profileSeparator ,

所有可配置的屬性可以在org.springframework.cloud.config.server.environment.VaultEnvironmentRepository中找到锚烦。

運(yùn)行您的配置服務(wù)器,您可以向服務(wù)器發(fā)出HTTP請(qǐng)求帝雇,以從Vault后端檢索值涮俄。為此,您將需要一個(gè)令牌為您的Vault服務(wù)器摊求。

首先將一些數(shù)據(jù)放在你身上Vault禽拔。例如

$ vault write secret/application foo=bar baz=bam
$ vault write secret/myapp foo=myappsbar

現(xiàn)在,將HTTP請(qǐng)求發(fā)送給您的配置服務(wù)器以檢索值室叉。

$ curl -X "GET" "http://localhost:8888/myapp/default" -H "X-Config-Token: yourtoken"

在提出上述要求后睹栖,您應(yīng)該會(huì)看到類(lèi)似的回復(fù)。

{
   "name":"myapp",
   "profiles":[
      "default"
   ],
   "label":null,
   "version":null,
   "state":null,
   "propertySources":[
      {
         "name":"vault:myapp",
         "source":{
            "foo":"myappsbar"
         }
      },
      {
         "name":"vault:application",
         "source":{
            "baz":"bam",
            "foo":"bar"
         }
      }
   ]
}
多個(gè)屬性來(lái)源

使用Vault時(shí)茧痕,您可以為應(yīng)用程序提供多個(gè)屬性源野来。例如,假設(shè)您已將數(shù)據(jù)寫(xiě)入Vault中的以下路徑踪旷。

secret/myApp,dev
secret/myApp
secret/application,dev
secret/application

寫(xiě)入secret/application的屬性可 用于使用配置服務(wù)器的所有應(yīng)用程序曼氛。名稱(chēng)為myApp的應(yīng)用程序?qū)⒕哂袑?xiě)入secret/myAppsecret/application的任何屬性豁辉。當(dāng)myApp啟用dev配置文件時(shí),寫(xiě)入所有上述路徑的屬性將可用舀患,列表中第一個(gè)路徑中的屬性?xún)?yōu)先于其他路徑徽级。

與所有應(yīng)用共享配置

基于文件的存儲(chǔ)庫(kù)

使用基于文件(即git,svn和native)的存儲(chǔ)庫(kù)聊浅,所有客戶(hù)端應(yīng)用程序(application.properties餐抢,application.ymlapplication-*.properties等))共享文件名為application*的資源低匙。您可以使用這些文件名的資源來(lái)配置全局默認(rèn)值旷痕,并根據(jù)需要將其覆蓋應(yīng)用程序特定的文件。

_property_overrides [屬性覆蓋]功能也可用于設(shè)置全局默認(rèn)值顽冶,并且允許占位符應(yīng)用程序在本地覆蓋它們欺抗。

|

提示

| 使用“本機(jī)”配置文件(本地文件系統(tǒng)后端),建議您使用不屬于服務(wù)器自身配置的顯式搜索位置强重。否則绞呈,默認(rèn)搜索位置中的application*資源將被刪除,因?yàn)樗鼈兪欠?wù)器的一部分竿屹。 |

Vault服務(wù)器

當(dāng)使用Vault作為后端時(shí)报强,您可以通過(guò)將配置放在secret/application中與所有應(yīng)用程序共享配置。例如拱燃,如果您運(yùn)行此Vault命令

$ vault write secret/application foo=bar baz=bam

使用配置服務(wù)器的所有應(yīng)用程序都可以使用屬性foobaz秉溉。

復(fù)合環(huán)境庫(kù)

在某些情況下,您可能希望從多個(gè)環(huán)境存儲(chǔ)庫(kù)中提取配置數(shù)據(jù)碗誉。為此召嘶,只需在配置服務(wù)器的應(yīng)用程序?qū)傩曰験AML文件中啟用多個(gè)配置文件即可。例如哮缺,如果您要從Git存儲(chǔ)庫(kù)以及SVN存儲(chǔ)庫(kù)中提取配置數(shù)據(jù)弄跌,那么您將為配置服務(wù)器設(shè)置以下屬性。

spring:
  profiles:
    active: git, svn
  cloud:
    config:
      server:
        svn:
          uri: file:///path/to/svn/repo
          order: 2
        git:
          uri: file:///path/to/git/repo
          order: 1

除了指定URI的每個(gè)repo之外尝苇,還可以指定order屬性铛只。order屬性允許您指定所有存儲(chǔ)庫(kù)的優(yōu)先級(jí)順序。order屬性的數(shù)值越低糠溜,優(yōu)先級(jí)越高淳玩。存儲(chǔ)庫(kù)的優(yōu)先順序?qū)⒂兄诮鉀Q包含相同屬性的值的存儲(chǔ)庫(kù)之間的任何潛在沖突。

|

注意

| 從環(huán)境倉(cāng)庫(kù)檢索值時(shí)的任何類(lèi)型的故障將導(dǎo)致整個(gè)復(fù)合環(huán)境的故障非竿。 |

|

注意

| 當(dāng)使用復(fù)合環(huán)境時(shí)蜕着,重要的是所有repos都包含相同的標(biāo)簽。如果您有類(lèi)似于上述的環(huán)境红柱,并且使用標(biāo)簽master請(qǐng)求配置數(shù)據(jù)承匣,但是SVN repo不包含稱(chēng)為master的分支蓖乘,則整個(gè)請(qǐng)求將失敗。 |

自定義復(fù)合環(huán)境庫(kù)

除了使用Spring Cloud中的一個(gè)環(huán)境存儲(chǔ)庫(kù)之外韧骗,還可以提供自己的EnvironmentRepository bean作為復(fù)合環(huán)境的一部分嘉抒。要做到這一點(diǎn),你的bean必須實(shí)現(xiàn)EnvironmentRepository接口袍暴。如果您想在復(fù)合環(huán)境中控制自定義EnvironmentRepository的優(yōu)先級(jí)众眨,您還應(yīng)該實(shí)現(xiàn)Ordered接口并覆蓋getOrdered方法。如果您不實(shí)現(xiàn)Ordered接口容诬,則您的EnvironmentRepository將被賦予最低優(yōu)先級(jí)。

屬性覆蓋

Config Server具有“覆蓋”功能沿腰,允許操作員為所有應(yīng)用程序提供配置屬性览徒,這些應(yīng)用程序不會(huì)被應(yīng)用程序使用正常的Spring Boot鉤子意外更改。要聲明覆蓋只是將名稱(chēng)/值對(duì)的地圖添加到spring.cloud.config.server.overrides颂龙。例如

spring:
  cloud:
    config:
      server:
        overrides:
          foo: bar

將導(dǎo)致配置客戶(hù)端的所有應(yīng)用程序獨(dú)立于自己的配置讀取foo=bar习蓬。(當(dāng)然,應(yīng)用程序可以以任何方式使用Config Server中的數(shù)據(jù)措嵌,因此覆蓋不可強(qiáng)制執(zhí)行躲叼,但如果它們是Spring Cloud Config客戶(hù)端,則它們會(huì)提供有用的默認(rèn)行為企巢。)

|

提示

| 通常使用“{}”的Spring環(huán)境占位符可以使用反斜杠(“\”)來(lái)轉(zhuǎn)義(并在客戶(hù)端上解析)來(lái)轉(zhuǎn)義“”或“{”枫慷,例如\${app.foo:bar}解析為“bar “除非該應(yīng)用程序提供自己的”app.foo“。請(qǐng)注意浪规,在YAML中或听,您不需要轉(zhuǎn)義反斜杠本身,而是在您執(zhí)行的屬性文件中配置服務(wù)器上的覆蓋笋婿。 |

您可以將客戶(hù)端中所有覆蓋的優(yōu)先級(jí)更改為更為默認(rèn)值誉裆,允許應(yīng)用程序通過(guò)在遠(yuǎn)程存儲(chǔ)庫(kù)中設(shè)置標(biāo)志spring.cloud.config.overrideNone=true(默認(rèn)值為false),在環(huán)境變量或系統(tǒng)屬性中提供自己的值缸濒。

健康指標(biāo)

配置服務(wù)器附帶運(yùn)行狀況指示器足丢,檢查配置的EnvironmentRepository是否正常工作。默認(rèn)情況下庇配,它要求EnvironmentRepository應(yīng)用程序名為app斩跌,default配置文件和EnvironmentRepository實(shí)現(xiàn)提供的默認(rèn)標(biāo)簽。

您可以配置運(yùn)行狀況指示器以檢查更多應(yīng)用程序以及自定義配置文件和自定義標(biāo)簽讨永,例如

spring:
  cloud:
    config:
      server:
        health:
          repositories:
            myservice:
              label: mylabel
            myservice-dev:
              name: myservice
              profiles: development

您可以通過(guò)設(shè)置spring.cloud.config.server.health.enabled=false來(lái)禁用運(yùn)行狀況指示器滔驶。

安全

您可以以任何對(duì)您有意義的方式(從物理網(wǎng)絡(luò)安全性到OAuth2承載令牌)來(lái)保護(hù)您的Config Server,而Spring Security和Spring Boot可以輕松做任何事情卿闹。

要使用默認(rèn)的Spring Boot配置的HTTP Basic安全性揭糕,只需在類(lèi)路徑中包含Spring Security(例如萝快,通過(guò)spring-boot-starter-security)。默認(rèn)是“user”的用戶(hù)名和隨機(jī)生成的密碼著角,這在實(shí)踐中不會(huì)非常有用揪漩,因此我們建議您配置密碼(通過(guò)security.user.password)進(jìn)行加密(有關(guān)以下內(nèi)容的說(shuō)明,請(qǐng)參閱以下內(nèi)容)怎么做)吏口。

加密和解密

|

重要

| 先決條件:要使用加密和解密功能奄容,您需要在JVM中安裝全面的JCE(默認(rèn)情況下不存在)。您可以從Oracle下載“Java加密擴(kuò)展(JCE)無(wú)限強(qiáng)度管理策略文件”产徊,并按照安裝說(shuō)明(實(shí)際上將JRE lib / security目錄中的2個(gè)策略文件替換為您下載的文件)昂勒。 |

如果遠(yuǎn)程屬性源包含加密內(nèi)容(以{cipher}開(kāi)頭的值)),則在通過(guò)HTTP發(fā)送給客戶(hù)端之前舟铜,它們將被解密戈盈。這種設(shè)置的主要優(yōu)點(diǎn)是,當(dāng)它們“靜止”時(shí)谆刨,屬性值不必是純文本(例如在git倉(cāng)庫(kù)中)塘娶。如果值無(wú)法解密,則從屬性源中刪除該值痊夭,并添加具有相同鍵的附加屬性刁岸,但以“無(wú)效”作為前綴。和“不適用”的值(通常為“<n / a>”)她我。這主要是為了防止密碼被用作密碼并意外泄漏虹曙。

如果要為配置客戶(hù)端應(yīng)用程序設(shè)置遠(yuǎn)程配置存儲(chǔ)庫(kù),可能會(huì)包含一個(gè)application.yml鸦难,例如:

application.yml

spring:
  datasource:
    username: dbuser
    password: '{cipher}FKSAJDFGYOS8F7GLHAKERGFHLSAJ'

.properties文件中的加密值不能用引號(hào)括起來(lái)根吁,否則不會(huì)解密該值:

application.properties

spring.datasource.username: dbuser
spring.datasource.password: {cipher}FKSAJDFGYOS8F7GLHAKERGFHLSAJ

您可以安全地將此純文本推送到共享git存儲(chǔ)庫(kù),并且保密密碼合蔽。

服務(wù)器還暴露了/encrypt/decrypt端點(diǎn)(假設(shè)這些端點(diǎn)將被保護(hù)并且只能由授權(quán)代理訪(fǎng)問(wèn))击敌。如果您正在編輯遠(yuǎn)程配置文件,可以使用Config Server通過(guò)POST到/encrypt端點(diǎn)來(lái)加密值拴事,例如

$ curl localhost:8888/encrypt -d mysecret
682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda

|

注意

| 如果要加密的值具有需要進(jìn)行URL編碼的字符沃斤,則應(yīng)使用--data-urlencode選項(xiàng)curl來(lái)確保它們已正確編碼。 |

逆向操作也可通過(guò)/decrypt獲得(如果服務(wù)器配置了對(duì)稱(chēng)密鑰或完整密鑰對(duì)):

<pre class="notranslate">$ curl localhost:8888/decrypt -d 682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
mysecret</pre>

|

提示

| 如果您使用curl進(jìn)行測(cè)試刃宵,則使用--data-urlencode(而不是-d)或設(shè)置顯式Content-Type: text/plain衡瓶,以確保在有特殊字符時(shí)正確地對(duì)數(shù)據(jù)進(jìn)行編碼('+'特別是棘手)。 |

在加入值之前牲证,先添加{cipher}前綴哮针,然后再將其放在YAML或?qū)傩晕募校缓笤偬峤徊⑵渫扑偷竭h(yuǎn)程,可能不安全的存儲(chǔ)區(qū)十厢。

/encrypt/decrypt端點(diǎn)也都接受/*/{name}/{profiles}形式的路徑等太,當(dāng)客戶(hù)端調(diào)用到主環(huán)境資源時(shí),可以使用每個(gè)應(yīng)用程序(名稱(chēng))和配置文件控制密碼蛮放。

|

注意

| 為了以這種細(xì)微的方式控制密碼缩抡,您還必須提供TextEncryptorLocator類(lèi)型的@Bean,每個(gè)名稱(chēng)和配置文件都會(huì)創(chuàng)建一個(gè)不同的加密器包颁。默認(rèn)提供的不會(huì)這樣做(所有加密使用相同的密鑰)瞻想。 |

spring命令行客戶(hù)端(安裝了Spring Cloud CLI擴(kuò)展名)也可用于加密和解密,例如

$ spring encrypt mysecret --key foo
682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
$ spring decrypt --key foo 682bc583f4641835fa2db009355293665d2647dade3375c0ee201de2a49f7bda
mysecret

要在文件中使用密鑰(例如用于加密的RSA公鑰)娩嚼,使用“@”鍵入鍵值蘑险,并提供文件路徑,例如

$ spring encrypt mysecret --key @${HOME}/.ssh/id_rsa.pub
AQAjPgt3eFZQXwt8tsHAVv/QHiY5sI2dRcR+...

關(guān)鍵參數(shù)是強(qiáng)制性的(盡管有一個(gè)--前綴)岳悟。

密鑰管理

Config Server可以使用對(duì)稱(chēng)(共享)密鑰或非對(duì)稱(chēng)密鑰(RSA密鑰對(duì))漠其。非對(duì)稱(chēng)選擇在安全性方面是優(yōu)越的,但是使用對(duì)稱(chēng)密鑰往往更方便竿音,因?yàn)樗皇桥渲玫囊粋€(gè)屬性值。

要配置對(duì)稱(chēng)密鑰拴驮,您只需要將encrypt.key設(shè)置為一個(gè)秘密字符串(或使用環(huán)境變量ENCRYPT_KEY將其保留為純文本配置文件)春瞬。

要配置非對(duì)稱(chēng)密鑰,您可以將密鑰設(shè)置為PEM編碼的文本值(encrypt.key)或通過(guò)密鑰庫(kù)(例如由JDK附帶的keytool實(shí)用程序創(chuàng)建)套啤。密鑰庫(kù)屬性為encrypt.keyStore.*宽气,*等于

  • locationResource位置),

  • password(解鎖密鑰庫(kù))和

  • alias(以識(shí)別商店中使用的密鑰)潜沦。

使用公鑰進(jìn)行加密萄涯,需要私鑰進(jìn)行解密。因此唆鸡,原則上您只能在服務(wù)器中配置公鑰涝影,如果您只想進(jìn)行加密(并準(zhǔn)備使用私鑰本地解密值)。實(shí)際上争占,您可能不想這樣做燃逻,因?yàn)樗鼑@所有客戶(hù)端傳播密鑰管理流程,而不是將其集中在服務(wù)器中臂痕。另一方面伯襟,如果您的配置服務(wù)器真的相對(duì)不安全,并且只有少數(shù)客戶(hù)端需要加密的屬性握童,這是一個(gè)有用的選項(xiàng)姆怪。

創(chuàng)建用于測(cè)試的密鑰庫(kù)

要?jiǎng)?chuàng)建一個(gè)密鑰庫(kù)進(jìn)行測(cè)試,您可以執(zhí)行以下操作:

$ keytool -genkeypair -alias mytestkey -keyalg RSA \
  -dname "CN=Web Server,OU=Unit,O=Organization,L=City,S=State,C=US" \
  -keypass changeme -keystore server.jks -storepass letmein

server.jks文件放在類(lèi)路徑(例如)中,然后在配置服務(wù)器的application.yml中:

encrypt:
  keyStore:
    location: classpath:/server.jks
    password: letmein
    alias: mytestkey
    secret: changeme

使用多個(gè)鍵和鍵旋轉(zhuǎn)

除了加密屬性值中的{cipher}前綴之外稽揭,配置服務(wù)器在(Base64編碼)密文開(kāi)始之前查找{name:value}前綴(零或多個(gè))俺附。密鑰被傳遞給TextEncryptorLocator,它可以執(zhí)行找到密碼的TextEncryptor所需的任何邏輯淀衣。如果配置了密鑰庫(kù)(encrypt.keystore.location)昙读,默認(rèn)定位器將使用“key”前綴提供的別名,即使用如下密碼來(lái)查找存儲(chǔ)中的密鑰:

foo:
  bar: `{cipher}{key:testkey}...`

定位器將尋找一個(gè)名為“testkey”的鍵膨桥。也可以通過(guò)前綴中的{secret:…?}值提供一個(gè)秘密蛮浑,但是如果不是默認(rèn)值镰矿,則使用密鑰庫(kù)密碼(這是您構(gòu)建密鑰存儲(chǔ)并且不指定密碼時(shí)獲得的密碼)唬复。如果你這樣做 提供一個(gè)秘密建議你也加密使用自定義SecretLocator的秘密。

如果密鑰只用于加密幾個(gè)字節(jié)的配置數(shù)據(jù)(即它們沒(méi)有在其他地方使用)胰舆,則密碼轉(zhuǎn)換幾乎不是必需的册舞,但是如果存在安全漏洞蕴掏,有時(shí)您可能需要更改密鑰實(shí)例。在這種情況下调鲸,所有客戶(hù)端都需要更改其源配置文件(例如git)盛杰,并在所有密碼中使用新的{key:…?}前綴,當(dāng)然藐石,先檢查配置服務(wù)器密鑰庫(kù)中的密鑰別名可用即供。

|

提示

| 如果要讓Config Server處理所有加密以及解密,也可以將{name:value}前綴添加到發(fā)布到/encrypt端點(diǎn)的明文于微。 |

提供加密屬性

有時(shí)您希望客戶(hù)端在本地解密配置逗嫡,而不是在服務(wù)器中進(jìn)行配置。在這種情況下株依,您仍然可以擁有/加密和/解密端點(diǎn)(如果提供encrypt.*配置來(lái)定位密鑰)驱证,但是您需要使用spring.cloud.config.server.encrypt.enabled=false明確地關(guān)閉傳出屬性的解密。如果您不關(guān)心端點(diǎn)恋腕,那么如果您既不配置密鑰也不配置使能的標(biāo)志抹锄,則應(yīng)該起作用。

服務(wù)替代格式

90%高可用的千億級(jí)微服務(wù)架構(gòu)之道深入學(xué)習(xí)一線(xiàn)大廠必備微服務(wù)架構(gòu)技術(shù)荠藤。VIP 教程限時(shí)免費(fèi)領(lǐng)取祈远。 ? 立即查看

來(lái)自環(huán)境端點(diǎn)的默認(rèn)JSON格式對(duì)于Spring應(yīng)用程序的消耗是完美的,因?yàn)樗苯佑成涞?code>Environment抽象商源。如果您喜歡车份,可以通過(guò)向資源路徑(“.yml”,“.yaml”或“.properties”)添加后綴來(lái)使用與YAML或Java屬性相同的數(shù)據(jù)牡彻。這對(duì)于不關(guān)心JSON端點(diǎn)的結(jié)構(gòu)的應(yīng)用程序的消費(fèi)或其提供的額外的元數(shù)據(jù)可能是有用的扫沼,例如出爹,不使用Spring的應(yīng)用程序可能會(huì)受益于此方法的簡(jiǎn)單性。

YAML和屬性表示有一個(gè)額外的標(biāo)志(作為布爾查詢(xún)參數(shù)resolvePlaceholders提供))缎除,以標(biāo)示Spring ${…?}形式的原始文檔中的占位符信號(hào)严就,在渲染之前應(yīng)盡可能在輸出中解析。這對(duì)于不了解Spring占位符約定的消費(fèi)者來(lái)說(shuō)是一個(gè)有用的功能器罐。

|

注意

| 使用YAML或?qū)傩愿袷酱嬖诰窒扌陨椅饕桥c元數(shù)據(jù)的丟失有關(guān)。JSON被構(gòu)造為屬性源的有序列表轰坊,例如铸董,名稱(chēng)與源相關(guān)聯(lián)。即使源的起源具有多個(gè)源肴沫,并且原始源文件的名稱(chēng)丟失粟害,YAML和屬性表也合并成一個(gè)映射。YAML表示不一定是后臺(tái)存儲(chǔ)庫(kù)中YAML源的忠實(shí)表示:它是由平面屬性源的列表構(gòu)建的颤芬,并且必須對(duì)鍵的形式進(jìn)行假設(shè)悲幅。 |

服務(wù)純文本

90%高可用的千億級(jí)微服務(wù)架構(gòu)之道深入學(xué)習(xí)一線(xiàn)大廠必備微服務(wù)架構(gòu)技術(shù)。VIP 教程限時(shí)免費(fèi)領(lǐng)取站蝠。 ? 立即查看

您的應(yīng)用程序可能不需要使用Environment抽象(或YAML中的其他替代表示形式或?qū)傩愿袷剑┨撸歉鶕?jù)自己的環(huán)境需要通用的純文本配置文件。配置服務(wù)器通過(guò)/{name}/{profile}/{label}/{path}中的附加端點(diǎn)提供這些服務(wù)菱魔,其中“name”郁副,“profile”和“l(fā)abel”的含義與常規(guī)環(huán)境端點(diǎn)相同,但“path”是文件名(例如log.xml )豌习。此端點(diǎn)的源文件位于與環(huán)境端點(diǎn)相同的方式:與屬性或YAML文件相同的搜索路徑,而不是聚合所有匹配的資源拔疚,只返回匹配的第一個(gè)肥隆。

資源位置后,使用正常格式(${…?})的占位符使用提供的應(yīng)用程序名稱(chēng)稚失,配置文件和標(biāo)簽的有效Environment來(lái)解析栋艳。以這種方式,資源端點(diǎn)與環(huán)境端點(diǎn)緊密集成句各。例如吸占,如果您有一個(gè)GIT(或SVN)資源庫(kù)的布局:

<pre class="notranslate">application.yml
nginx.conf</pre>

其中nginx.conf看起來(lái)像這樣:

server {
    listen              80;
    server_name         ${nginx.server.name};
}

application.yml這樣:

nginx:
  server:
    name: example.com
---
spring:
  profiles: development
nginx:
  server:
    name: develop.com

那么/foo/default/master/nginx.conf資源如下所示:

server {
    listen              80;
    server_name         example.com;
}

/foo/development/master/nginx.conf如下所示:

server {
    listen              80;
    server_name         develop.com;
}

|

注意

| 就像環(huán)境配置的源文件一樣,“配置文件”用于解析文件名凿宾,所以如果你想要一個(gè)特定于文件的文件矾屯,那么/*/development/*/logback.xml將被一個(gè)名為logback-development.xml的文件解析(優(yōu)先于logback.xml)。 |

嵌入配置服務(wù)器

90%高可用的千億級(jí)微服務(wù)架構(gòu)之道深入學(xué)習(xí)一線(xiàn)大廠必備微服務(wù)架構(gòu)技術(shù)初厚。VIP 教程限時(shí)免費(fèi)領(lǐng)取件蚕。 ? 立即查看

配置服務(wù)器最好作為獨(dú)立應(yīng)用程序運(yùn)行,但如果需要,可以將其嵌入到另一個(gè)應(yīng)用程序中排作。只需使用@EnableConfigServer注釋牵啦。在這種情況下可以使用的可選屬性是spring.cloud.config.server.bootstrap,它是一個(gè)標(biāo)志妄痪,表示服務(wù)器應(yīng)該從自己的遠(yuǎn)程存儲(chǔ)庫(kù)配置自身哈雏。該標(biāo)志默認(rèn)關(guān)閉,因?yàn)樗赡軙?huì)延遲啟動(dòng)衫生,但是當(dāng)嵌入在另一個(gè)應(yīng)用程序中時(shí)裳瘪,以與其他應(yīng)用程序相同的方式初始化是有意義的。

|

注意

| 應(yīng)該很明顯障簿,但是請(qǐng)記住盹愚,如果使用引導(dǎo)標(biāo)志,配置服務(wù)器將需要在bootstrap.yml中配置其名稱(chēng)和存儲(chǔ)庫(kù)URI站故。 |

要更改服務(wù)器端點(diǎn)的位置皆怕,您可以(可選)設(shè)置spring.cloud.config.server.prefix,例如“/ config”西篓,以提供前綴下的資源愈腾。前綴應(yīng)該開(kāi)始但不以“/”結(jié)尾。它應(yīng)用于Config Server中的@RequestMappings(即Spring Boot前綴server.servletPathserver.contextPath)之下岂津。

如果您想直接從后端存儲(chǔ)庫(kù)(而不是從配置服務(wù)器)讀取應(yīng)用程序的配置虱黄,這基本上是一個(gè)沒(méi)有端點(diǎn)的嵌入式配置服務(wù)器。如果不使用@EnableConfigServer注釋?zhuān)ㄖ辉O(shè)置spring.cloud.config.server.bootstrap=true)吮成,則可以完全關(guān)閉端點(diǎn)橱乱。

推送通知和Spring Cloud Bus

90%高可用的千億級(jí)微服務(wù)架構(gòu)之道深入學(xué)習(xí)一線(xiàn)大廠必備微服務(wù)架構(gòu)技術(shù)。VIP 教程限時(shí)免費(fèi)領(lǐng)取粱甫。 ? 立即查看

許多源代碼存儲(chǔ)庫(kù)提供程序(例如Github泳叠,Gitlab或Bitbucket)將通過(guò)webhook通知您存儲(chǔ)庫(kù)中的更改。您可以通過(guò)提供商的用戶(hù)界面將webhook配置為URL和一組感興趣的事件茶宵。例如危纫, Github 將使用包含提交列表的JSON主體和“X-Github-Event”等于“push”的頭文件發(fā)送到webhook。如果您在spring-cloud-config-monitor庫(kù)中添加依賴(lài)關(guān)系并激活配置服務(wù)器中的Spring Cloud Bus乌庶,則啟用“/ monitor”端點(diǎn)种蝶。

當(dāng)Webhook被激活時(shí),配置服務(wù)器將發(fā)送一個(gè)RefreshRemoteApplicationEvent針對(duì)他認(rèn)為可能已經(jīng)改變的應(yīng)用程序瞒大。變更檢測(cè)可以進(jìn)行策略化螃征,但默認(rèn)情況下,它只是查找與應(yīng)用程序名稱(chēng)匹配的文件的更改(例如透敌,“foo.properties”針對(duì)的是“foo”應(yīng)用程序会傲,“application.properties”針對(duì)所有應(yīng)用程序) 锅棕。如果要覆蓋該行為的策略是PropertyPathNotificationExtractor,它接受??請(qǐng)求標(biāo)頭和正文作為參數(shù)淌山,并返回更改的文件路徑列表裸燎。

默認(rèn)配置與Github,Gitlab或Bitbucket配合使用泼疑。除了Github德绿,Gitlab或Bitbucket的JSON通知之外,您還可以通過(guò)使用表單編碼的身體參數(shù)path={name}通過(guò)POST為“/ monitor”來(lái)觸發(fā)更改通知退渗。這將廣播到匹配“{name}”模式的應(yīng)用程序(可以包含通配符)。

|

注意

| 只有在配置服務(wù)器和客戶(hù)端應(yīng)用程序中激活spring-cloud-bus時(shí)才會(huì)傳送RefreshRemoteApplicationEvent会油。 |

|

注意

| 默認(rèn)配置還檢測(cè)本地git存儲(chǔ)庫(kù)中的文件系統(tǒng)更改(在這種情況下不使用webhook个粱,但是一旦編輯配置文件,將會(huì)播放刷新)翻翩。 |

Spring Cloud Config客戶(hù)端

90%高可用的千億級(jí)微服務(wù)架構(gòu)之道深入學(xué)習(xí)一線(xiàn)大廠必備微服務(wù)架構(gòu)技術(shù)都许。VIP 教程限時(shí)免費(fèi)領(lǐng)取。 ? 立即查看

一個(gè)Spring Boot應(yīng)用程序可以立即利用Spring Config Server(或應(yīng)用程序開(kāi)發(fā)人員提供的其他外部屬性源)嫂冻,并且還將獲取與Environment更改事件相關(guān)的一些其他有用功能胶征。

配置第一引導(dǎo)

這是在類(lèi)路徑中具有Spring Cloud Config Client的任何應(yīng)用程序的默認(rèn)行為。當(dāng)配置客戶(hù)端啟動(dòng)時(shí)桨仿,它將通過(guò)配置服務(wù)器(通過(guò)引導(dǎo)配置屬性spring.cloud.config.uri)綁定并使用遠(yuǎn)程屬性源初始化Spring Environment睛低。

這樣做的最終結(jié)果是所有想要使用配置服務(wù)器的客戶(hù)端應(yīng)用程序都需要spring.cloud.config.uri(默認(rèn)為“http:// localhost:8888”)的bootstrap.yml(或環(huán)境變量) )。

發(fā)現(xiàn)第一個(gè)引導(dǎo)

如果您正在使用“DiscoveryClient”實(shí)現(xiàn)服傍,例如Spring Cloud Netflix和Eureka Service Discovery或Spring Cloud Consul(Spring Cloud Zookeeper還不支持此功能)钱雷,那么您可以讓Config Server注冊(cè)Discovery Discovery,但在默認(rèn)的“配置優(yōu)先”模式下吹零,客戶(hù)端將無(wú)法利用注冊(cè)罩抗。

如果您希望使用DiscoveryClient找到Config Server,可以通過(guò)設(shè)置spring.cloud.config.discovery.enabled=true(默認(rèn)為“false”)來(lái)實(shí)現(xiàn)瘪校。最終的結(jié)果是客戶(hù)端應(yīng)用程序都需要具有適當(dāng)?shù)陌l(fā)現(xiàn)配置的bootstrap.yml(或環(huán)境變量)。例如名段,使用Spring Cloud Netflix阱扬,您需要定義Eureka服務(wù)器地址,例如eureka.client.serviceUrl.defaultZone伸辟。使用此選項(xiàng)的價(jià)格是啟動(dòng)時(shí)額外的網(wǎng)絡(luò)往返麻惶,以定位服務(wù)注冊(cè)。好處是配置服務(wù)器可以更改其坐標(biāo)信夫,只要發(fā)現(xiàn)服務(wù)是一個(gè)固定點(diǎn)窃蹋。默認(rèn)的服務(wù)標(biāo)識(shí)是“configserver”卡啰,但是您可以使用spring.cloud.config.discovery.serviceId在客戶(hù)端上進(jìn)行更改(在服務(wù)器上可以通過(guò)設(shè)置spring.application.name以通常方式更改服務(wù)。

發(fā)現(xiàn)客戶(hù)端實(shí)現(xiàn)都支持某種元數(shù)據(jù)映射(例如警没,對(duì)于Eureka匈辱,我們有eureka.instance.metadataMap)∩奔#可能需要在其服務(wù)注冊(cè)元數(shù)據(jù)中配置Config Server的一些其他屬性亡脸,以便客戶(hù)端可以正確連接。如果使用HTTP Basic安全配置服務(wù)器树酪,則可以將憑據(jù)配置為“用戶(hù)名”和“密碼”浅碾。并且如果配置服務(wù)器具有上下文路徑,您可以設(shè)置“configPath”续语。例如垂谢,對(duì)于作為Eureka客戶(hù)端的配置服務(wù)器:

bootstrap.yml

eureka:
  instance:
    ...
    metadataMap:
      user: osufhalskjrtl
      password: lviuhlszvaorhvlo5847
      configPath: /config

配置客戶(hù)端快速失敗

在某些情況下,如果服務(wù)無(wú)法連接到配置服務(wù)器疮茄,則可能希望啟動(dòng)服務(wù)失敗滥朱。如果這是所需的行為,請(qǐng)?jiān)O(shè)置引導(dǎo)配置屬性spring.cloud.config.failFast=true娃豹,客戶(hù)端將以異常停止焚虱。

配置客戶(hù)端重試

如果您希望配置服務(wù)器在您的應(yīng)用程序啟動(dòng)時(shí)可能偶爾不可用,您可以要求它在發(fā)生故障后繼續(xù)嘗試懂版。首先鹃栽,您需要設(shè)置spring.cloud.config.failFast=true,然后您需要將spring-retryspring-boot-starter-aop添加到您的類(lèi)路徑中躯畴。默認(rèn)行為是重試6次民鼓,初始退避間隔為1000ms,指數(shù)乘數(shù)為1.1蓬抄,用于后續(xù)退避丰嘉。您可以使用spring.cloud.config.retry.*配置屬性配置這些屬性(和其他)。

|

提示

| 要完全控制重試嚷缭,請(qǐng)使用id“configServerRetryInterceptor”添加RetryOperationsInterceptor類(lèi)型的@Bean饮亏。Spring Retry有一個(gè)RetryInterceptorBuilder,可以輕松創(chuàng)建一個(gè)阅爽。 |

查找遠(yuǎn)程配置資源

配置服務(wù)從/{name}/{profile}/{label}提供屬性源路幸,客戶(hù)端應(yīng)用程序中的默認(rèn)綁定

  • “name”= ${spring.application.name}

  • “profile”= ${spring.profiles.active}(實(shí)際上是Environment.getActiveProfiles()

  • “l(fā)abel”=“master”

所有這些都可以通過(guò)設(shè)置spring.cloud.config.*(其中*是“name”,“profile”或“l(fā)abel”)來(lái)覆蓋付翁〖螂龋“標(biāo)簽”可用于回滾到以前版本的配置; 使用默認(rèn)的Config Server實(shí)現(xiàn),它可以是git標(biāo)簽百侧,分支名稱(chēng)或提交ID砰识。標(biāo)簽也可以以逗號(hào)分隔的列表形式提供能扒,在這種情況下,列表中的項(xiàng)目會(huì)逐個(gè)嘗試辫狼,直到成功初斑。例如,當(dāng)您可能希望將配置標(biāo)簽與您的分支對(duì)齊予借,但使其成為可選(例如spring.cloud.config.label=myfeature,develop)時(shí)越平,這對(duì)于在特征分支上工作時(shí)可能很有用。

安全

如果您在服務(wù)器上使用HTTP基本安全性灵迫,那么客戶(hù)端只需要知道密碼(如果不是默認(rèn)用戶(hù)名)秦叛。您可以通過(guò)配置服務(wù)器URI,或通過(guò)單獨(dú)的用戶(hù)名和密碼屬性瀑粥,例如

bootstrap.yml

spring:
  cloud:
    config:
     uri: https://user:secret@myconfig.mycompany.com

要么

bootstrap.yml

spring:
  cloud:
    config:
     uri: https://myconfig.mycompany.com
     username: user
     password: secret

spring.cloud.config.passwordspring.cloud.config.username值覆蓋URI中提供的任何內(nèi)容挣跋。

如果您在Cloud Foundry部署應(yīng)用程序,則提供密碼的最佳方式是通過(guò)服務(wù)憑證(例如URI)狞换,因?yàn)樗踔敛恍枰谂渲梦募斜芘亍T贑loud Foundry上為本地工作的用戶(hù)提供的服務(wù)的一個(gè)例子,名為“configserver”:

bootstrap.yml

spring:
  cloud:
    config:
     uri: ${vcap.services.configserver.credentials.uri:http://user:password@localhost:8888}

如果您使用另一種形式的安全性修噪,則可能需要向ConfigServicePropertySourceLocator提供RestTemplate(例如查库,通過(guò)在引導(dǎo)上下文中獲取它并注入一個(gè))。ConfigServicePropertySourceLocator 提供{249 /}(例如通過(guò)在引導(dǎo)上下文中獲取它并注入)黄琼。

健康指標(biāo)

配置客戶(hù)端提供嘗試從配置服務(wù)器加載配置的Spring Boot運(yùn)行狀況指示器樊销。可以通過(guò)設(shè)置health.config.enabled=false來(lái)禁用運(yùn)行狀況指示器脏款。由于性能原因围苫,響應(yīng)也被緩存。默認(rèn)緩存生存時(shí)間為5分鐘撤师。要更改該值剂府,請(qǐng)?jiān)O(shè)置health.config.time-to-live屬性(以毫秒為單位)。

提供自定義RestTemplate

在某些情況下剃盾,您可能需要從客戶(hù)端自定義對(duì)配置服務(wù)器的請(qǐng)求腺占。通常這涉及傳遞特殊的Authorization標(biāo)頭來(lái)對(duì)服務(wù)器的請(qǐng)求進(jìn)行身份驗(yàn)證。要提供自定義RestTemplate痒谴,請(qǐng)按照以下步驟操作衰伯。

  1. 設(shè)置spring.cloud.config.enabled=false以禁用現(xiàn)有的配置服務(wù)器屬性源。

  2. 使用PropertySourceLocator的實(shí)現(xiàn)創(chuàng)建一個(gè)新的配置bean闰歪。

CustomConfigServiceBootstrapConfiguration.java

@Configuration
public class CustomConfigServiceBootstrapConfiguration {
    @Bean
    public ConfigClientProperties configClientProperties() {
        ConfigClientProperties client = new ConfigClientProperties(this.environment);
        client.setEnabled(false);
        return client;
    }

    @Bean
    public ConfigServicePropertySourceLocator configServicePropertySourceLocator() {
        ConfigClientProperties clientProperties = configClientProperties();
       ConfigServicePropertySourceLocator configServicePropertySourceLocator =  new ConfigServicePropertySourceLocator(clientProperties);
        configServicePropertySourceLocator.setRestTemplate(customRestTemplate(clientProperties));
        return configServicePropertySourceLocator;
    }
}
  1. resources/META-INF中創(chuàng)建一個(gè)名為spring.factories的文件嚎研,并指定您的自定義配置蓖墅。

spring.factorties

org.springframework.cloud.bootstrap.BootstrapConfiguration = com.my.config.client.CustomConfigServiceBootstrapConfiguration

Vault

當(dāng)使用Vault作為配置服務(wù)器的后端時(shí)库倘,客戶(hù)端將需要為服務(wù)器提供令牌以從Vault中檢索值临扮。可以通過(guò)在bootstrap.yml中設(shè)置spring.cloud.config.token來(lái)在客戶(hù)端中提供此令牌教翩。

bootstrap.yml

spring:
  cloud:
    config:
      token: YourVaultToken

Vault

嵌套密鑰在Vault

Vault支持將鍵嵌入存儲(chǔ)在Vault中的值杆勇。例如

echo -n '{"appA": {"secret": "appAsecret"}, "bar": "baz"}' | vault write secret/myapp -

此命令會(huì)將JSON對(duì)象寫(xiě)入您的Vault。要在Spring中訪(fǎng)問(wèn)這些值饱亿,您將使用傳統(tǒng)的點(diǎn)(蚜退。)注釋。例如

@Value("${appA.secret}")
String name = "World";

上述代碼將name變量設(shè)置為appAsecret彪笼。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末钻注,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子配猫,更是在濱河造成了極大的恐慌幅恋,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件泵肄,死亡現(xiàn)場(chǎng)離奇詭異捆交,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)腐巢,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén)品追,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人冯丙,你說(shuō)我怎么就攤上這事肉瓦。” “怎么了银还?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵风宁,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我蛹疯,道長(zhǎng)戒财,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任捺弦,我火速辦了婚禮饮寞,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘列吼。我一直安慰自己幽崩,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布寞钥。 她就那樣靜靜地躺著慌申,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蹄溉,一...
    開(kāi)封第一講書(shū)人閱讀 51,292評(píng)論 1 301
  • 那天咨油,我揣著相機(jī)與錄音,去河邊找鬼柒爵。 笑死役电,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的棉胀。 我是一名探鬼主播法瑟,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼唁奢!你這毒婦竟也來(lái)了霎挟?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤麻掸,失蹤者是張志新(化名)和其女友劉穎氓扛,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體论笔,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡采郎,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了狂魔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蒜埋。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖最楷,靈堂內(nèi)的尸體忽然破棺而出整份,到底是詐尸還是另有隱情,我是刑警寧澤籽孙,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布烈评,位于F島的核電站,受9級(jí)特大地震影響犯建,放射性物質(zhì)發(fā)生泄漏讲冠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一适瓦、第九天 我趴在偏房一處隱蔽的房頂上張望竿开。 院中可真熱鬧,春花似錦玻熙、人聲如沸否彩。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)列荔。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間贴浙,已是汗流浹背筷转。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留悬而,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓锭汛,卻偏偏與公主長(zhǎng)得像笨奠,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子唤殴,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354