尊重原創,本文轉自:https://www.cnblogs.com/FlyAway2013/p/8811385.htmlhtml
前咱們項目,全部的配置基本都是經過本地properties 文件進行配置的,好比ip地址、端口、消息中間件和數據庫鏈接的各類參數,當咱們須要切換環境或調整參數的時候,咱們必須手動的修改這些配置。若是隻有一個配置文件還好,可是,若是有不少這樣的配置文件,並且又分佈式部署在多臺機器,那麼這樣, 無疑是很是低效並且容易出錯的。java
咱們當前的項目,大都是分佈式部署的項目,機器多,配置項更是繁多,所以,咱們頗有必要引入一個配置中心。mysql
各開源配置中心對比矩陣以下:git
在對比了各家的開源產品以後,咱們選用了攜程的apollo : https://github.com/ctripcorp/apollogithub
Apollo(阿波羅)是攜程框架部門研發的分佈式配置中心,可以集中化管理應用不一樣環境、不一樣集羣的配置,配置修改後可以實時推送到應用端,而且具有規範的權限、流程治理等特性,適用於微服務配置管理場景。redis
服務端基於Spring Boot和Spring Cloud開發,打包後能夠直接運行,不須要額外安裝Tomcat等應用容器。spring
Java客戶端不依賴任何框架,可以運行於全部Java運行時環境,同時對Spring/Spring Boot環境也有較好的支持。sql
.Net客戶端不依賴任何框架,可以運行於全部.Net運行時環境。數據庫
上圖簡要描述了Apollo客戶端的實現原理:json
將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 ;
./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-項目分支-版本.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啓動就可能會出現異常。
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();
}
}
@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 ();
}
}
,以下,@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;
}
}
applicationKey= ${apolloValue}
獲取默認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);
使用:
@Autowired
TestJavaConfigBean javaConfigBean;
@Autowired
SampleRedisConfig redisConfig;
@Autowired
TestApolloAnnotationBean apolloAnnotationBean;
關於 META-INF/app.properties文件:它主要是用來定義app.id的。官方默認狀況下,這個文件是不可缺乏的,可是爲了簡化你們的開發,我這邊已經修改了源碼,設置了默認值hy,因此,這個文件如今就變成不是必須配置的了
關於server.properties 文件,位於C:\opt\settings\server.properties或/opt/settings/server.properties ,它主要是用來定義env和idc參數的。官方默認狀況下,這個文件是不可缺乏的,可是爲了簡化你們的開發,我這邊已經修改了源碼,設置了默認值env=dev,因此,這個文件如今就變成不是必須配置的了(若是有設置,那麼,它是不可動態增長刪除或修改, 只在啓動的時候讀取一次)
因此,如今來講, 咱們已經不須要任何apollo配置文件了,咱們直接在portal上配置便可。
l jvm 參數
env idc
l 系統環境變量:
ENV, app.id, idc
l 配置文件
/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配置中心