• Spring Cloud config之一:分布式配置中心config server介绍


    Spring Cloud Config为服务端和客户端提供了分布式系统的外部化配置支持。配置服务器为各应用的所有环境提供了一个中心化的外部配置。它实现了对服务端和客户端对Spring Environment和PropertySource抽象的映射,所以它除了适用于Spring构建的应用程序,也可以在任何其他语言运行的应用程序中使用。作为一个应用可以通过部署管道来进行测试或者投入生产,我们可以分别为这些环境创建配置,并且在需要迁移环境的时候获取对应环境的配置来运行。

    配置服务器默认采用git来存储配置信息,这样就有助于对环境配置进行版本管理,并且可以通过git客户端工具来方便的管理和访问配置内容。当然他也提供本地化文件系统的存储方式,下面从这两方面介绍如何使用分布式配置来存储微服务应用多环境的配置内容。

    一、构建Config Server配置中心+config client(微服务配置使用demo)

    1.首先我们需要一个远程的Git仓库,自己学习可以直接用GitHub,在在实际生产环境中,需要自己搭建一个Git服务器,远程Git仓库的作用主要是用来保存我们的配置文件
    2.除了远程Git仓库之外,我们还需要一个本地Git仓库,每当Config Server访问远程Git仓库时,都会保存一份到本地,这样当远程仓库无法连接时,就直接使用本地存储的配置信息
    3.至于微服务A、微服务B则是我们具体的应用,这些应用在启动的时候会从Config Server中来加载相应的配置信息
    4.当微服务A/B尝试去从Config Server中加载配置信息的时候,Config Server会先通过git clone命令克隆一份配置文件保存到本地
    5.由于配置文件是存储在Git仓库中,所以配置文件天然的具备版本管理功能,Git中的Hook功能可以实时监控配置文件的修改

    1.1、构建Config Server

    通过Spring Cloud构建一个Config Server,新建一个maven工程SCconfigcenter,非常简单,只需要三步:

    • pom.xml中引入spring-cloud-config-server依赖,完整依赖配置如下:
      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
          <modelVersion>4.0.0</modelVersion>
          <groupId>com.dxz</groupId>
          <artifactId>SCconfigcenter</artifactId>
          <version>0.0.1-SNAPSHOT</version>
          <parent>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-parent</artifactId>
              <version>1.3.5.RELEASE</version>
              <relativePath /> <!-- lookup parent from repository -->
          </parent>
      
          <dependencies>
      
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-test</artifactId>
                  <scope>test</scope>
              </dependency>
      
              <dependency>
                  <groupId>org.springframework.cloud</groupId>
                  <artifactId>spring-cloud-config-server</artifactId>
              </dependency>
      
          </dependencies>
      
          <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>
      </project>
      View Code
    • 创建Spring Boot的程序主类,并添加@EnableConfigServer注解,开启Config Server
    package com.dxz;
    
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.builder.SpringApplicationBuilder;
    import org.springframework.cloud.config.server.EnableConfigServer;
    
    @EnableConfigServer
    @SpringBootApplication
    public class SCconfigCenterApplication {
        public static void main(String[] args) {
            new SpringApplicationBuilder(SCconfigCenterApplication.class).web(true).run(args);
        }
    }
    • application.properties中配置服务信息以及git信息,例如:
      spring.application.name=config-server
      server.port=7001
      
      spring.cloud.config.server.git.uri=http://git.oschina.net/duanxz/springcloud-config-server/
      spring.cloud.config.server.git.searchPaths=config-server
      spring.cloud.config.server.git.username=18*****6@qq.com
      spring.cloud.config.server.git.password=******
    • 到这里,使用一个通过Spring Cloud Config实现,并使用git管理内容的配置中心已经完成了,启动该应用,成功后开始下面的内容。spring.cloud.config.server.git.uri:配置git仓库位置
    • spring.cloud.config.server.git.searchPaths:配置仓库路径下的相对搜索位置,可以配置多个
    • spring.cloud.config.server.git.username:访问git仓库的用户名
    • spring.cloud.config.server.git.password:访问git仓库的用户密码

    Spring Cloud Config也提供本地存储配置的方式。我们只需要设置属性spring.profiles.active=native,Config Server会默认从应用的src/main/resource目录下检索配置文件。也可以通过spring.cloud.config.server.native.searchLocations=file:F:/properties/属性来指定配置文件的位置。虽然Spring Cloud Config提供了这样的功能,但是为了支持更好的管理内容和版本控制的功能,还是推荐使用git的方式。

    1.2、config server服务端git配置

    为了验证上面完成的配置服务器,在http://git.oschina.net/duanxz/springcloud-config-server下创建了一个config-repo目录作为配置仓库,并根据不同环境新建了下面四个配置文件:

    • center.properties
    • center-dev.properties
    • center-test.properties
    • center-prod.properties

    其中设置了一个from属性,为每个配置文件分别设置了不同的值,如:

    • from=git-default-1.0
    • from=git-dev-1.0
    • from=git-test-1.0
    • from=git-prod-1.0

    git客户端操作方法如下:

    在sourcetree里创建分支,在分支上创建4个文件,

    推送到服务器上。

    再服务器端创建request,合并到master上。

    为了测试版本控制,在master中,我们都加入1.0的后缀,同时创建一个config-server1.0分支。完成了这些准备工作之后,我们就可以通过浏览器或POSTMAN等工具直接来访问到我们的配置内容了。

    URL与配置文件的映射关系如下:

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

    上面的url会映射{application}-{profile}.properties对应的配置文件,{label}对应git上不同的分支,默认为master。

    我们可以尝试构造不同的url来访问不同的配置内容,比如:要访问config-label-test分支,didispace应用的prod环境,可以通过这个url:http://127.0.0.1:7001/config-server/test/config-server1.0

    {
        "name": "config-server",
        "profiles": [
            "test"
        ],
        "label": "config-server1.0",
        "version": "7e1fdc54c91574ed2f22ed1ef2d7c59714b555ce",
        "propertySources": []
    }

    在完成并验证了配置服务中心之后,下面看看我们如何在微服务应用中获取配置信息。

    default是master分支:

    1.3、config client(微服务配置读取)微服务端映射配置

    • 创建一个Spring Boot应用SCconfigcenterClient的maven工程,在pom.xml中引入spring-cloud-starter-config依赖,完整依赖关系如下:
      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
          <modelVersion>4.0.0</modelVersion>
          <groupId>com.dxz</groupId>
          <artifactId>SCconfigcenterClient</artifactId>
          <version>0.0.1-SNAPSHOT</version>
          <parent>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-parent</artifactId>
              <version>1.3.5.RELEASE</version>
              <relativePath /> <!-- lookup parent from repository -->
          </parent>
          <dependencies>
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-test</artifactId>
                  <scope>test</scope>
              </dependency>
              <dependency>
                  <groupId>org.springframework.boot</groupId>
                  <artifactId>spring-boot-starter-web</artifactId>
              </dependency>
              <dependency>
                  <groupId>org.springframework.cloud</groupId>
                  <artifactId>spring-cloud-starter-config</artifactId>
              </dependency>
          </dependencies>
          <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>
      </project>
      View Code
    • 创建最基本的Spring Boot启动主类
    package com.dxz;
    
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.builder.SpringApplicationBuilder;
    
    @SpringBootApplication
    public class SCconfigcenterClientApplication {
        public static void main(String[] args) {
            new SpringApplicationBuilder(SCconfigcenterClientApplication.class).web(true).run(args);
        }
    }
    • 创建/SCconfigcenterClient/src/main/resources/bootstrap.properties配置,来指定config server,例如:
    spring.application.name=didispace
    spring.cloud.config.profile=dev
    spring.cloud.config.label=master
    spring.cloud.config.uri=http://localhost:7001/
    server.port=7002
    • spring.application.name:对应前配置文件中的{application}部分
    • spring.cloud.config.profile:对应前配置文件中的{profile}部分
    • spring.cloud.config.label:对应前配置文件的git分支
    • spring.cloud.config.uri:配置中心的地址

    这里需要格外注意:上面这些属性必须配置在bootstrap.properties中,config部分内容才能被正确加载。因为config的相关配置会先于application.properties,而bootstrap.properties的加载也是先于application.properties

    • 创建一个Rest Api来返回配置中心的from属性,具体如下:
    package com.dxz.controler;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.cloud.context.config.annotation.RefreshScope;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RefreshScope
    @RestController
    class TestController {
        @Value("${from}")
        private String from;
    
        @RequestMapping("/from")
        public String from() {
            return this.from;
        }
    }

    启动该应用,并访问:http://localhost:7002/from ,我们就可以根据配置内容输出对应环境的from内容了。通过@Value("${from}")绑定配置服务中配置的from属性。

    1.3、配置刷新示例

    有时候,我们需要对配置内容做一些实时更新的场景,那么Spring Cloud Config是否可以实现呢?答案显然是可以的。下面,我们看看如何进行改造来实现配置内容的实时更新。

    在改造程序之前,我们先将config-server和config-client都启动起来,并访问客户端提供的REST API:http://localhost:7002/from来获取配置信息,可以获得返回内容为:git-dev-1.0。接着,我们可以尝试使用Git工具修改当前配置的内容,比如,将config-repo/didispace-dev.properties中的from的值从from=git-dev-1.0修改为from=git-dev-2.0,再访问http://localhost:7002/from,可以看到其返回内容还是git-dev-1.0

    下面,我们将在config-client端增加一些内容和操作以实现配置的刷新:

    • 在config-clinet的pom.xml中新增spring-boot-starter-actuator监控模块,其中包含了/refresh刷新API。
         <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
    •  重新启动config-client,访问一次http://localhost:7002/from,可以看到当前的配置值
    • 修改Git仓库config-repo/didispace-dev.properties文件中from的值
    • 再次访问一次http://localhost:7002/from,可以看到配置值没有改变
    • 通过POST请求发送到http://localhost:7002/refresh,我们可以看到返回内容如下,代表from参数的配置内容被更新了
    • 通过上面的介绍,大家不难想到,该功能还可以同Git仓库的Web Hook功能进行关联,当有Git提交变化时,就给对应的配置主机发送/refresh请求来实现配置信息的实时更新。但是,当我们的系统发展壮大之后,维护这样的刷新清单也将成为一个非常大的负担,而且很容易犯错,那么有什么办法可以解决这个复杂度呢?后续我们将继续介绍如何通过Spring Cloud Bus来实现以消息总线的方式进行通知配置信息的变化,完成集群上的自动化更新。再次访问一次http://localhost:7002/from,可以看到配置值已经是更新后的值了

    二、Config server常用功能

    2.0、config-server的扩展,使用外部存储资源作为config-server的资源

    Spring Cloud Config配置中心可以使用本地,git,svn以及数据库方式实现配置存储等等,也可以通过自己自定义其他外部配置来获取配置数据,比如通过连接mogodb, 或者链接zookeeper, 来实现配置数据的获取,只要定义类去实现EnvironmentRepository接口即可。

    public class CustomEnvironmentRepository implements EnvironmentRepository {
        @Override
        public Environment findOne(String application, String profile, String label) {
            Environment environment = new Environment(application, StringUtils.commaDelimitedListToStringArray(profile), label, null, null);
            PropertySource propertySource = new PropertySource(name, sourceMap);
            environment.add(propertySource);        
            return environment.add;
        }
    }

    2.1、config-server配置本地缓存

    config-client从eureka-server中调用config-server的服务

    1.在config-client的pom中加入依赖:

    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
    </dependency>

    2.改造配置文件,如下:

    #配置文件名称,即 "-" 之前的
    spring.cloud.config.name=config
    #配置文件profile,即"-"之后的
    spring.profiles.active=dev
    #配置文件所在分支
    spring.cloud.config.label=master
    #注册中心地址
    eureka.clent.serviceUrl.defaultZone=http://localhost:8761/eureka/
    spring.application.name=config-client
    #开启去注册中心寻找config-server服务
    spring.cloud.config.discovery.enabled=true
    #注册中心的config-server服务名,会根据这个名称找到地址,从而获取配置
    spring.cloud.config.discovery.service-id=config-server
    server.port=8881
    #配置缓存目录,避免配置丢失.如下的配置会将配置文件缓存在当前工程目录的config-repo文件夹,没有则自动新建
    spring.cloud.config.server.git.basedir=config-repo

    2.2、配置动态刷新

    2.2.1、config client(微服务应用中动态读取和加载配置内容)配置动态刷新

    1、单独引入 spring-boot-starter-actuator或者spring-cloud-starter-config(spring cloud config的客户端)  是不会暴露/refresh端点的,两者同时引入之后才能暴露/refresh端点。

    2、一般使用spring-cloud-starter-config的文章都会让你在bootstrap里加上配置中心服务端的地址,这里我们要脱离配置中心服务端使用,所以这些配置完全不需要。

    3、对需要刷新的属性使用@Value注解,同时将类使用@RefreshScope注解进行标记,示例如下:

    @RefreshScope标记在类或者方法上@value标记在setXXX()或者成员变量上。

    4、然后把yml文件改下,然后push到git上,再curl -X POST http://localhost:7031/refresh(读取应用的)刷一把配置。

    2.2.2、使用Spring Cloud Bus自动刷新配置

    http://www.luyixian.cn/news_show_10499.aspx

    通过消息总线Spring Cloud Bus实现配置文件刷新(使用Kafka)

    2.3、高可用问题

    2.3.1、传统作法

    通常在生产环境,Config Server与服务注册中心一样,我们也需要将其扩展为高可用的集群。在之前实现的config-server基础上来实现高可用非常简单,不需要我们为这些服务端做任何额外的配置,只需要遵守一个配置规则:将所有的Config Server都指向同一个Git仓库,这样所有的配置内容就通过统一的共享文件系统来维护,而客户端在指定Config Server位置时,只要配置Config Server外的均衡负载即可,就像如下图所示的结构:

    2.3.2、将每一台config server注册到服务注册中心为服务

    虽然通过服务端负载均衡已经能够实现,但是作为架构内的配置管理,本身其实也是可以看作架构中的一个微服务。所以,另外一种方式更为简单的方法就是把config-server也注册为服务,这样所有客户端就能以服务的方式进行访问。通过这种方法,只需要启动多个指向同一Git仓库位置的config-server就能实现高可用了。

    配置过程也非常简单,具体如下:

    config-server配置

    • pom.xml的dependencies节点中引入如下依赖,相比之前的config-server就,加入了spring-cloud-starter-eureka,用来注册服务
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.dxz</groupId>
        <artifactId>SCconfigcenter</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.3.5.RELEASE</version>
            <relativePath /> <!-- lookup parent from repository -->
        </parent>
    
        <dependencies>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-config-server</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-eureka</artifactId>
            </dependency>
    
        </dependencies>
    
        <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>
    </project>
    • application.properties中配置参数eureka.client.serviceUrl.defaultZone以指定服务注册中心的位置,详细内容如下:
    spring.application.name=config-server
    server.port=7001
    # u914Du7F6Eu670Du52A1u6CE8u518Cu4E2Du5FC3
    eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/
    # gitu4ED3u5E93u914Du7F6E
    spring.cloud.config.server.git.uri=http://git.oschina.net/didispace/SpringCloud-Learning/
    spring.cloud.config.server.git.searchPaths=Chapter1-1-8/config-repo
    spring.cloud.config.server.git.username=username
    spring.cloud.config.server.git.password=password
    • 在应用主类中,新增@EnableDiscoveryClient注解,用来将config-server注册到上面配置的服务注册中心上去。
    package com.dxz;
    
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.builder.SpringApplicationBuilder;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    import org.springframework.cloud.config.server.EnableConfigServer;
    
    @EnableDiscoveryClient
    @EnableConfigServer
    @SpringBootApplication
    public class SCconfigCenterApplication {
        public static void main(String[] args) {
            new SpringApplicationBuilder(SCconfigCenterApplication.class).web(true).run(args);
        }
    }
    • 启动该应用,并访问http://localhost:1111/,可以在Eureka Server的信息面板中看到config-server已经被注册了。

    config-client配置

    • 同config-server一样,在pom.xml的dependencies节点中新增spring-cloud-starter-eureka依赖,用来注册服务:
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.dxz</groupId>
        <artifactId>SCconfigcenterClient</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.3.5.RELEASE</version>
            <relativePath /> <!-- lookup parent from repository -->
        </parent>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-config</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-eureka</artifactId>
            </dependency>
        </dependencies>
        <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>
    </project>
    • bootstrap.properties中,按如下配置:
    spring.application.name=didispace
    server.port=7002
    eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/
    spring.cloud.config.discovery.enabled=true
    spring.cloud.config.discovery.serviceId=config-server
    spring.cloud.config.profile=dev

    其中,通过eureka.client.serviceUrl.defaultZone参数指定服务注册中心,用于服务的注册与发现,再将spring.cloud.config.discovery.enabled参数设置为true,开启通过服务来访问Config Server的功能,最后利用spring.cloud.config.discovery.serviceId参数来指定Config Server注册的服务名。这里的spring.application.namespring.cloud.config.profile如之前通过URI的方式访问时候一样,用来定位Git中的资源。

    • 在应用主类中,增加@EnableDiscoveryClient注解,用来发现config-server服务,利用其来加载应用配置
    package com.dxz;
    
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.builder.SpringApplicationBuilder;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    
    @EnableDiscoveryClient
    @SpringBootApplication
    public class SCconfigcenterClientApplication {
        public static void main(String[] args) {
            new SpringApplicationBuilder(SCconfigcenterClientApplication.class).web(true).run(args);
        }
    }
    • 沿用之前我们创建的Controller来加载Git中的配置信息
    package com.dxz.controler;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.cloud.context.config.annotation.RefreshScope;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RefreshScope
    @RestController
    class TestController {
        @Value("${from}")
        private String from;
    
        @RequestMapping("/from")
        public String from() {
            return this.from;
        }
    }
    • 完成了上述配置之后,我们启动该客户端应用。若启动成功,访问http://localhost:1111/,可以在Eureka Server的信息面板中看到该应用已经被注册成功了。

    • 访问客户端应用提供的服务:http://localhost:7002/from,此时,我们会返回在Git仓库中didispace-dev.properties文件配置的from属性内容:”git-dev-1.0”。

    2.4、Config Client 失败快速响应与重试

    Spring Boot应用可以立即使用Spring Config Server。只要在classpath中有Spring Cloud Config Client的jar包,这个应用就会请求配置的服务端。他将使用绑定的配置服务器(spring.cloud.config.uri中配置的)的属性初始化spring环境。

      在某些情况下,如果服务无法连接到配置服务器,则可能希望启动服务失败。如果这是所需的行为,请设置引导配置属性spring.cloud.config.failFast=true,客户端将以异常停止。

      如果您希望配置服务器在您的应用程序启动时可能偶尔不可用,您可以要求它在发生故障后继续尝试。首先,您需要设置spring.cloud.config.failFast=true,然后您需要将spring-retry和spring-boot-starter-aop添加到您的类路径中。默认行为是重试6次,初始退避间隔为1000ms,指数乘数为1.1,用于后续退避。您可以使用spring.cloud.config.retry.*配置属性配置这些属性(和其他)。

    细粒度控制重试

    我们可以在代码中实现更精细的控制重试机制,在 web 项目中创建一个新的 java 类 RetryConfiguration,添加如下代码:

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
    import org.springframework.context.annotation.Bean;
    import org.springframework.retry.interceptor.RetryInterceptorBuilder;
    import org.springframework.retry.interceptor.RetryOperationsInterceptor;
    
    public class RetryConfiguration {
        private static Logger log = LoggerFactory.getLogger(RetryConfiguration.class);
    
        @Bean
        @ConditionalOnMissingBean(name = "configServerRetryInterceptor")
        public RetryOperationsInterceptor configServerRetryInterceptor() {
            log.info(String.format(
                    "configServerRetryInterceptor: Changing backOffOptions " +
                            "to initial: %s, multiplier: %s, maxInterval: %s",
                    1000, 1.2, 5000));
            return RetryInterceptorBuilder
                    .stateless()
                    .backOffOptions(1000, 1.2, 5000)
                    .maxAttempts(10)
                    .build();
        }
    }

    这里我们定义了configServerRetryInterceptor方法用于 Spring Retry 使用我们自定义的重试拦截器。方法使用 RetryInterceptorBuilder 按要求创建了一个 stateless 的 RetryOperationsInterceptor,并设置了初始重试间隔为 1000 毫秒,增加倍数为 1.2 倍,最大重试间隔为 5000 毫秒,最大重试次数为 10 次,builder 还提供了诸如配置重试机制之类的接口,有兴趣的读者可自行研究。

    @ConditionalOnMissingBean 标明当 BeanFactory 中没有名为 configServerRetryInterceptor 的 bean 时才匹配此 Bean。

    最后在 src/main/resources/META-INF/ (没有可创建此文件夹) 新建一个 spring.factories 文件,指定我们刚创建类为启动时的配置,以在获取远程配置之前生效

    org.springframework.cloud.bootstrap.BootstrapConfiguration=包路径.RetryConfiguration

    2.5、安全保护

    开发环境中我们的配置中心肯定是不能随随便便被人访问的,我们可以加上适当的保护机制,由于微服务是构建在Spring Boot之上,所以整合Spring Security是最方便的方式。

    首先添加依赖:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>

    然后在application.properties中配置用户名密码:

    security.user.name=sang
    security.user.password=123

    最后在配置中心的客户端上配置用户名和密码即可,如下:

     
    spring.cloud.config.username=sang
    spring.cloud.config.password=123

    OK,如此之后,其他人就不能随意的获取到我们的配置信息了。

    三、问题

    1、git连接不上时,导致config server的异常;

    可能是config-server本地的git库在temp目录下,被删除了。

    #配置缓存目录,避免配置丢失.如下的配置会将配置文件缓存在当前工程目录的config-repo文件夹,没有则自动新建
    basedir: e:logsconfig-repo

    2、config server异常,config client连接不上config server,config client的服务故障问题;

    1、关闭config-server client端对config-server的健康检查。

    2、启动config-server client的快速失败。

    见《Spring Cloud config之三:config-server因为server端和client端的健康检查导致服务超时阻塞问题

  • 相关阅读:
    Active Record 和 Data Mapper 是 ORM 的常见实现方式
    指令重排
    Borg、Omega和Kubernetes:谷歌十几年来从这三个容器管理系统中得到的经验教训 原创: 韩佳瑶 译 Docker 2016-03-23Borg、Omega和Kubernetes:谷歌十几年来从这三个容器管理系统中得到的经验教训 原创: 韩佳瑶 译 Docker 2016-03-23
    等待 Redis 应答 Redis pipeline It's not just a matter of RTT
    阿里巴巴微服务与配置中心技术实践之道 配置推送 ConfigurationManagement ConfigDrivenAnyting
    c3p0数据库连接池 原创: Java之行 Java之行 5月8日 一、连接池概述 实际开发中“获得连接”或“释放资源”是非常消耗系统资源的两个过程
    KA,连接池居然这么简单? 原创: 58沈剑 架构师之路 3月20日
    连接池大小调优 原创: ImportNew ImportNew 2017-06-07
    从另一个线程获取消息的确认
    制作织梦模板channelartlist超强解析
  • 原文地址:https://www.cnblogs.com/duanxz/p/3512408.html
Copyright © 2020-2023  润新知