分布式配置中心: Spring Cloud Config:

  spring cloud config是一个基于http协议的远程配置实现方式。通过统一的配置管理服务器进行配置管理,客户端通过https协议主动的拉取服务的的配置信息,完成配置获取。

  spring cloud config的使用方式非常简单,spring cloud config server默认的实现方式是git管理配置,官方文档介绍已经详细说明有几种使用方式。下面看一下git的spring cloud config server实现方式。

  boot版本:springBoot : 2.0.1.RELEASE

构建配置中心:

1.依赖管理(.pom)

<dependencyManagement>
<dependencies>
<dependency>
<!-- SpringCloud 所有子项目 版本集中管理. 统一所有SpringCloud依赖项目的版本依赖-->
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR3</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.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
</dependencies>

2.启动类注解(@EnableConfigServer)

@SpringBootApplication
@EnableConfigServer
public class App {
private final static Logger log = LoggerFactory.getLogger(App.class); public static void main(String[] args) {
SpringApplication.run(App.class, args);
log.info("服务启动成功"); }
}

3.application.properties 文件配置

server.port = 8888
spring.application.name=config
# 选择的同步工具
spring.profiles.active=git
# git地址
spring.cloud.config.server.git.uri=https://github.com/wuzhenzhao/spring-cloud-config-repo.git
# 搜索目录
spring.cloud.config.server.git.search-paths=properties
# git仓库default-label默认值是master
spring.cloud.config.server.git.default-label=master

  如果仓库是私有的还需要配置如下:

spring.cloud.config.server.git.username=
spring.cloud.config.server.git.password=

  github 上有如下3个环境的配置文件,内容分别是foo=hello-dev / foo=hello-pro / foo=hello-test

  就这样完成了简单的配置,启动程序,如果想获取开发配置,访问http://localhost:8888/config/dev可以读取到config-dev.properties的配置内容。请求配置的参数通过路径参数设置。

  完成了这些准备工作之后,我们就可以通过浏览器、 POSTMAN或CURL等工具直接来访问我们的配置内容了。访问配置信息的URL与配置文件的映射关系如下所示:

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

  上面的 url 会映射 {application}-{profile} .properties 对应的配置文件,其中 {label} 对应Git上不同的分支,默认为 master 。我们可以尝试构造不同的 url 来访问不同的配置内容, 例如:http://localhost:8888/{applicationName}/{profile}/{label} , label分支,不传的话默认master。并获得如下返回信息:

  同时, 我们可以看到 config-server 的控制台中还输出了下面的内容,配置服务器在从 Git 中获取配置信息后, 会存储 一 份在 config-server 的文件系统中, 实质上config-server 是通过 git clone 命令将配置内容复制了一 份在本地存储, 然后读取这些内容并返回给微服务应用进行加载。config-server 通过 Git 在本地仓库暂存,可以有效防止当 Git 仓库出现故障而引起无法加载配置信息的情况。

构建客户端:

1.依赖管理(.pom)

<dependencyManagement>
<dependencies>
<dependency>
<!-- SpringCloud 所有子项目 版本集中管理. 统一所有SpringCloud依赖项目的版本依赖-->
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
</dependencies>

2.bootstrap.properties 配置

server.port = 8889
spring.application.name=config
spring.cloud.config.label=master
spring.cloud.config.profile=test
spring.cloud.config.uri=http://localhost:8888/

3.测试类

@RestController
public class TestRestController { @Value("${foo}")
String foo; @RequestMapping(value = "/hello")
public String hello(){
return foo;
}
}

4.启动类注解 @EnableConfigServer

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({ConfigServerConfiguration.class})
public @interface EnableConfigServer {
}

  项目启动后访问测试类的接口,可以根据配置文件中的spring.cloud.config.profile所配置的环境获取到不同的值。

服务端源码详解:

  注解 EnableConfigServer 可以开启应用服务对配置中心的支持。当开启之后,配置服务器就会在启动时进行自动配置。通过该注解寻找到如下配置。

@Configuration
public class ConfigServerConfiguration {
public ConfigServerConfiguration() {
} @Bean
public ConfigServerConfiguration.Marker enableConfigServerMarker() {
return new ConfigServerConfiguration.Marker();
} class Marker {
Marker() {
}
}
}

  可以看到好像没有继续前进的入口了,仅仅是注入了这个Marker类嘛?通过寻找我们可以发现该类唯一被引用的地方,就是如下类。

@Configuration
@ConditionalOnBean({Marker.class})
@EnableConfigurationProperties({ConfigServerProperties.class})
@Import({EnvironmentRepositoryConfiguration.class,
  CompositeConfiguration.class,
  ResourceRepositoryConfiguration.class,
  ConfigServerEncryptionConfiguration.class,
  ConfigServerMvcConfiguration.class})
public class ConfigServerAutoConfiguration {
public ConfigServerAutoConfiguration() {
}
}

  @ConditionalOnBean(Marker.class)表示当装配了ConfigServerConfiguration.Marker的实例时才会执行ConfigServerAutoConfiguration的处理。

  这里又另外引入了5个配置类。

  EnvironmentRepositoryConfiguration: 环境变量存储相关的配置类

  CompositeConfiguration:组合方式的环境仓库配置类

  ResourceRepositoryConfiguration:资源仓库相关的配置类

  ConfigServerEncryptionConfiguration:加密断点相关的配置类

  ConfigServerMvcConfiguration:对外暴露的MVC端点控制器的配置类,

  对于服务端来说,其基本职责就是能够将具体存储中的配置信息先拿到,然后提供出 API 供客户端来调用。下面从ConfigServerAutoConfiguration 中 import的这些配置类来具体看下实现。

  重点是 EnvironmentRepositoryConfiguration 类。

@Configuration
@EnableConfigurationProperties({
  SvnKitEnvironmentProperties.class,
  JdbcEnvironmentProperties.class,
  NativeEnvironmentProperties.class,
  VaultEnvironmentProperties.class})
@Import({CompositeRepositoryConfiguration.class,
  JdbcRepositoryConfiguration.class,
  VaultRepositoryConfiguration.class,
  SvnRepositoryConfiguration.class,
  NativeRepositoryConfiguration.class,
  GitRepositoryConfiguration.class,
  DefaultRepositoryConfiguration.class})
public class EnvironmentRepositoryConfiguration {
.......
}

  这里的@Import又引入了7种配置类,会发现其实刚好对应config server的几种实现方式git的实现方式使用的配置类就是GitRepositoryConfiguration。以GitRepositoryConfiguration的为例分析。

@Configuration
@Profile({"git"})
class GitRepositoryConfiguration extends DefaultRepositoryConfiguration {
GitRepositoryConfiguration() {
}
}

  GitRepositoryConfiguration 集成了 DefaultRepositoryConfiguration,这也说明了 Spring Cloud Config 默认使用的是Git。不同的配置类实现都会被标注一个@Profile,可以通过这个来激活相应的配置类;具体做法是在配置服务端的 application.properties(application.yml) 中来指定:

spring.profile.active=git

  DefaultRepositoryConfiguration 的 ConditionalOnMissingBean 可以知道,如果上下文中没有 EnvironmentRepository,那么就使用 DefaultRepositoryConfiguration。最后DefaultRepositoryConfiguration是封装了一个 MultipleJGitEnvironmentRepository 这个bean。

@Configuration
@ConditionalOnMissingBean(
value = {EnvironmentRepository.class},
search = SearchStrategy.CURRENT
)
class DefaultRepositoryConfiguration {
@Autowired
private ConfigurableEnvironment environment;
@Autowired
private ConfigServerProperties server;
@Autowired(
required = false
)
private TransportConfigCallback customTransportConfigCallback; DefaultRepositoryConfiguration() {
} @Bean
public MultipleJGitEnvironmentRepository defaultEnvironmentRepository(
        MultipleJGitEnvironmentRepositoryFactory gitEnvironmentRepositoryFactory,
        MultipleJGitEnvironmentProperties environmentProperties) throws Exception {
return gitEnvironmentRepositoryFactory.build(environmentProperties);
}
}

  我们可以先来看一下 MultipleJGitEnvironmentRepository 类的类图:

  这里我们可以发现 MultipleJGitEnvironmentRepository 实现了 InitializingBean 接口,那么在配置加载完以后一定要调用 afterPropertiesSet 方法,我们来看一下具体都做了什么:

public synchronized void afterPropertiesSet() throws Exception {
Assert.state(this.getUri() != null, "You need to configure a uri for the git repository.");
this.initialize();
if (this.cloneOnStart) {
this.initClonedRepository();
} }

  从源码中我们看到,首先会将配置从git上clone到本地,然后再进行其他的操作。接着就本地的git仓库中获取指定的数据了。

  MultipleJGitEnvironmentRepository 的顶层接口是 EnvironmentRepository ,当然其他的实现也都是实现了这个接口的。另外一个需要关注的是 SearchPathLocator。EnvironmentRepository:定义了获取指定应用服务环境信息的方法,返回一个Enviroment

  SearchPathLocator 中有一个内部类 Locations ,Locdations中定义了应用服务配置存储信息。

public interface EnvironmentRepository {
Environment findOne(String application, String profile, String label);
}

  AbstractScmEnvironmentRepository 实现了 AbstractScmAccessor 和 EnvironmentRepository ,主要就是EnvironmentRepository 中 findOne 的实现:

public synchronized Environment findOne(String application, String profile, String label) {
//新建了一个本地仓库作为代理仓库来使用
NativeEnvironmentRepository delegate = new NativeEnvironmentRepository(this.getEnvironment(), new NativeEnvironmentProperties());
//获取本地仓库中指定应用的位置
Locations locations = this.getLocations(application, profile, label);
delegate.setSearchLocations(locations.getLocations());
//根据这个路径搜索应用服务的配置信息
Environment result = delegate.findOne(application, profile, "");
result.setVersion(locations.getVersion());
result.setLabel(label);
return this.cleaner.clean(result, this.getWorkingDirectory().toURI().toString(), this.getUri());
}

  getLocations 是一个模板方法,Config Server中提供了三种实现:

  以 git 方式为例 最后会调到 JGitEnvironmentRepository#getLocations 方法:

public synchronized Locations getLocations(String application, String profile, String label) {
if (label == null) {
label = this.defaultLabel;
}
// 获取最新的版本号
String version = this.refresh(label);
// 根据最新的版本号返回 Locations 定位到资源的搜索路径
return new Locations(application, profile, label, version, this.getSearchLocations(this.getWorkingDirectory(), application, profile, label));
}

  refresh 方法做的作用就是刷新本地仓库的配置状态,这样就能保证每次都能拉取到最新的配置信息。下面来分析这个方法。

public String refresh(String label) {
Git git = null; String var20;
try {
// 创建一个git客户端
git = this.createGitClient();
// 是否需要执行 git pull
if (this.shouldPull(git)) {
FetchResult fetchStatus = this.fetch(git, label);
if (this.deleteUntrackedBranches && fetchStatus != null) {
this.deleteUntrackedLocalBranches(fetchStatus.getTrackingRefUpdates(), git);
}
// 获取后checkout,这样我们就可以获得任何新的分支、tag等。
this.checkout(git, label);
this.tryMerge(git, label);
} else {
// 没有什么要更新,所以只是checkout和merge。
// 合并是因为远程分支以前可能已经更新过
this.checkout(git, label);
this.tryMerge(git, label);
}
// 返回当前的版本
var20 = git.getRepository().findRef("HEAD").getObjectId().getName();
} catch (RefNotFoundException var15) {
throw new NoSuchLabelException("No such label: " + label, var15);
} catch (NoRemoteRepositoryException var16) {
throw new NoSuchRepositoryException("No such repository: " + this.getUri(), var16);
} catch (GitAPIException var17) {
throw new NoSuchRepositoryException("Cannot clone or checkout repository: " + this.getUri(), var17);
} catch (Exception var18) {
throw new IllegalStateException("Cannot load environment", var18);
} finally {
try {
if (git != null) {
git.close();
}
} catch (Exception var14) {
this.logger.warn("Could not close git repository", var14);
} } return var20;
}

  这个里面基本就是通过git客户端的一些操作。先是检查远程仓库的状态,然后判断本地仓库是否要执行刷新操作。如果有状态更新,比如新的提交时,Git客户端就会执行fetch,然后再进行merge,更新到本地仓库。最终是装配一个MultipleJGitEnvironmentRepository的bean,实际每种配置类的实现的最终都是装配一个EnvironmentRepository的子类,可以认为,有一个地方最终会引用到EnvironmentRepository的bean,在ConfigServerAutoConfiguration类中曾经导入了ConfigServerMvcConfiguration 类,而这个类正是向外暴露出端口供客户端访问的配置,在里面组装了两个的 Controller:

@Bean
public EnvironmentController environmentController(EnvironmentRepository envRepository, ConfigServerProperties server) {
EnvironmentController controller = new EnvironmentController(this.encrypted(envRepository, server), this.objectMapper);
controller.setStripDocumentFromYaml(server.isStripDocumentFromYaml());
controller.setAcceptEmpty(server.isAcceptEmpty());
return controller;
} @Bean
@ConditionalOnBean({ResourceRepository.class})
public ResourceController resourceController(ResourceRepository repository, EnvironmentRepository envRepository, ConfigServerProperties server) {
ResourceController controller = new ResourceController(repository, this.encrypted(envRepository, server));
return controller;
}

  而这两个应该是客户端获取服务端配置的入口,以 EnvironmentController 为例查看代码如下。

@RequestMapping({"/{name}/{profiles}/{label:.*}"})
public Environment labelled(@PathVariable String name, @PathVariable String profiles, @PathVariable String label) {
if (name != null && name.contains("(_)")) {
name = name.replace("(_)", "/");
} if (label != null && label.contains("(_)")) {
label = label.replace("(_)", "/");
} Environment environment = this.repository.findOne(name, profiles, label);
if (this.acceptEmpty || environment != null && !environment.getPropertySources().isEmpty()) {
return environment;
} else {
throw new EnvironmentNotFoundException("Profile Not found");
}
}

  注意这里的EnvironmentController#repository属性就是GitRepositoryConfiguration实例化的MultipleJGitEnvironmentRepository,如果是别的实现方式就是别的EnvironmentRepository。可以看出”/{name}/{profiles}/{label:.*}”路径参数正好与我们的请求方式相对应,因此Config Server是通过建立一个RestController来接收读取配置请求的,然后使用EnvironmentRepository来进行配置查询,最后返回一个这个对象的JSON。

public class Environment {
private String name;
private String[] profiles;
private String label;
private List<PropertySource> propertySources;
private String version;
private String state;
.........
}

  通过访问 http://localhost:8888/config/pro/master 会得到信息如下,而这个信息正是 Environment 类

{
"name":"config",
"profiles":["pro"],
"label":"master",
"version":"e6a0ce237a9f9e05608e5c276a9365f0fdd67ed6",
"state":null,
"propertySources":[{
"name":"https://github.com/wuzhenzhao/spring-cloud-config-repo.git/properties/config-pro.properties",
"source":{"foo":"hello-pro"}
}] }

SVN仓库配置:

  Config Server除了支持Git仓库之外, 也能 使用SYN仓库, 只需要做如下配置。 在 pom.xml中引入SYN的依赖配置,让ConfigServer拥有读取SYN内容的能力:

<dependency>
<groupId>org.tmatesoft.svnkit</groupId>
<artifactId>svnkit</artifactId>
<version>1.8.</version>
</dependency>

  在application.properties中使用SVN的配置属性来指定SVN服务器的位置, 以及访问的账户名与密码:

spring.cloud.config.server.svn.uri=svn://localhost:443/wuzz/config-repo
spring.cloud.config.server.svn.username = username
spring.cloud.config.server.svn.password = password

  通过上面的配置修改,ConfigServer就可以使用SVN作为仓库来存储配置文件了, 而对于客户端来说, 这个过程是透明的, 所以不需要做任何变动。

本地仓库:

  在使用了Git或SVN仓库之后, 文件都会在ConfigServer的本地文件系统中存储一 份,这点上面也体现了。这 些文 件默认会被存 储于以 config-repo 为前缀的临 时 目录中, 比如名为/tmp/config-repo-<随机数>的目录。 由于其随机性以及临时目录的特性, 可能会有 一些不可预知的后果, 为了避免将来可能会出现的问题, 最好的办法就是指定一 个固定的位置来存储这些重要信息。我们只需要通过spring.cloud.config.server.git.basedir或 spring.cloud.config.server.svn.basedir来配置一 个我们准备好的目录即可。

属性覆盖:

  Config Server 还有 一 个“ 属性覆盖 ”的特性, 它可以让开发人员为所有的应用提供配置属性,只需要通过 spring.cloud.config.server.overrides 属性来设置键值对的参数,这些参数会以 Map 的方式加载到客户端的配置中。 比如:

spring.cloud.config.server.overrides.name = wuzz
spring.cloud.config.server.overrides.from = hangzhou

  通过该属性配置的参数,不会被 Spring Cloud 的客户端修改,并且 Spring Cloud 客户端从 Config Server 中获取配置信息时,都会取得这些配置信息。 利用该特性可以方便地为Spring Cloud 应用配置 一 些共同属性或是默认属性。 当然,这些属性并非强制的,我们可以通过改变客户端中更高优先级的配置方式(比如,配置环境变量或是系统属性),来选择是否使用 Config Server 提供的默认值。

安全保护:

  由于配置中心存储的内容比较敏感,做 一 定的安全处理是必需的。 为配置中心实现安全保护的方式有很多,比如物理网络限制、 0Auth2 授权等。 不过,由于我们的微服务应用和配置中心都构建于 Spring Boot 基础上,所以与 Spring Security 结合使用会更加方便。我们只需要在配置中心的 pom.xml 中加入 spring-boot-starter-security 依赖,不需要做任何其他改动就能实现对配置中心访问的安全保护。

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

  大多数情况下,我们并不会使用随机生成密码的机制。 我们可以在配置文件中指定用户和密码, 比如:

security.user.name=user
security.user.password=37cc5635-559b-4e6f-b633-7e932b813f73

  由于我们已经为 config-server 设置了安全保护,如果这时候连接到配置中心的客户端中没有设置对应的安全信息,在获取配置信息时会返回401错误。 所以,需要通过配置的方式在客户端中加入安全信息来通过校验, 比如:

spring.cloud.config.username=user
spring.cloud.config.password=37cc5635-559b-4e6f-b633-7e932b813f73

  此外,spring cloud 还提供了加解密。这里就不说明了。因为配置比较繁琐,而且实际环境中应用的比较少。

高可用配置:

  当要将配置中心部署到生产环境中时, 与服务注册中心 一 样, 我们也希望它是 一 个高可用的应用。 Spring Cloud Config 实现服务端的高可用非常简单, 主要有以下两种方式。

  传统模式: 不需要为这些服务端做任何额外的配置, 只需要遵守 一 个配置规则, 将所有的 Config Server 都指向同 一 个 Git 仓库, 这样所有的配置内容就通过统 一 的共享文件系统来维护。而客户端在指定 Config Server 位置时,只需要配置 Config Server上层的负载均衡设备地址即可, 就如下图所示的结构。

  服务模式:除了上面这种传统的实现模式之外, 我们也可以将 Config Server 作为 一个普通的微服务应用,纳入 Eureka 的服务治理体系中。 这样我们的微服务应用就可以通过配置中心的服务名来获取配置信息, 这种方式比起传统的实现模式来说更加有利于维护, 因为对于服务端的负载均衡配置和客户端的配置中心指定都通过服务治理机制一 并解决了, 既实现了高可用, 也实现了自维护。

  主要步骤是在服务端添加 Eureka依赖,启用@EnableDiscoveryClient 注解。在 application.properties 中配置参数eureka.client.serviceUrl.defaultZone以指定服务注册中心的位置。然后进行配置客户端,也是需要添加Eureka依赖,开启@EnableDiscoveryClient注解,然后添加以下配置信息

spring.application.name=wuzz-config-client
server.port=
#指定服务注册中心, 用于服务的注册与发现
eureka.client.serviceUrl.defaultZone = http: / /localhost: /eureka/
#开启通过服务来访间 Config Server 的功能
spring.cloud.config.discovery.enabled=true
#指定 Config Server 注册的服务名
spring.cloud.config.discovery.serviceid=config-server
spring.cloud.config.profile=dev

失败快速响应与重试:

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

  但是, 若只是因为网络波动等其他间歇性原因导致的问题, 直接启动失败似乎代价有些高。 所以, Config 客户端还提供了自动重试的功能, 在开启重试功能前, 先确保已经配置了 spring.cloud.config.failFast=true, 再进行下面的操作。先添加以下依赖

<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 次失败后, 才返回错误信息。 通过这样的重试机制, 可以避免 一 些间歇性问题引起的失败导致客户端应用无法启动的情况。

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

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

动态刷新配置:

  有时候, 我们需要对配置 内容做 一 些实时更新, 那么Spring Cloud Config是否可以实现呢?

  在config-client的pom.xml中新增spring-boot-starter-actuator监控模块。 其中包含了/refresh 端点的 实现,该端点将用于实现客户端应用配置信息的重新获取与刷新。

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

  在修改了Git上面的配置信息之后。通过POST请求发送到http://localhost:8888/refresh .再去获取配置信息就是修改之后的,若无法访问改端口请加上配置:

#开启这个端点,便于等等我们查看配置
management.endpoints.web.exposure.include = refresh

spring-cloud-config-server分布式配置中心的更多相关文章

  1. 【Spring Cloud】Spring Cloud Config 实现分布式配置中心

    Spring Cloud Config 实现分布式配置中心 一.分布式配置中心 分布式系统中,往往拥有大量的服务应用,而每个应用程序都需要有对应的配置文件来协助完成服务环境初始化.运行.因此生产了大量 ...

  2. SpringCloud实战之初级入门(三)— spring cloud config搭建git配置中心

    目录 1.环境介绍 2.配置中心 2.1 创建工程 2.2 修改配置文件 2.3 在github中加入配置文件 2.3 修改启动文件 3. 访问配置中心 1.环境介绍 上一篇文章中,我们介绍了如何利用 ...

  3. Spring Cloud(九):分布式配置中心和消息总线

    我们在Spring Cloud(七):使用SVN存储分布式配置中心文件和实现refresh中讲到,如果需要客户端获取到最新的配置信息需要执行refresh,我们可以利用webhook的机制每次提交代码 ...

  4. Spring Cloud(八):分布式配置中心服务化和高可用

    在前两篇的介绍中,客户端都是直接调用配置中心的server端来获取配置文件信息.这样就存在了一个问题,客户端和服务端的耦合性太高,如果server端要做集群,客户端只能通过原始的方式来路由,serve ...

  5. Spring Boot + Spring Cloud 实现权限管理系统 配置中心(Config、Bus)

    技术背景 如今微服务架构盛行,在分布式系统中,项目日益庞大,子项目日益增多,每个项目都散落着各种配置文件,且随着服务的增加而不断增多.此时,往往某一个基础服务信息变更,都会导致一系列服务的更新和重启, ...

  6. spring cloud深入学习(七)-----配置中心git示例

    随着线上项目变的日益庞大,每个项目都散落着各种配置文件,如果采用分布式的开发模式,需要的配置文件随着服务增加而不断增多.某一个基础服务信息变更,都会引起一系列的更新和重启,运维苦不堪言也容易出错.配置 ...

  7. 为Spring Cloud Config Server配置远程git仓库

    简介 虽然在开发过程,在本地创建git仓库操作起来非常方便,但是在实际项目应用中,多个项目组需要通过一个中心服务器来共享配置,所以Spring Cloud配置中心支持远程git仓库,以使分散的项目组更 ...

  8. Spring Cloud 入门教程 - 搭建配置中心服务

    简介 Spring Cloud 提供了一个部署微服务的平台,包括了微服务中常见的组件:配置中心服务, API网关,断路器,服务注册与发现,分布式追溯,OAuth2,消费者驱动合约等.我们不必先知道每个 ...

  9. .NET Core微服务之基于Steeltoe使用Spring Cloud Config统一管理配置

    Tip: 此篇已加入.NET Core微服务基础系列文章索引 =>  Steeltoe目录快速导航: 1. 基于Steeltoe使用Spring Cloud Eureka 2. 基于Steelt ...

  10. 【Spring Cloud学习之五】配置中心

    环境 eclipse 4.7 jdk 1.8 Spring Boot 1.5.2 Spring Cloud 1.2 一.什么是配置中心在分布式系统中,由于服务数量巨多,为了方便服务配置文件统一管理,实 ...

随机推荐

  1. git异常操作解决办法合集

    1. git add .后发现提交错误,想撤销 git reset head 文件名-----撤销某个文件 git reset head --hard 强制撤销当前的所有操作到上次提交的版本 2. g ...

  2. SPOJ DIVCNT2

    SPOJ DIVCNT2 题目大意: 求\(S2(n)=\sum_{i=1}^{n}\sigma_0{(i^2)}\) . 题解 我们可以先考虑括号里只有一个\(i\)的情况,这样,我们把\(i\)分 ...

  3. [APIO2017]商旅(floyd+分数规划+SPFA)

    题解:首先肯定要跑最短路,而n<=100,所以可以用floyd,然后根据比值,很容易想到二分答案,然后再SPFA跑一遍负环,就能求出解了. #include<bits/stdc++.h&g ...

  4. Java基础 -- 嵌套类(非静态嵌套类、静态嵌套类)

    可以将一个类的定义放在另一个类的内部定义,这样的类就被称为嵌套类,包含嵌套类的类被称为外部类(outer class),也可以叫做封闭类. 嵌套类可以分为两种: 静态嵌套类(Static Nested ...

  5. nacos作为配置中心

    分布式配置中心 在微服务架构中,为什么需要一个统一的配置中心呢?如果用一句话来说那就是方便管理,降低出错的可能.比如:你开发环境是一套配置,测试环境是一套,生产环境又是一套.你如果手动去修改,难免会出 ...

  6. IIS8的SNI功能实现同一服务器多HTTPS站点

    名词解释: SNI指是一项用于改善SSL/TLS的技术,在SSLv3/TLSv1中被启用.它允许客户端在发起SSL握手请求时(具体说来,是客户端发出SSL请求中的ClientHello阶段),就提交请 ...

  7. 企业级playbook的使用

    一.roles文件存放位置 可以在ansible.cfg配置文件中找到,默认路径如下: 也可以在ansible.cfg文件中自定义修改 二.下面以/usr/share/ansible目录来讲解 ans ...

  8. Qt: usb热插拔检测(windows);

    Qt提供了QAbstractNativeEventFilter来实现本地时间得过滤,通过对本地事件的检测,判断usb热插拔:(这里是windows 的例子); 首先,以QWidget, QAbstra ...

  9. axios传参

    get //通过给定的ID来发送请求 axios.get('/user?ID=12345') .then(function(response){ console.log(response); }).c ...

  10. HTML页面只能使用微信浏览器打开

    看到一个项目,刚开始还以为是APP,只能用微信打开.仔细看了下原来是个web项目,只是禁用了其他浏览器打开,只能用微信浏览器打开.加上前端页面用了类似mui的模板,就更像APP了. 百度了下,参考 h ...