携程开源的配置管理中心统一管理各种应用配置的基础服务组件),能够集中化管理应用的不同环境,不同集群的配置,配置修改后能够实时推送到应用端,适合微服务配置管理场景。Apollo包括服务端客户端

在系统架构中,配置中心是整个微服务基础架构体系中的一个组件,如下图,它的功能看上去并不起眼,无非就是配置的管理和存取,但它是整个微服务架构中不可或缺的一环。
集中管理配置,那么就要将应用的配置作为一个单独的服务抽离出来。一个合格的配置中心满足如下需求:① 配置项容易读取和修改;② 添加新配置简单直接;③ 执行对配置的修改的监视以把控风险;④ 可以查看配置修改的历史纪录;⑤ 不同部署环境支持隔离

一、Apollo 特性


【1】统一管理不同环境、不同集群的配置:Apollo 提供了一个统一界面集中式管理不同环境(environment)、不同集群(cluster)、不同命名空间(namespace)的配置。同一份代码部署在不同的集群,可以有不同的配置,比如 zk的地址等。通过命名空间(namespace)可以很方便地支持多个不同应用共享同一份配置,同时还允许应用对共享的配置进行覆盖。
【2】配置修改实时生效用户在 Apollo 修改完配置并发布后,客户端能实时(1s)接收到最新的配置,并通知到应用程序。
【3】版本发布管理:所有的配置发布都有版本概念,从而可以方便地支持配置的回滚。
【4】灰度发布:支持配置的灰度发布,比如点了发布后,只对部分应用实例生效,观察一段时间没问题后再推给所有应用实例。
【5】权限管理、发布审核、操作审计:应用和配置的管理都有完善的权限管理机制,对配置的管理还分为编辑和发布两个环节,从而减少人为的错误。所有的操作都有审计日志,可以方便地追踪问题。
【6】客户端配置信息监控:可以在界面上方便地看到配置在被哪些实例使用。
【7】提供开放平台API:Apollo 自身提供了比较完善的统一配置管理界面,支持多环境、多数据中心配置管理、权限、流程治理等特性。不过 Apollo 处于通用性考虑,不会对配置的修改做过多限制,只要符合基本的格式就能保存,不会针对不同的配置值进行针对性校验,如数据库用户名、密码、Redis服务地址等。对于这类应用配置,Apollo 支持应用方通过开放平台API在 Apollo进行配置的修改和发布,并且具备完善的授权和权限控制。

二、执行流程


在 Apollo 配置中心修改配置(服务端),应用程序通过 Apollo客户端从配置中心拉取配置信息。用户通过 Apollo配置中心修改或发布配置后,会有两种机制来保证应用程序来获取最新配置:一种是 Apollo配置中心向客户端推送最新配置;另一种是 Apollo客户端会定时从 Apollo配置中心拉取最新的配置,通过以上两种机制共同保证应用程序能及时获取到配置。

三、安装 Apollo


【运行时环境】:JDK1.8、MySQL5.6.5:Apollo的表结构对 timestamp使用了多个 default声明,所以需要5.6.5以上版本。
【下载jar包】链接点击 download,下载如下三个.zip包进行解压。
【创建ApolloConfigDB数据库】Apollo 服务端共需要两个数据库:ApolloPortalDB和 ApolloConfigDB,ApolloPortalDB只需要在生产环境部署一个即可,而 ApolloConfigDB需要在每个环境部署一套。创建 ApolloPortalDB  sql脚本链接

source ApolloProtalDB_initialization.sql

验证ApolloConfigDB】导入的所有表如下:
  【创建ApolloPortalDB数据库】sql脚本链接

source ApolloConfigDB__initialization.sql

验证ApolloPortalDB】导入的所有表如下:
 

四、启动 Apollo


【1】确保端口未被占用:Apollo 默认会启动3个服务,分别使用8070,8080,8090端口,请确保这3个端口当前被使用。
【2】启动 apollo-configservice,在 Apollo目录下执行执行如下命令,可以通过 -Dserver.port=8080修改默认端口。

java -Xms256m -Xmx256m -Dspring.datasource.url=jdbc:mysql://localhost:3306/ApolloConfigDB?characterEncoding=utf8 -Dspring.datasource.username=root -Dspring.datasource.password=root -jar apollo-configservice-1.3.0.jar

【3】启动 apollo-adminservice,可通过 -Dserver.port=8090修改默认端口

1 java -Xms256m -Xmx256m -Dspring.datasource.url=jdbc:mysql://localhost:3306/ApolloConfigDB?characterEncoding=utf8 -Dspring.datasource.username=root -Dspring.datasource.password=root -jar apollo-adminservice-1.3.0.jar

【4】启动 apollo-portal,可通过 -Dserver.port=8070修改默认端口

java -Xms256m -Xmx256m -Ddev_meta=http://localhost:8080/ -Dserver.port=8070 -Dspring.datasource.url=jdbc:mysql://localhost:3306/ApolloPortalDB?characterEncoding=utf8 -Dspring.datasource.username=root -Dspring.datasource.password=root -jar apollo-portal-1.3.0.jar

【5】也可以使用提供的 runApollo.bat快速启动三个服务(修改数据库连接地址,数据库以及密码)

1 echo
2 set url="localhost:3306"
3 set username="root"
4 set password="root"
5
6 start "configService" java -Xms256m -Xmx256m -Dapollo_profile=github -Dspring.datasource.url=jdbc:mysql://%url%/ApolloConfigDB?characterEncoding=utf8 -Dspring.datasource.username=%username% -Dspring.datasource.password=%password% -Dlogging.file=.\logs\apollo-configservice.log -jar .\apollo-configservice-1.3.0.jar
7 start "adminService" java -Xms256m -Xmx256m -Dapollo_profile=github -Dspring.datasource.url=jdbc:mysql://%url%/ApolloConfigDB?characterEncoding=utf8 -Dspring.datasource.username=%username% -Dspring.datasource.password=%password% -Dlogging.file=.\logs\apollo-adminservice.log -jar .\apollo-adminservice-1.3.0.jar
8 start "ApolloPortal" java -Xms256m -Xmx256m -Dapollo_profile=github,auth -Ddev_meta=http://localhost:8080/ -Dserver.port=8070 -Dspring.datasource.url=jdbc:mysql://%url%/ApolloPortalDB?characterEncoding=utf8 -Dspring.datasource.username=%username% -Dspring.datasource.password=%password% -Dlogging.file=.\logs\apollo-portal.log -jar .\apollo-portal-1.3.0.jar

【6】待启动成功后,访问管理页面[http://localhost:8070/]用户名 apollo,密码 admin

五、发布配置


【1】点击管理页面的 “创建项目

【2】点击“新增配置

【3】提前我们需要配置的 key-value 键值对

【4】提交之后,配置默认是“未发布”状态,需要点击“发布” 让配置生效。也可以对配置进行修改,修改后也需要发布。

六、客户端配置


【1】在项目的 pom.xml文件中添加 Apollo客户端依赖:

1 <dependency>
2 <groupId>com.ctrip.framework.apollo</groupId>
3 <artifactId>apollo-client</artifactId>
4 <version>1.1.0</version>
5 </dependency>

【2】Apollo客户端连接 Apollo服务端需要配置如下3点:

1 #配置文件中定义的项目名称
2 -Dapp.id=apollo-quickstart
3 #项目的执行环境
4 -Denv=DEV
5 #Apollo服务的运行地址
6 -Ddev_meta=http://localhost:8080

【3】获取 Apollo配置界面配置的属性,例如我们配置的 sms.enable,获取代码如下:

七、Apollo 工作原理


上图简要描述了 Apollo的总体架构,我们从下往上进行分析:
【1】Config Service 提供配置的读取推送等功能,服务对象是 Apollo客户端
【2】Admin Service 提供配置的修改发布等功能,服务对象是 Apollo Portal(管理界面);
【3】Eureka/Consul等提供服务注册和发现,为了简单起见,目前 Eureka在部署时和 Config Service是在一个 JVM进程中的;
【4】Config Service 和 Admin Service都是多实例、无状态部署,所以需要将自己注册到 Eureka中并保持心跳;
【5】在 Eureka 之上有一层 Meta Sever 用于封装 Eureka 的服务发现接口;
【6】Client 通过域名访问 MetaServer 获取 Config Service 服务列表(IP+Port),而后直接通过 IP+Port访问服务,同时在 Client 侧会做 load balance、错误重试;
【7】Portal 通过域名访问 MetaServer 获取 Admin Server服务列表(IP+Port),而后直接通过 IP+Port访问服务,同时在Portal侧会做 load balance、错误重试;
【8】为了简化部署,我们实际上会把 Config Service、Eureka 和 Meta Server三个逻辑角色部署在同一个 JVM进程中;

八、核心概念


【1】application:这个很好理解,就是实际使用配置的应用,Apollo客户端在运行时需要知道当前应用是谁,从而获取对应的配置;关键字:appid
【2】environment(环境)配置对应的环境,Apollo客户端在运行时需要知道当前应用处于哪个环境,从而可以去获取应用的配置;关键字:env
【3】cluster(集群)一个应用下不同实例的分组,比如典型的可以按照数据中心分,把上海机房的应用实例分为一个集群,把北京机房的应用实例分为另一个实例;关键字:cluster
【4】namespace(命名空间):一个应用下不同配置的分组,可以简单地把 namespace类比为文件,不同类型的配置存放在不同的文件中,如数据库配置文件,PRC配置文件,应用自身的配置文件等。可以定义一个公共的namespace,其它namespace继承该公共配置即可。关键字:namespace

九、项目管理


【添加部门】:apollo 默认部门有两个。增加自己部门步骤:点击“管理员工具”-“系统参数

在  key中输入 organizations 查看已配置的部门,并根据该格式添加自己的部门;

【用户管理】 :apollo 默认提供一个超级管理员:apollo,我们也可以通过“管理员工具”-“用户管理”添加用户
例如我们创建一个 zzx用户
那么我们再创建项目的时候,就可以将项目与用户进行关联,如下:当使用该用户登录 Apollo时,只能看到分配给自己的项目。
也可以给新用户授权已有项目的权限,点击到需授权的项目:点击“授权

【删除项目】:如果要删除整个项目,点击右上角的 "管理员工具"– "删除应用、集群…"

十、配置管理-Namespace


添加 Namespace:Namespace作为配置的分类,可当成一个配置文件。以添加 RocketMQ配置为例,添加 “spring-rocketmq” Namespace配置 RocketMQ相关信息。

【1】添加项目私有Namespace:spring-rocketmq,进入项目首页,点击左下脚的 “添加Namespace”。
共包括两项:关联公共Namespace和创建 Namespace,这里选择“创建Namespace”,就会跳出如下界面,最后记得发布;
【2】添加配置项:当添加配置时,也可以直接将项目配置文件中的 key-value 键值对直接 cope到 Apollo中,最后记得发布;

【3】从项目中获取私有的 namespace,需要制定获取的 namespace名称;

 1 public class GetConfigTest {
2 public static void main(String[] args) throws InterruptedException {
3 //获取 Apollop 配置类
4 //Config appConfig = ConfigService.getAppConfig();
5 Config appConfig = ConfigService.getConfig("spring-rocketmq");
6 //模拟 web 服务
7 while(true){
8 Thread.sleep(100L);
9 //获取 Apollo 服务端我们添加的 sms.enable配置,并给一个默认值
10 String property = appConfig.getProperty("test", null);
11 System.out.println("sms.enable = " + property);
12 }
13 }
14 }

【4】创建公共的 namespace,我们创建一个公共的项目来配置公共的 namespace;

【5】如果想让 apollo-quickstart继承公共的 namespace,选择“关联公共Namespace
【6】我们查看 apollo-quickstart拥有的配置时,会发现 common_namespace 配置,我们可以覆盖公共配置中的属性,如果要修改公共配置就需要进入公共配置类中继续修改。

十一、配置管理-集群管理


集群管理:再有些情况下,应用有需求对不同的集群做不同的配置,比如部署在 A机房的应用连接的 RocketMQ服务器地址和部署在 B机房的应用连接的 RocketMQ服务器地址不一样。另外在项目开发过程中,也可以为不同的开发人员创建不同的集群来满足开发人员的自定义配置。

【1】点击 “添加集群
【2】输入新集群名称,选择环境并提交:添加上海金桥数据中心为例
【3】项目中就会多新增的集群环境,并且默认会有该项目私有的namespace,公共的配置也可以通过关联进行获取。
【4】通过同步进行集群之间的数据同步;在有数据的集群中点击同步,然后选择目标集群。如下:需点击“同步”按钮。回到目标集群中点击“发布”即可。

十二、配置发布原理


在配置中心中,一个重要的功能就是配置发布后实时推送到客户端。下面简要看一下这块时怎么设计实现的。
【1】用户在 Portal操作配置发布;
【2】Portal 调用 Admin Service的接口操作发布;
【3】Admin Service发布配置后,发送 ReleaseMessage给各个 Config Service
【4】Config Service收到 ReleaseMessage后,通知对应的客户端;

发送 ReleaseMessage:Admin Service在配置发布后,需要通知所有的 Config Service有配置发布,从而 Config Service可以通知对应的客户端来拉取最新的配置。从概念上来看,这是一个典型的消息使用场景,Admin Service作为 producer(生产者)发出消息,各个 Config Service作为consumer(消费者)消费消息。通过一个消息队列组件(Message Queue)就能很好的实现 Admin ServiceConfig Service的解耦。

在实现上,考虑到 Apollo的实际使用场景,以及为了尽可能减少外部依赖,我们没有采用外部的消息中间件,而是通过数据库实现了一个简单的消息队列。具体实现方式如下:
【1】Admin Service在配置发布后会往 ReleaseMessage表插入一条消息记录,消息内容就是配置发布的AppId+Cluster+Namespace

SELECT * FROM ApolloConfigDB.ReleaseMessage

消息发送类:DatabaseMessageSende

ReleaseMessage newMessage = releaseMessageRepository.save(new ReleaseMessage(message));

【2】Config Service 有一个线程会每秒扫描一次 ReleaseMessage表,看看是否有新的消息记录。消息扫描类:ReleaseMessageScanner

1 List<ReleaseMessage> releaseMessages =
2 releaseMessageRepository.findFirst500ByIdGreaterThanOrderByIdAsc(maxIdScanned);
3 //通知
4 fireMessageScanned(releaseMessages);

【3】Config Service 如果发现有新的消息记录,那么就会通知到所有的消息监听器。

 1 private void fireMessageScanned(List<ReleaseMessage> messages) {
2 for (ReleaseMessage message : messages) {
3 for (ReleaseMessageListener listener : listeners) {
4 try {
5 listener.handleMessage(message, Topics.APOLLO_RELEASE_TOPIC);
6 } catch (Throwable ex) {
7 Tracer.logError(ex);
8 logger.error("Failed to invoke message listener {}", listener.getClass(), ex);
9 }
10 }
11 }
12 }

然后调用消息监听类的 handleMessage方法:NotificationControllerV2

 1   @Override
2 public void handleMessage(ReleaseMessage message, String channel) {
3 logger.info("message received - channel: {}, message: {}", channel, message);
4
5 String content = message.getMessage();
6 Tracer.logEvent("Apollo.LongPoll.Messages", content);
7 if (!Topics.APOLLO_RELEASE_TOPIC.equals(channel) || Strings.isNullOrEmpty(content)) {
8 return;
9 }
10
11 String changedNamespace = retrieveNamespaceFromReleaseMessage.apply(content);
12
13 if (Strings.isNullOrEmpty(changedNamespace)) {
14 logger.error("message format invalid - {}", content);
15 return;
16 }
17
18 if (!deferredResults.containsKey(content)) {
19 return;
20 }
21
22 //create a new list to avoid ConcurrentModificationException
23 List<DeferredResultWrapper> results = Lists.newArrayList(deferredResults.get(content));
24
25 ApolloConfigNotification configNotification = new ApolloConfigNotification(changedNamespace, message.getId());
26 configNotification.addMessage(content, message.getId());
27 }

NotificationControllerV2 得到配置发布的 AppId+Cluster+Namespace后,会通知对应的客户端:

十三、Config Service通知客户端


上面简要描述了 NotificationControllerV2是如何得知有配置发布的,那 NotificationControllerV2在得知有配置发布后是如何通知到客户端的呢?实现方式如下:
【1】客户端会发起一个 Http请求到 Config Service的 notifications/v2接口NotificationControllerV2

 1 @RestController
2 @RequestMapping("/notifications/v2")
3 public class NotificationControllerV2 implements ReleaseMessageListener {
4 private static final Logger logger = LoggerFactory.getLogger(NotificationControllerV2.class);
5 private final Multimap<String, DeferredResultWrapper> deferredResults =
6 Multimaps.synchronizedSetMultimap(TreeMultimap.create(String.CASE_INSENSITIVE_ORDER, Ordering.natural()));
7 private static final Splitter STRING_SPLITTER =
8 Splitter.on(ConfigConsts.CLUSTER_NAMESPACE_SEPARATOR).omitEmptyStrings();
9 private static final Type notificationsTypeReference =
10 new TypeToken<List<ApolloConfigNotification>>() {
11 }.getType();

【2】客户端发送请求类:RemoteConfigLongPollService 链接

 1 private void doLongPollingRefresh(String appId, String cluster, String dataCenter) {
2 final Random random = new Random();
3 ServiceDTO lastServiceDto = null;
4 // 循环执行,直到停止或线程中断
5 while (!m_longPollingStopped.get() && !Thread.currentThread().isInterrupted()) {
6 if (!m_longPollRateLimiter.tryAcquire(5, TimeUnit.SECONDS)) {
7 //wait at most 5 seconds
8 try {
9 TimeUnit.SECONDS.sleep(5);
10 } catch (InterruptedException e) {
11 }
12 }
13 Transaction transaction = Tracer.newTransaction("Apollo.ConfigService", "pollNotification");
14 String url = null;
15 try {
16 if (lastServiceDto == null) {
17 //获取所有的ConfigServer地址
18 List<ServiceDTO> configServices = getConfigServices();
19 lastServiceDto = configServices.get(random.nextInt(configServices.size()));
20 }
21 // 组装url(notifications/v2)
22 url =
23 assembleLongPollRefreshUrl(lastServiceDto.getHomepageUrl(), appId, cluster, dataCenter,
24 m_notifications);
25
26 logger.debug("Long polling from {}", url);
27 HttpRequest request = new HttpRequest(url);
28 request.setReadTimeout(LONG_POLLING_READ_TIMEOUT);
29
30 transaction.addData("Url", url);
31
32 final HttpResponse<List<ApolloConfigNotification>> response =
33 m_httpUtil.doGet(request, m_responseType);
34
35 logger.debug("Long polling response: {}, url: {}", response.getStatusCode(), url);
36 if (response.getStatusCode() == 200 && response.getBody() != null) {
37 updateNotifications(response.getBody());
38 updateRemoteNotifications(response.getBody());
39 transaction.addData("Result", response.getBody().toString());
40 //通知对应的RemoteConfigRepository
41 notify(lastServiceDto, response.getBody());
42 }
43
44 //try to load balance
45 if (response.getStatusCode() == 304 && random.nextBoolean()) {
46 lastServiceDto = null;
47 }
48
49 m_longPollFailSchedulePolicyInSecond.success();
50 transaction.addData("StatusCode", response.getStatusCode());
51 transaction.setStatus(Transaction.SUCCESS);
52 } catch (Throwable ex) {
53 lastServiceDto = null;
54 Tracer.logEvent("ApolloConfigException", ExceptionUtil.getDetailMessage(ex));
55 transaction.setStatus(ex);
56 long sleepTimeInSecond = m_longPollFailSchedulePolicyInSecond.fail();
57 logger.warn(
58 "Long polling failed, will retry in {} seconds. appId: {}, cluster: {}, namespaces: {}, long polling url: {}, reason: {}",
59 sleepTimeInSecond, appId, cluster, assembleNamespaces(), url, ExceptionUtil.getDetailMessage(ex));
60 try {
61 TimeUnit.SECONDS.sleep(sleepTimeInSecond);
62 } catch (InterruptedException ie) {
63 //ignore
64 }
65 } finally {
66 transaction.complete();
67 }
68 }
69 }

NotificationControllerV2 不会立即返回结果,而是把请求挂起。考虑到会有数万客户端向服务端发起长连,因此在服务端使用了async servlet(Spring DeferredResult)来服务Http Long Polling请求。如果在60秒内没有该客户端关心的配置发布,那么会返回 Http状态码 304给客户端。

如果有该客户端关心的配置发布,NotificationControllerV2 会调用 DeferredResult的 setResult方法,传入有配置变化的 namespace信息,同时该请求会立即返回。客户端从返回的结果中获取到配置变化的 namespace后,会立即请求 Config Service获取该 namespace的最新配置。

十四、客户端读取设计


除了之前介绍的客户端和服务端保持一个长连接,从而能第一时间获得配置更新的推送外,客户端还会定时从 Apollo配置中心服务端拉取应用的最新配置。
【1】这是一个备用机制,为了防止推送机制失效导致配置不更新;
【2】客户端定时拉取会上报本地版本,所以一般情况下,对于定时拉取的操作,服务端都会返回304 - Not Modified;
【3】定时频率默认为每 5分钟拉取一次,客户端也可以通过在运行时指定 System Property: apollo.refreshInterval来覆盖,单位为分钟;

十五、Apollo应用于分布式系统


【1】客户端需要继承 Apollo 客户端的依赖

1 <dependency>
2 <groupId>com.ctrip.framework.apollo</groupId>
3 <artifactId>apollo-client</artifactId>
4 <version>1.1.0</version>
5 </dependency>

【2】在Spring Boot application.propertiesapplication.yml中配置

 1 #与配置Apollo配置页面中的 APPID保持一致
2 app.id=account-service
3 #开启apollo客户端
4 apollo.bootstrap.enabled = true
5 #配置 namespace,与配置Apollo配置页面中的namespace保持一致
6 apollo.bootstrap.namespaces = application,micro_service.spring-boot-http,spring-rocketmq,micro_service.spring-boot-druid
7 #配置 meta-server 客户端用来获取配置的地址,是 环境.meta 一般项目都会给不同环境创建不通的配置文件
8 dev.meta=http://localhost:8080
9 #集群和环境 跟正常项目一样配置
10 profile=dev

本地缓存路径:Apollo客户端会把从服务端获取到的配置在本地文件系统缓存一份,用于在遇到服务不可用,或网络不通的时候,依然能从本地恢复配置,不影响应用正常运行。本地配置文件会以下面的文件名格式放置于配置的本地缓存路径下:{appId}+{cluster}+{namespace}.properties 可以通过如下方式指定缓存路径,通过Java System Property 的 apollo.cacheDir:-Dapollo.cacheDir=/opt/data/apollo-config
【3】启用配置:在应用的启动类添加 @EnableApolloConfig注解即可:

1 @SpringBootApplication(scanBasePackages = “com.pbteach.account”)
2 @EnableApolloConfig
3 public class AccountApplication {

【4】读取配置信息:通过 @Value注解读取;

1 @Value("${sms.enable}")
2 private Boolean smsEnable;

十六、环境部署


生产环境部署:当一个项目要上线部署到生产环境时,项目的配置比如数据库连接RocketMQ地址等都会发生变化,这时候就需要通过 Apollo为生产环境添加自己的配置。
企业部署方案:在企业中常用的部署方案为:Apollo-adminserviceApollo-configservice两个服务分别在线上环境(pro),仿真环境(uat)和开发环境(dev)各部署一套,Apollo-portal 做为管理端只部署一套,统一管理上述三套环境。

修改端口时,除了修改脚本中的端口,还需要修改数据库中的Eureka信息:

UPDATE ServerConfig SET Value = “http://localhost:8081/eureka/” WHERE key = “eureka.service.url”;

【添加 pro环境】:【1】服务配置项统一存储在 ApolloPortalDB.ServerConfig表中,可以通过管理员工具 - 系统参数
在该页面配置输入:apollo.portal.envs 点击“查询”添加 pro (可支持的环境列表)
【2】启动 ApolloPortal:Apollo Portal需要在不同环境访问不同 meta service(apollo-configservice)地址,所以我们需要在配置中提供这些信息。记得关闭之前的 Apollo Portal。

-Ddev_meta=http://localhost:8080/ -Dpro_meta=http://localhost:8081/

【3】登录 Apollo Portal界面,进入项目,点击“补缺环境” 我们添加的 pro环境就出来了,也可以"补缺 namespace"如下:

【4】在配置文件中增加 pro.meta=http://localhost:8081 修改 服务的启动参数为:-Denv=pro

十七、灰度发布


在页面直接点击

Apollo 分布式配置中心理论到实践的更多相关文章

  1. Apollo分布式配置中心部署以及使用

    一.简介Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境.不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限.流程治理等特性,适用于微服务配置管理场 ...

  2. Apollo 分布式配置中心

    1.  介绍 Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境.不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限.流程治理等特性,适用于微服务配置 ...

  3. Apollo 分布式配置中心(补充)

    1.   Namespace 1.1.  什么是Namespace Namespace是配置项的集合,类似于一个配置文件的概念. Apollo在创建项目的时候,都会默认创建一个“application ...

  4. 携程apollo分布式配置中心

    原理 : apollo的部署 jdk 要求8以上 mysql 5.7以上 执行build.sh 这样就把configService,adminService 打包到对应的target下面 把这个放到l ...

  5. 分布式配置中心 携程(apollo)

    1.传统配置文件与分布式配置文件区别 传统配置文件:如果修改了配置文件,需要重新打包发布,重新发布服务,而且每个环境的变更配置文件,比较繁琐. 分布式配置文件:将配置文件注册到配置中心上去,可以使用分 ...

  6. 分布式配置中心Apollo

    1,什么是分布式配置中心 项目中配置文件比较繁杂,而且不同环境的不同配置修改相对频繁,每次发布都需要对应修改配置,如果配置出现错误,需要重新打包发布,时间成本较高,因此需要做统一的分布式注册中心,能做 ...

  7. 实践分布式配置中心Apollo

    简介 Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境.不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限.流程治理等特性,适用于微服务配置管理场景 ...

  8. SpringCloud系列之分布式配置中心极速入门与实践

    SpringCloud系列之分布式配置中心极速入门与实践 @ 目录 1.分布式配置中心简介 2.什么是SpringCloud Config? 3.例子实验环境准备 4.Config Server代码实 ...

  9. 分布式配置中心Apollo——QuickStart

    分布式配置中心 剥离配置文件,实现动态修改,自动更新. [假设没有分布式配置中心,修改配置文件后都需要重启服务,对于数量庞多的微服务开发来说,就会非常繁琐] 分布式配置中心有哪些 disconf(依赖 ...

  10. spring cloud 集成分布式配置中心 apollo(单机部署apollo)

    一.什么是apollo? Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境.不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限.流程治理等特性,适用 ...

随机推荐

  1. 挖坑——未完成题目列表QwQ

    OI一些的小计划: 日拱一卒,功不唐捐! Unfinished luogu P2814 家谱 Luogu P2076 聚会 luogu P2212 Watering the Fields  草坪上有N ...

  2. linux开机自启动tomcat或者其他应用

     开机自启动Tomcat: 1.创建一个脚本,touch tomcat_start.sh 2.编辑脚本,vim tomcat_start.sh #!/bin/sh #chkconfig: 2345 8 ...

  3. SQLite 帮助类

    public static class SqliteHelper { /// <summary> /// 获得连接对象 /// </summary> /// <retur ...

  4. 20200924--图像相似度(奥赛一本通P92 5多维数组)

    给出两幅相同大小的黑白图像(用0-1矩阵)表示,求它们的相似度.说明:若两幅图像在相同位置上的像素点颜色相同,则称它们在该位置具有相同的像素点.两幅图像的相似度定义为相同像素点数占总像素点数的百分比. ...

  5. springboot 整合内存缓存Caffeine

    springboot 整合内存缓存Caffeine 1.引jar包 <dependency> <groupId>org.springframework.boot</gro ...

  6. "蔚来杯"2022牛客暑期多校训练营1 C.Grab the Seat!

    C.Grab the Seat! 题目链接 https://ac.nowcoder.com/acm/contest/33186/C 题目大意 1.二维平面中,(0,1) - (0,m)为屏幕 2.有n ...

  7. Python - XSS-Attribute

    参考资料:https://owasp-skf.gitbook.io/asvs-write-ups/cross-site-scripting-attribute-xss-attribute/kbid-3 ...

  8. 复杂数据类型(signal)的解读-C语言基础

    这一篇文章要探讨的是C语言中复杂数据类型的解读.涉及到signal()函数数据类型的解读(并不解释signal()的作用)以及对于数据类型的理解,属于C语言基础篇. 在开始解读signal()这种复杂 ...

  9. Laravel自定义JSON错误消息 The given data was invalid.

    Laravel自定义错误消息 在Laravel验证请求时出现错误,默认会返回如下的错误: 可以看到JSO结构中的message为The given data was invalid.而并非是我们具体自 ...

  10. tuxedo 12c 安装

    tuxedo12c 安装命令 静默安装 控制台安装 tuxedo版本介绍 Tuxedo Release Name Tuxedo Release Number Note which contains L ...