配置中心

當項目達到一定程度,配置五花八門這時候配置中心的便派上了用場。

方案1 maven打包

如果只是要區(qū)分開發(fā)環(huán)境和上線環(huán)境的配置,只要打包的時候吧不同文件環(huán)境打包進來就ok了
maven舉例

<profiles>
<profile>
    <id>local</id>
    <activation>
        <activeByDefault>true</activeByDefault>
    </activation>
    <properties>
        <package.environment>local</package.environment>
    </properties>
</profile>
<profile>
    <id>dev</id>
    <properties>
        <package.environment>dev</package.environment>
    </properties>
</profile>
<profile>
    <id>prod</id>
    <properties>
        <package.environment>production</package.environment>
    </properties>
</profile>
</profiles>
<build>  
    <resources>  
        <resource>  
            <directory>src/main/resources</directory>  
            <excludes>  
                <exclude>test/*</exclude>  
                <exclude>production/*</exclude>  
                <exclude>development/*</exclude>  
            </excludes>  
        </resource>  
        <resource>  
            <directory>src/main/resources/${profiles.active}</directory>  
        </resource>  
    </resources>  
</build>  

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <webXml>src/main/webapp/WEB-INF/web.xml</webXml>
                    <webResources>
                        <resource>
                            <directory>/config/${package.environment}/properties</directory>
                            <targetPath>WEB-INF/classes/properties</targetPath>
                            <filtering>false</filtering>
                        </resource>
                    </webResources>
                </configuration>
            </plugin>

mvn package –P dev

方案2 spring profiles

spring為beans標簽提供了profile功能,以便項目的開發(fā)和生成環(huán)境分離。
參考:https://my.oschina.net/yybear/blog/113755
spring boot 不再贅述http://blog.csdn.net/he90227/article/details/52981747

方案3 Spring Cloud Config Server

maven依賴

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.4.1.BUILD-SNAPSHOT</version>
</parent>
<dependencies>
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
    </dependency>
</dependencies>

服務端

@EnableConfigServer
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
@Override
protected SpringApplicationBuilderconfigure(SpringApplicationBuilder application) {
    return application.sources(Application.class);
 }
public static void main(String[] args) throws Exception {
    SpringApplication.run(Application.class,args);
 }
}

配置文件application.properties

(git)

spring.application.name=config-server
server.port=7001
spring.cloud.config.server.git.uri=https://github.com/www1350/springclouddemo
##搜索目錄
spring.cloud.config.server.git.searchPaths=properties
spring.cloud.config.server.git.username=aaaa
spring.cloud.config.server.git.password=bbb
spring.cloud.config.enabled=true

(svn)

spring.application.name=config-server
server.port=7001
spring.cloud.config.server.svn.uri=svn://IP:port/project/config
spring.cloud.config.server.svn.username=absurd
spring.cloud.config.enabled=true
spring.cloud.config.server.svn.password=fdsaf

feign-consumer-dev.properties

userid=7
username=123
password=123
  • /{application}/{profile}[/{label}]
  • [/{label}/]{application}-{profile}.yml
  • [/{label}/]{application}-{profile}.properties

http://localhost:7001/feign-consumer/dev/master


http://localhost:7001/master/feign-consumer-dev.yml


http://localhost:7001/master/feign-consumer-dev.properties

客戶端調(diào)用(bootstrap.properties)

spring.application.name=feign-consumer
spring.cloud.config.profile=dev
spring.cloud.config.label=master
spring.cloud.config.uri=http://localhost:7001/
@RestController
@RefreshScope
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@Value("${userid}")
private Long userid;
@Value("${username}")
private String username;
@Value("${password}")
private String password;

@RequestMapping(value="/username",method= RequestMethod.GET)
@ResponseBody
public String getUserName(){
return username;
}
@RequestMapping(value="/dev",method= RequestMethod.GET)
@ResponseBody
public String getUser(){
return userService.getUserByParam(userid);
}
@RequestMapping(value="/{id}",method= RequestMethod.GET)
@ResponseBody
public String getUser(@PathVariable("id") Long id){
return userService.getUser(id);
}
}

下面這種寫法也是可以的。

@Autowired
private Environment environment;

另外,他還提供了很多方式來滿足需求。比如,修改了配置后,可以

$curl -X POST http://localhost:7001/refresh

來刷新配置。

$curl -X POST http://localhost:7001/restart

項目地址:https://github.com/www1350/springclouddemo
官方:https://github.com/spring-cloud/spring-cloud-config

方案4 Disconf

  • Distributed Configuration Management Platform(分布式配置管理平臺)
  • 專注于各種「分布式系統(tǒng)配置管理」的「通用組件」和「通用平臺」, 提供統(tǒng)一的「配置管理服務」。
    功能特點
  • 支持配置(配置項+配置文件)的分布式化管理
  • 配置發(fā)布統(tǒng)一化
  • 配置發(fā)布、更新統(tǒng)一化:
  • 同一個上線包 無須改動配置 即可在 多個環(huán)境中(RD/QA/PRODUCTION) 上線
  • 配置存儲在云端系統(tǒng),用戶統(tǒng)一管理 多個環(huán)境(RD/QA/PRODUCTION)、多個平臺 的所有配置
  • 配置更新自動化:用戶在平臺更新配置,使用該配置的系統(tǒng)會自動發(fā)現(xiàn)該情況,并應用新配置。特殊地,如果用戶為此配置定義了回調(diào)函數(shù)類,則此函數(shù)類會被自動調(diào)用。
  • 極簡的使用方式(注解式編程 或 XML無代碼侵入模式):我們追求的是極簡的、用戶編程體驗良好的編程方式。目前支持兩種開發(fā)模式:基于XML配置或者基于注解,即可完成復雜的配置分布式化。
  • 低侵入性或無侵入性、強兼容性:
  • 低侵入性:通過極少的注解式代碼撰寫,即可實現(xiàn)分布式配置。
  • 無侵入性:通過XML簡單配置,即可實現(xiàn)分布式配置。
  • 強兼容性:為程序添加了分布式配置注解后,開啟Disconf則使用分布式配置;若關閉Disconf則使用本地配置;若開啟Disconf后disconf-web不能正常Work,則Disconf使用本地配置。
  • 支持配置項多個項目共享,支持批量處理項目配置。
  • 配置監(jiān)控:平臺提供自校驗功能(進一步提高穩(wěn)定性),可以定時校驗應用系統(tǒng)的配置是否正確。
    注:配置項是指某個類里的某個Field字段。
    官方文檔:http://disconf.readthedocs.io/zh_CN/latest/

disconf-web安裝

安裝依賴軟件

  • Mysql(Ver 14.12 Distrib 5.0.45, for unknown-linux-gnu (x86_64) using EditLine wrapper)
  • Tomcat(apache-tomcat-7.0.50)
  • Nginx(nginx/1.5.3)
  • zookeeeper (zookeeper-3.3.0)
  • Redis (2.4.5)
    項目地址:https://github.com/knightliao/disconf

打開disconf-web文件夾

  • jdbc-mysql.properties (數(shù)據(jù)庫配置)
  • redis-config.properties (Redis配置,主要用于web登錄使用)
  • zoo.properties (Zookeeper配置)
  • application.properties (應用配置)

注意,記得執(zhí)行將application-demo.properties復制成application.properties:
cp application-demo.properties application.properties

上線前的初始化工作
初始化數(shù)據(jù)庫:
可以參考 sql/readme.md 來進行數(shù)據(jù)庫的初始化。注意順序執(zhí)行

0-init_table.sql
1-init_data.sql
201512/20151225.sql
20160701/20160701.sql

里面默認有6個用戶(請注意線上環(huán)境刪除這些用戶以避免潛在的安全問題

name pwd
admin admin
testUser1 MhxzKhl9209
testUser2 MhxzKhl167
testUser3 MhxzKhl783
testUser4 MhxzKhl8758
testUser5 MhxzKhl112

如果想自己設置初始化的用戶名信息,可以參考代碼來自己生成用戶:
src/main/java/com/baidu/disconf/web/tools/UserCreateTools.java

部署War
修改server.xml文件,在Host結點下設定Context:
<Context path="" docBase="/home/work/dsp/disconf-rd/war"></Context>

并設置端口為 8015
啟動Tomcat,即可。
部署 前端
修改 nginx.conf

upstream disconf {
server 127.0.0.1:8015;
}
server {
listen  80;
server_name localhost;
access_log /home/work/var/logs/disconf/access.log;
error_log /home/work/var/logs/disconf/error.log;
location / {
root /home/work/dsp/disconf-rd/war/html;
if ($query_string) {
expires max;
}
}
location ~ ^/(api|export) {
proxy_pass_header Server;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_pass http://localhost;
}
}

關于host
這里的 host 設置成 localhost (可以自定義),但它 必須與 application.properties 里的domain一樣。
然后瀏覽器的訪問域名也是這個。

新建app

Paste_Image.png

新建配置項

Paste_Image.png
Paste_Image.png

新增配置文件

Paste_Image.png

以config1.properties舉例:

uid=1
password=4
username=www2
Paste_Image.png

客戶端

引入

<dependency>
<groupId>com.baidu.disconf</groupId>
<artifactId>disconf-client</artifactId>
<version>2.6.36</version>
</dependency>

基于xml的分布式配置
第一步:撰寫配置文件

    <bean id="disconfMgrBean" class="com.baidu.disconf.client.DisconfMgrBean"
          destroy-method="destroy">
        <property name="scanPackage" value="com.absurd"/>
    </bean>
    <bean id="disconfMgrBean2" class="com.baidu.disconf.client.DisconfMgrBeanSecond"
          init-method="init" destroy-method="destroy">
    </bean>
    <context:component-scan base-package="com.absurd"/>
    <aop:aspectj-autoproxy  proxy-target-class="true"/>

第二步:撰寫disconf.properties

# 是否使用遠程配置文件
# true(默認)會從遠程獲取配置 false則直接獲取本地配置
enable.remote.conf=true

#
# 配置服務器的 HOST,用逗號分隔  127.0.0.1:8000,127.0.0.1:8000
#
conf_server_host=localhost

# 版本, 請采用 X_X_X_X 格式
version=1_0_0_0

# APP 請采用 產(chǎn)品線_服務名 格式
app=absurd-app

# 環(huán)境
env=rd

# debug
debug=true

# 忽略哪些分布式配置,用逗號分隔
ignore=

# 獲取遠程配置 重試次數(shù),默認是3次
conf_server_url_retry_times=1
# 獲取遠程配置 重試時休眠時間,默認是5秒
conf_server_url_retry_sleep_seconds=1

第三步:撰寫配置類
以config1.properties舉例:

@Service
@Scope("singleton")
@DisconfFile(filename = "config1.properties")
public class OneConfig {
    private Long uid;
    private String username;
    private String password;

    @DisconfFileItem(name = "uid", associateField = "uid")
    public Long getUid() {
        return uid;
    }

    public void setUid(Long uid) {
        this.uid = uid;
    }

    @DisconfFileItem(name = "username", associateField = "username")
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @DisconfFileItem(name = "password", associateField = "password")
    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

上面這種寫法是托管配置,通過簡單的注解類方式 托管配置。托管后,本地不需要此配置文件,統(tǒng)一從配置中心服務獲取。

當配置被更新后,注解類的數(shù)據(jù)通過@Service實現(xiàn)自動同步。

** 變量分布式配置 **

@Service
@Scope("singleton")
public class OneKeyConfig {
    private Long key;
    @DisconfItem(key = "absurd-app-rd-1")
    public Long getKey() {
        return key;
    }
}

靜態(tài)配置

@DisconfFile(filename = "config1.properties")
public class OneStaticConfig {
    private static Long uid;
    private static String username;
    private static String password;
    @DisconfFileItem(name = "uid", associateField = "uid")
    public static Long getUid() {
        return uid;
    }

    @DisconfFileItem(name = "username", associateField = "username")
    public static String getUsername() {
        return username;
    }

    @DisconfFileItem(name = "password", associateField = "password")
    public static String getPassword() {
        return password;
    }
}

配置更新的通知

實現(xiàn)IDisconfUpdate 接口的reload方法,注意這里此類必須是JavaBean,Spring托管的,且 “scope” 都必須是singleton的。
添加 @DisconfUpdateService 注解,classes 值加上 OneConfig.class ,表示當 JedisConfig.class 這個配置文件更新時,此回調(diào)類將會被調(diào)用?;蛘撸褂?confFileKeys 也可以。

@Service
@Scope("singleton")
@DisconfFile(filename = "config1.properties")
@DisconfUpdateService(classes = {OneConfig.class})
public class OneConfig implements IDisconfUpdate {
    Logger logger = LoggerFactory.getLogger(getClass());
    private Long uid;
    private String username;
    private String password;

    @DisconfFileItem(name = "uid", associateField = "uid")
    public Long getUid() {
        return uid;
    }

    public void setUid(Long uid) {
        this.uid = uid;
    }

    @DisconfFileItem(name = "username", associateField = "username")
    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    @DisconfFileItem(name = "password", associateField = "password")
    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void reload() throws Exception {
        logger.info(">>>>>>>>>>配置已改變>>>>>>>>>>>>");

    }
}

當然也可以單獨抽出來寫一個類

基于xml配置

  • 可以自動reload
    <bean id="configproperties_disconf" class="com.baidu.disconf.client.addons.properties.ReloadablePropertiesFactoryBean">
        <property name="locations">
            <list>
                <value>classpath:config2.properties</value>
            </list>
        </property>
    </bean>

    <bean id="propertyConfigurer" class="com.baidu.disconf.client.addons.properties.ReloadingPropertyPlaceholderConfigurer">
        <property name="ignoreResourceNotFound" value="true"/>
        <property name="ignoreUnresolvablePlaceholders" value="true"/>
        <property name="propertiesArray" >
            <list>
                <ref bean="configproperties_disconf"/>
            </list>
        </property>
    </bean>

如果有 <context:property-placeholder location="classpath*:properties/*.properties"/>必須去掉否則會報錯

  • 不可以自動reload
    <!-- 使用托管方式的disconf配置(無代碼侵入, 配置更改不會自動reload)-->
    <bean id="configproperties_no_reloadable_disconf"
          class="com.baidu.disconf.client.addons.properties.ReloadablePropertiesFactoryBean">
        <property name="locations">
            <list>
                <value>classpath:config2.properties</value>
            </list>
        </property>
    </bean>

    <bean id="propertyConfigurerForProject1"
          class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="ignoreResourceNotFound" value="true"/>
        <property name="ignoreUnresolvablePlaceholders" value="true"/>
        <property name="propertiesArray">
            <list>
                <ref bean="configproperties_no_reloadable_disconf"/>
            </list>
        </property>
    </bean>

過濾要進行托管的配置

忽略哪些分布式配置,用逗號分隔

ignore=jdbc-mysql.properties

示例代碼如下:
https://github.com/www1350/disconfig-demos

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容