spring cloud config学习四:config server 高可用

高可用配置

当要将配置中心部署到生产环境时,与服务注册一样,需要时高可用的应用。spring cloud config实现服务端的高可用。spring cloud config实现服务端的高可用非常简单,主要有以下两种方式:

  • 传统方式:不需要为这些服务端做任何额外的配置,遵循一个规则,将所有的config server都指向同一个git仓库,这样所有的配置内容就通过统一的共享文件系统来维护。而客户端在指定config server位置时,只需要配置config server上层的负载均衡设置地址即可。(此时要借助nginx等服务了)
  • 服务模式: 将config server作为一个普通的微服务应用,纳入到eureka的服务治理体系中。这样我们的微服务应用就可以通过配置中心的服务名来获取配置信息,这种方式比起传统的实现模式来说更加有利于维护,因为对于服务端的负载均衡配置和客户端的配置中心制定都通过服务治理机制一并解决了,即实现了高可用,也实现了自维护。

客户端详解

uri指定配置中心(Config First Bootstrap)

spring cloud config的客户端在启动的时候,默认会从工程的classpath中加载配置信息并启动应用。只有当我们配置spring.cloud.config.uri的时候,客户端应用才会尝试连接spring cloud config的服务端来获取远程配置信息并初始化spring环境配置。同时,我们必须将该参数配置在bootstrap.yml,环境变量或是其他优先级高于应用jar包内的配置信息中,才能正确加载到远程配置。若不指定spring.cloud.uri参数的话,spring cloud config的客户端会默认尝试连接http://localhost:8888

spring:
  application:
    name: zhihaomiao
  cloud:
    config:
      uri: http://localhost:9090/
      profile: pro
      label: config-label-test

参考资料
config-first-bootstrap

服务化配置中心(Discovery First Bootstrap)

config server注册到服务中心,并被其他应用所发现实现配置信息获取。我们把config server看作一个微服务。

对快速入门进行改造:

服务端配置:

  • 在config-server的pom.xml总增加eureka依赖,如下:
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
  • 在application.yml中配置注册eureka的相关参数:
security:
  basic:
    enabled: true
  user:
    name: user
    password: root123456
spring:
  application:
    name: config-server-git
  cloud:
    config:
      server:
        git:
          uri: http://git.oschina.net/zhihaomiao/{application}-config
          username: zhihao.miao
          password: 13579qwertyu
server:
  port: 9090

encrypt:
  key: zhihao.miao

eureka:
  client:
    service-url:
     defaultZone: http://localhost:8761/eureka
  instance:
    instance-id:  ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}
    prefer-ip-address: true
  • 在应用主类中,新增@EnableDiscoveryClient注解,用来将config-server注册到配置中心
@EnableDiscoveryClient
@EnableConfigServer
@SpringBootApplication
public class ConfigServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication.class,args);
    }
}
  • 启动eureka服务,可以看到config-servereureka控制面板的信息。

客户端配置:

  • order-service的pom中新增了eureka依赖,以实现客户端发现config-server服务,具体依赖如下:
<dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
  • 在bootstrap.yml中,按如下配置:
spring:
  application:
    name: order-service
  cloud:
    config:
      discovery:
        enabled: true
        service-id: config-server-git
      username: user
      password: root123456
      profile: pro
      label: master
server:
  port: 6060


eureka:
  client:
    service-url:
     defaultZone: http://localhost:8761/eureka
  instance:
    instance-id:  ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}
    prefer-ip-address: true

其中,通过eureka.client.service-url.defaultZone参数指定服务注册中心,用于服务的注册与发现,将spring.cloud.config.discovery.enabled参数设置为true,开启通过服务来访问config server的功能;spring.cloud.config. discovery.service-id参数来指定config server注册的服务名。这里的spring.application.namespring.cloud.config.profile和之前一样,定位git中的资源。

  • 应用主类上加上@EnableDiscoveryClient注解,用来发现config-server-git的服务,利用其发现服务进行加载应用配置:
@EnableDiscoveryClient
@SpringBootApplication
public class ConfigClientApplication {

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

官网中还有这一段:

The discovery client implementations all support some kind of metadata map (e.g. for Eureka we have eureka.instance.metadataMap). Some additional properties of the Config Server may need to be configured in its service registration metadata so that clients can connect correctly. If the Config Server is secured with HTTP Basic you can configure the credentials as "username" and "password". And if the Config Server has a context path you can set "configPath". Example, for a Config Server that is a Eureka client:

服务发现客户端实现都支持一些元数据映射(例如,对于Eureka,我们有eureka.instance.metadataMap配置)。 可能需要在其服务注册元数据中配置Config Server的一些其他属性,以便客户端可以正确连接。 如果使用HTTP Basic安全配置服务器,则可以将凭据配置为“用户名”和“密码”。 并且如果配置服务器具有上下文路径,您可以设置“configPath”。 例如,对于作为Eureka客户端的配置服务器:
bootstrap.yml

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

在我的理解就是服务注册的客户端与服务注册服务端进行数据交互验证的时候可以使用这个属性

参考资料
Discovery First Bootstrap

失败快速响应与重试

spring cloud config的客户端会预先加载很多其他信息,然后再开始连接config server进行属性的注入,当我们构建的应用比较复杂的时候,可能在连接config server之前花费太多的启动时间,而在一些特殊的场景下,我们希望可以快速知道当前应用是否能顺利地从config server获取到配置信息,这对在初期构建调试环境时,可以减少很多等待启动的时间。要实现客户端优先判断config server获取是否正常,并快速响应失败内容,只需在bootstrap.yml中配置参数spring.cloud.config.failFast=true即可。

测试一下,在没有该参数前,不启动config server,直接启动客户端应用,可以获得下面的报错信息,同时,在报错之前,可以看到客户端应用已经加载了很多内容,比如controller的请求,只有在属性注入的时候报错了,

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'configClientController': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'spring.datasource.username' in value "${spring.datasource.username}"

加上spring.cloud.config.failFast=true参数之后,再启动客户端应用,可以获得下面的报错信息,并且前置的加载内容少了很多,这样通过该参数有效避免了当config server配置有误时,不需要多等待前置的一些加载时间,实现快速失败信息。

java.lang.IllegalStateException: Could not locate PropertySource and the fail fast property is set, failing
    at org.springframework.cloud.config.client.ConfigServicePropertySourceLocator.locate(ConfigServicePropertySourceLocator.java:130) ~[spring-cloud-config-client-1.2.3.RELEASE.jar:1.2.3.RELEASE]
    at org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration.initialize(PropertySourceBootstrapConfiguration.java:89) ~[spring-cloud-context-1.1.9.RELEASE.jar:1.1.9.RELEASE]
    at org.springframework.boot.SpringApplication.applyInitializers(SpringApplication.java:636) [spring-boot-1.4.5.RELEASE.jar:1.4.5.RELEASE]
    at org.springframework.boot.SpringApplication.prepareContext(SpringApplication.java:350) [spring-boot-1.4.5.RELEASE.jar:1.4.5.RELEASE]

上面,我们演示了当config server宕机或是客户端配置不正确导致连接不到而启动失败的情况,快速响应的配置可以发挥比较好的效果。但是,若只是因为网络波动等其他间歇性原因导致的问题,直接启动失败似乎代价有点高。所以,config客户端还提供了重试的功能,在开启重试功能前,先确保已经配置了spring.cloud.config.failFast=true,在进行下面的操作:

  • pom.xml中增加spring.retryspring-boot-starter-aop依赖:
<dependency>
       <groupId>org.springframework.retry</groupId>
       <artifactId>spring-retry</artifactId>
</dependency>
<dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

不需要做其他任何配置,启动客户端应用,在控制台中可以看到如下内容,客户端连接config server失败之后,继续尝试,直到第6次失败后,才返回错误信息。通过这样的重试机制,可以避免一些间歇性问题引起的失败导致客户端应用无法启动的情况。

2017-08-18 18:29:44.142  INFO 55961 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888
2017-08-18 18:29:45.211  INFO 55961 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888
2017-08-18 18:29:46.345  INFO 55961 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888
2017-08-18 18:29:47.578  INFO 55961 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888
2017-08-18 18:29:48.923  INFO 55961 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888
2017-08-18 18:29:50.399  INFO 55961 --- [           main] c.c.c.ConfigServicePropertySourceLocator : Fetching config from server at: http://localhost:8888
2017-08-18 18:29:50.405  WARN 55961 --- [           main] o.s.boot.SpringApplication               : Error handling failed (ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@1d61c6dc: startup date [Thu Jan 01 08:00:00 CST 1970]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@3af9c5b7)
2017-08-18 18:29:50.413 ERROR 55961 --- [           main] o.s.boot.SpringApplication               : Application startup failed

如果是配置具体的uri的话那么就会重试6次的uri配置,如果是配置的eureka注册的话,就会发6次http://localhost:8888失败。

若对默认的最大重试次数和重试间隔等设置不满意,还可以通过下面的参数进行调整:

  • spring.cloud.config.retry.multiplier:初始重试间隔时间(单位为毫秒),默认是1000毫秒。
  • spring.cloud.config.retry.initial-interval:下一个间隔的乘数,默认是1.1,所以当最初间隔式1000毫秒时,下一次失败后的间隔为1100毫秒。
  • spring.cloud.config.retry.max-interval:最大间隔时间,默认是2000毫秒。
  • spring.cloud.config.retry.max-attempts:最大重试次数,默认为6次。

参考资料
Config Client Fail Fast
Config Client Retry

获取远程配置

在快速入门中,我们对 {application}, {profile}, {label}这些参数已经有了一定的了解。在git仓库中,一个形如 {application}-{profile}.properties或是 {application}-{profile}.yml的配置文件,通过uri请求和客户端配置访问对应可以总结如下:

  • 通过向config-server发送get请求以直接的方式获取,可用下面的链接形式:

不带{label}分支信息,默认访问master分支,可使用

  • /{application}-{profile}.yml
  • /{application}-{profile}.properties

带{label}分支信息,可使用:

  • /{label}/{application}-{profile}.yml
  • /{application}/{profile}[/{label}]
  • /{label}/{application}-{profile}.properties
  • 通过客户端配置方式加载的内容如下所示
  • spring.application.name: 对应配置文件中的{application}内容
  • spring.application.profile: 对应配置文件中{profile}内容
  • spring.application.config.label: 对应分支内容,如不配置,默认为master

参考资料
Locating Remote Configuration Resources

本博客代码
代码地址
配置仓库
user服务配置仓库
order服务配置仓库

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,378评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,356评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,702评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,259评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,263评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,036评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,349评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,979评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,469评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,938评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,059评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,703评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,257评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,262评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,501评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,792评论 2 345

推荐阅读更多精彩内容