Apollo配置中心轉

尊重原創,本文轉自:https://www.cnblogs.com/FlyAway2013/p/8811385.htmlhtml

 

 

前咱們項目,全部的配置基本都是經過本地properties 文件進行配置的,好比ip地址、端口、消息中間件和數據庫鏈接的各類參數,當咱們須要切換環境或調整參數的時候,咱們必須手動的修改這些配置。若是隻有一個配置文件還好,可是,若是有不少這樣的配置文件,並且又分佈式部署在多臺機器,那麼這樣, 無疑是很是低效並且容易出錯的。java

 

咱們當前的項目,大都是分佈式部署的項目,機器多,配置項更是繁多,所以,咱們頗有必要引入一個配置中心。mysql

 

各開源配置中心對比矩陣以下:git

 

 

 

在對比了各家的開源產品以後,咱們選用了攜程的apollo : https://github.com/ctripcorp/apollogithub

 

Apollo介紹

Apollo(阿波羅)是攜程框架部門研發的分佈式配置中心,可以集中化管理應用不一樣環境、不一樣集羣的配置,配置修改後可以實時推送到應用端,而且具有規範的權限、流程治理等特性,適用於微服務配置管理場景。redis

 

服務端基於Spring Boot和Spring Cloud開發,打包後能夠直接運行,不須要額外安裝Tomcat等應用容器。spring

 

Java客戶端不依賴任何框架,可以運行於全部Java運行時環境,同時對Spring/Spring Boot環境也有較好的支持。sql

 

.Net客戶端不依賴任何框架,可以運行於全部.Net運行時環境。數據庫

 

Apollo特性

  • 統一管理不一樣環境、不一樣集羣的配置
    • Apollo提供了一個統一界面集中式管理不一樣環境(environment)、不一樣集羣(cluster)、不一樣命名空間(namespace)的配置。
    • 同一份代碼部署在不一樣的集羣,能夠有不一樣的配置,好比zk的地址等
    • 經過命名空間(namespace)能夠很方便的支持多個不一樣應用共享同一份配置,同時還容許應用對共享的配置進行覆蓋
  • 配置修改實時生效(熱發佈)
    • 用戶在Apollo修改完配置併發布後,客戶端能實時(1秒)接收到最新的配置,並通知到應用程序。
  • 版本發佈管理
    • 全部的配置發佈都有版本概念,從而能夠方便的支持配置的回滾。
  • 灰度發佈
    • 支持配置的灰度發佈,好比點了發佈後,只對部分應用實例生效,等觀察一段時間沒問題後再推給全部應用實例。
  • 權限管理、發佈審覈、操做審計
    • 應用和配置的管理都有完善的權限管理機制,對配置的管理還分爲了編輯和發佈兩個環節,從而減小人爲的錯誤。
    • 全部的操做都有審計日誌,能夠方便的追蹤問題。
  • 客戶端配置信息監控
    • 能夠方便的看到配置在被哪些實例使用
  • 提供Java和.Net原生客戶端
    • 提供了Java和.Net的原生客戶端,方便應用集成
    • 支持Spring Placeholder, Annotation和Spring Boot的ConfigurationProperties,方便應用使用(須要Spring 3.1.1+)
    • 同時提供了Http接口,非Java和.Net應用也能夠方便的使用
  • 提供開放平臺API
    • Apollo自身提供了比較完善的統一配置管理界面,支持多環境、多數據中心配置管理、權限、流程治理等特性。
    • 不過Apollo出於通用性考慮,對配置的修改不會作過多限制,只要符合基本的格式就可以保存。
    • 在咱們的調研中發現,對於有些使用方,它們的配置可能會有比較複雜的格式,如xml, json,須要對格式作校驗。
    • 還有一些使用方如DAL,不只有特定的格式,並且對輸入的值也須要進行校驗後方可保存,如檢查數據庫、用戶名和密碼是否匹配。
    • 對於這類應用,Apollo支持應用方經過開放接口在Apollo進行配置的修改和發佈,而且具有完善的受權和權限控制
  • 部署簡單
    • 配置中心做爲基礎服務,可用性要求很是高,這就要求Apollo對外部依賴儘量地少
    • 目前惟一的外部依賴是MySQL,因此部署很是簡單,只要安裝好Java和MySQL就可讓Apollo跑起來
    • Apollo還提供了打包腳本,一鍵就能夠生成全部須要的安裝包,而且支持自定義運行時參數

 

工做原理

整體架構:

 

 

 

  1. 用戶在Portal操做配置發佈
  2. Portal調用Admin Service的接口操做發佈
  3. Admin Service發佈配置後,發送ReleaseMessage給各個Config Service
  4. Config Service收到ReleaseMessage後,通知對應的客戶端

 

客戶端:

 

 

上圖簡要描述了Apollo客戶端的實現原理:json

  1. 客戶端和服務端保持了一個長鏈接,從而能第一時間得到配置更新的推送。(經過Http Long Polling實現)
  2. 客戶端還會定時從Apollo配置中心服務端拉取應用的最新配置。
  • 這是一個fallback機制,爲了防止推送機制失效致使配置不更新
  • 客戶端定時拉取會上報本地版本,因此通常狀況下,對於定時拉取的操做,服務端都會返回304 - Not Modified
  • 定時頻率默認爲每5分鐘拉取一次,客戶端也能夠經過在運行時指定System Property: apollo.refreshInterval來覆蓋,單位爲分鐘。
  1. 客戶端從Apollo配置中心服務端獲取到應用的最新配置後,會保存在內存中
  2. 客戶端會把從服務端獲取到的配置在本地文件系統緩存一份
  • 在遇到服務不可用,或網絡不通的時候,依然能從本地恢復配置
  1. 應用程序能夠從Apollo客戶端獲取最新的配置、訂閱配置更新通知

 

 

服務端部署

單機部署指南

將apollo-quick-start.zip 上傳到某一個服務器, 做爲配置中心, 解壓, 修改sh腳本參數,

修改IP:

修改端口:

 

操做步驟:

1 修改apolloconfigdb.sql 的

# Config

# ------------------------------------------------------------

INSERT INTO `ServerConfig` (`Key`, `Cluster`, `Value`, `Comment`)

VALUES

    ('eureka.service.url', 'default', 'http://192.168.1.229:5998/eureka/', 'Eureka服務Url,多個service以英文逗號分隔'),

    ('namespace.lock.switch', 'default', 'false', '一次發佈只能有一我的修改開關'),

    ('item.value.length.limit', 'default', '20000', 'item value最大長度限制'),

    ('config-service.cache.enabled', 'default', 'false', 'ConfigService是否開啓緩存,開啓後能提升性能,可是會增大內存消耗!'),

    ('item.key.length.limit', 'default', '128', 'item key 最大長度限制');

 

ip: 192.168.1.229

 

2 必定要先啓動 cfg, 而後是 admin, 而後是 portal

admin必定要在 cfg啓動成功 以後,

portal 必定要在 admin啓動成功 以後,

 

D:\code\git\apollo\apollo-configservice\target>java -jar apollo-configservice-0.

10.0-SNAPSHOT.jar start  -Dspring_datasource_username=ww

 

 

 

中止

./cfg/scripts/shutdown.sh ;   ./adm/scripts/shutdown.sh ;    ./ptl/scripts/shutdown.sh ;   

 

 

 

 

啓動apollo:

 

./cfg/scripts/shutdown.sh ;  ./cfg/scripts/startup.sh  ;  ./adm/scripts/shutdown.sh ;  ./adm/scripts/startup.sh  ; ./ptl/scripts/shutdown.sh ;  ./ptl/scripts/startup.sh  ;

 

 

java  -Dapollo_profile=github  -Dspring.datasource.url=jdbc:mysql://localhost:3306/ApolloConfigDB?characterEncoding=utf8 -Dspring.datasource.username=root -Dspring.datasource.password=admin   -jar cfg/apollo-configservice.jar

 

java  -Dapollo_profile=github  -Dspring.datasource.url=jdbc:mysql://localhost:3306/ApolloConfigDB?characterEncoding=utf8 -Dspring.datasource.username=root -Dspring.datasource.password=admin   -jar adm/apollo-adminservice.jar

 

java  -Dapollo_profile=github,auth -Ddev_meta=http://localhost:5998/ -Dserver.port=5999 -Dspring.datasource.url=jdbc:mysql://localhost:3306/ApolloPortalDB?characterEncoding=utf8 -Dspring.datasource.username=root -Dspring.datasource.password=admin  -jar ptl/apollo-portal.jar

 

 

 

[root@VM228 apollo]# ./demo.sh start

==== starting service ====

Service logging file is ./service/apollo-service.log

Started [11050]

Waiting for config service startup....

Config service started. You may visit http://192.168.1.228:8080 for service status now!

Waiting for admin service startup...

Admin service started

==== starting portal ====

Portal logging file is ./portal/apollo-portal.log

Started [11196]

Waiting for portal startup....

Portal started. You can visit http://192.168.1.228:8070 now!

 

測試:

系統出錯,請重試或聯繫系統負責人 ---  configdb 的serverconfig表 的: eureka.service.url 能夠要重啓。。

配置錯誤 。。。= http://192.168.4.112:5998/eureka/

 

使用portal: 訪問 http://192.168.1.228:8070/, 管理員帳號:apollo/admin

 

 

 

 

中止:

[root@VM228 apollo]# ./demo.sh stop

==== stopping portal ====

Stopped [11196]

==== stopping service ====

Stopped [11050]

 

分佈式部署指南

咱們暫時不啓用它

參見:

https://github.com/ctripcorp/apollo/wiki/%E5%88%86%E5%B8%83%E5%BC%8F%E9%83%A8%E7%BD%B2%E6%8C%87%E5%8D%97

 

客戶端部署和使用

(主要針對dubbo應用)

參考:https://github.com/ctripcorp/apollo/wiki/Java客戶端使用指南

 

客戶端部署跟咱們以前部署方式同樣,不過部署以前,須要咱們對咱們的dubbo應用作一些調整:

 

引入apollo-client依賴

apollo-client-項目分支-版本.jar(統一由架構部門或運維部門來發布)

以下:

<dependency>
   <groupId>com.ctrip.framework.apollo</groupId>
   <artifactId>apollo-client</artifactId>
   <version> hy-linke-0.10.0</version>
</dependency>

統一配置和遷移

在應用中配置好META-INF/app.properties, META-INF/app.properties 是可選的,並且

把原先配置(必須是properties格式)複製一下,而後經過Apollo提供的文本編輯模式所有粘帖到應用的application namespace,發佈配置

若是原來是其它格式,如yml,請先轉成properties格式

 

最好把原先的配置文件如bootstrap.properties, application.properties從項目中刪除,固然,咱們也能夠同時保留咱們原來的application.properties配置,可是這樣可能會有衝突,若是在本地和配置中心有有同名的配置,那麼使用配置中心, 不然就使用其中存在的一方, 若是兩個地方都沒有,那麼就使用默認值, 若是默認值也沒有,那麼spring啓動就可能會出現異常。

代碼中使用

配置方式1:經過@Value,如

public class TestJavaConfigBean {

  @Value("${timeout:100}")

  private int timeout;

  private int batch;

 

  @Value("${batch:200}")

  public void setBatch(int batch) {

    this.batch = batch;

  }

 

  public int getTimeout() {

    return timeout;

  }

 

  public int getBatch() {

    return batch;

  }

}

 

 

@Configuration

@EnableApolloConfig

public class AppConfig {

  @Bean

  public TestJavaConfigBean javaConfigBean() {

    return new TestJavaConfigBean();

  }

}

 

配置方式2:經過@ ConfigurationProperties,如

@ConfigurationProperties(prefix = "redis.cache")

public class SampleRedisConfig {

  private int expireSeconds;

  private int commandTimeout;

 

  public void setExpireSeconds(int expireSeconds) {

    this.expireSeconds = expireSeconds;

  }

 

  public void setCommandTimeout(int commandTimeout) {

    this.commandTimeout = commandTimeout;

  }

}

 

@Configuration

@EnableApolloConfig

public class AppConfig {

  @Bean

  public SampleRedisConfig redisConfigBean() {

    return new SampleRedisConfig ();

  }

}

 

配置方式3:經過ApolloConfig獲取整個namespace的配置

,以下,@ApolloConfig 能夠和@Value一塊兒使用,ApolloConfigChangeListener能夠監聽配置變化:

public class TestApolloAnnotationBean {

  @ApolloConfig

  private Config config; //inject config for namespace application

  @ApolloConfig("application")

  private Config anotherConfig; //inject config for namespace application

  @ApolloConfig("FX.apollo")

  private Config yetAnotherConfig; //inject config for namespace FX.apollo

 

  @Value("${batch:100}")

  private int batch;

  

  //config change listener for namespace application

  @ApolloConfigChangeListener

  private void someOnChange(ConfigChangeEvent changeEvent) {

    //update injected value of batch if it is changed in Apollo

    if (changeEvent.isChanged("batch")) {

      batch = config.getIntProperty("batch", 100);

    }

  }

 

  //config change listener for namespace application

  @ApolloConfigChangeListener("application")

  private void anotherOnChange(ConfigChangeEvent changeEvent) {

    //do something

  }

 

  //config change listener for namespaces application and FX.apollo

  @ApolloConfigChangeListener({"application", "FX.apollo"})

  private void yetAnotherOnChange(ConfigChangeEvent changeEvent) {

    //do something

  }

 

  //example of getting config from Apollo directly

  //this will always return the latest value of timeout

  public int getTimeout() {

    return config.getIntProperty("timeout", 200);

  }

 

  //example of getting config from injected value

  //the program needs to update the injected value when batch is changed in Apollo using @ApolloConfigChangeListener shown above

  public int getBatch() {

    return this.batch;

  }

}

 

配置方式4(不推薦):在傳統的application.properties文件 經過${} 方式引入apollo配置:

applicationKey= ${apolloValue}

 

配置方式5((不推薦): 直接經過API的方式

獲取默認namespace的配置(application)

Config config = ConfigService.getAppConfig(); //config instance is singleton for each namespace and is never null

String someKey = "someKeyFromDefaultNamespace";

String someDefaultValue = "someDefaultValueForTheKey";

String value = config.getProperty(someKey, someDefaultValue);

 

配置方式6((不推薦): 經過XML的方式

使用:

@Autowired
TestJavaConfigBean javaConfigBean;

@Autowired
SampleRedisConfig redisConfig;

@Autowired
TestApolloAnnotationBean apolloAnnotationBean;

 

注意事項

關於apollo配置文件

關於 META-INF/app.properties文件:它主要是用來定義app.id的。官方默認狀況下,這個文件是不可缺乏的,可是爲了簡化你們的開發,我這邊已經修改了源碼,設置了默認值hy,因此,這個文件如今就變成不是必須配置的了

 

關於server.properties 文件,位於C:\opt\settings\server.properties或/opt/settings/server.properties ,它主要是用來定義env和idc參數的。官方默認狀況下,這個文件是不可缺乏的,可是爲了簡化你們的開發,我這邊已經修改了源碼,設置了默認值env=dev,因此,這個文件如今就變成不是必須配置的了(若是有設置,那麼,它是不可動態增長刪除或修改, 只在啓動的時候讀取一次)

 

因此,如今來講, 咱們已經不須要任何apollo配置文件了,咱們直接在portal上配置便可。

相關的重要的環境變量,不要覆蓋!:

jvm 參數

env idc

系統環境變量:

ENV, app.id, idc

配置文件

/META-INF/app.properties: app.id

server.properties: env, idc

 

本地緩存文件

位於:

/opt/data/{appId}/config-cache 或C:\opt\data\{appId}\config-cache

 

啓動順序

咱們的dubbo應用啓動以前, apollo 必須先啓動好,

 

不然,咱們dubbo應用會一直等待,直到apollo準備就緒,而且能夠在控制檯看到以下輸出

...

2018-03-01 18:01:59,932 [Apollo-RemoteConfigLongPollService-1] WARN  com.ctrip.framework.apollo.internals.RemoteConfigLongPollService.doLongPollingRefresh:193 - Long polling failed, will retry in 16 seconds. appId: SampleApp, cluster: default, namespaces: application+FX.apollo, long polling url: null, reason: Get config services failed from http://192.168.1.228:8080/services/config?appId=SampleApp&ip=192.168.1.222 [Cause: Could not complete get operation [Cause: connect timed out]]

2018-03-01 18:02:19,932 [Apollo-RemoteConfigLongPollService-1] WARN  com.ctrip.framework.apollo.internals.RemoteConfigLongPollService.doLongPollingRefresh:193 - Long polling failed, will retry in 32 seconds. appId: SampleApp, cluster: default, namespaces: application+FX.apollo, long polling url: null, reason: Get config services failed from http://192.168.1.228:8080/services/config?appId=SampleApp&ip=192.168.1.222 [Cause: Could not complete get operation [Cause: connect timed out]]

2018-03-01 18:02:55,933 [Apollo-RemoteConfigLongPollService-1] WARN  com.ctrip.framework.apollo.internals.RemoteConfigLongPollService.doLongPollingRefresh:193 - Long polling failed, will retry in 64 seconds. appId: SampleApp, cluster: default, namespaces: application+FX.apollo, long polling url: null, reason: Get config services failed from http://192.168.1.228:8080/services/config?appId=SampleApp&ip=192.168.1.222 [Cause: Could not complete get operation [Cause: connect timed out]]

2018-03-01 18:04:03,934 [Apollo-RemoteConfigLongPollService-1] WARN  com.ctrip.framework.apollo.internals.RemoteConfigLongPollService.doLongPollingRefresh:193 - Long polling failed, will retry in 120 seconds. appId: SampleApp, cluster: default, namespaces: application+FX.apollo, long polling url: null, reason: Get config services failed from http://192.168.1.228:8080/services/config?appId=SampleApp&ip=192.168.1.222 [Cause: Could not complete get operation [Cause: connect timed out]]

...

注意其中輪詢時間是從1,2,3,4,8,14,32, 方式一直增加,單位是s

 

 

問題:

 

由於數據庫是: http://192.168.4.112:5998/eureka/

2018-03-22 12:01:41.470  INFO 3840 --- [ost-startStop-1] c.c.f.a.biz.service.BizDBPropertySource  : Load config from DB : eureka.service.url = http://192.168.4.112:5998/eureka/

 

而portal 的參數是:

-Dapollo_profile=github,auth -Ddev_meta=http://localhost:5998/

 

因而portal 就啓動不了。。

2018-03-22 12:02:30.321 ERROR 8536 --- [HealthChecker-1] c.c.f.a.portal.component.PortalSettings  : Env is down. env: DEV, failed times: 3, meta server address: http://localhost:5998/

2018-03-22 12:02:40.322 ERROR 8536 --- [HealthChecker-1] c.c.f.a.portal.component.PortalSettings  : Env health check failed, maybe because of meta server down or configure wrong meta server address. env: DEV, meta server address: http://localhost:5998/

 

com.ctrip.framework.apollo.common.exception.ServiceException: No available admin server. Maybe because of meta server down or all admin server down. Meta server address: http://localhost:5998/

at com.ctrip.framework.apollo.portal.component.RetryableRestTemplate.getAdminServices(RetryableRestTemplate.java:172)

at com.ctrip.framework.apollo.portal.component.RetryableRestTemplate.execute(RetryableRestTemplate.java:90)

at com.ctrip.framework.apollo.portal.component.RetryableRestTemplate.get(RetryableRestTemplate.java:56)

at com.ctrip.framework.apollo.portal.api.AdminServiceAPI$HealthAPI.health(AdminServiceAPI.java:47)

at com.ctrip.framework.apollo.portal.component.PortalSettings$HealthCheckTask.isUp(PortalSettings.java:127)

at com.ctrip.framework.apollo.portal.component.PortalSettings$HealthCheckTask.run(PortalSettings.java:103)

at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)

at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)

at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)

at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

at java.lang.Thread.run(Thread.java:745)

 

2018-03-22 12:02:40.328 ERROR 8536 --- [HealthChecker-1] c.c.f.a.portal.component.PortalSettings  : Env is down. env: DEV, failed times: 4, meta server address: http://localhost:5998/

2018-03-22 12:02:50.530  INFO 8536 --- [HealthChecker-1] c.c.f.a.portal.component.PortalSettings  : Env revived because env health check success. env: DEV

 

解決:

都改爲localhost, 或者ip 就能夠了Apollo配置中心

相關文章
相關標籤/搜索