配置中心

作者: AbsurdOS | 来源:发表于2017-01-16 17:19 被阅读272次

    当项目达到一定程度,配置五花八门这时候配置中心的便派上了用场。

    方案1 maven打包

    如果只是要区分开发环境和上线环境的配置,只要打包的时候吧不同文件环境打包进来就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功能,以便项目的开发和生成环境分离。
    参考: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

    客户端调用(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(分布式配置管理平台)
    • 专注于各种「分布式系统配置管理」的「通用组件」和「通用平台」, 提供统一的「配置管理服务」。
      功能特点
    • 支持配置(配置项+配置文件)的分布式化管理
    • 配置发布统一化
    • 配置发布、更新统一化:
    • 同一个上线包 无须改动配置 即可在 多个环境中(RD/QA/PRODUCTION) 上线
    • 配置存储在云端系统,用户统一管理 多个环境(RD/QA/PRODUCTION)、多个平台 的所有配置
    • 配置更新自动化:用户在平台更新配置,使用该配置的系统会自动发现该情况,并应用新配置。特殊地,如果用户为此配置定义了回调函数类,则此函数类会被自动调用。
    • 极简的使用方式(注解式编程 或 XML无代码侵入模式):我们追求的是极简的、用户编程体验良好的编程方式。目前支持两种开发模式:基于XML配置或者基于注解,即可完成复杂的配置分布式化。
    • 低侵入性或无侵入性、强兼容性:
    • 低侵入性:通过极少的注解式代码撰写,即可实现分布式配置。
    • 无侵入性:通过XML简单配置,即可实现分布式配置。
    • 强兼容性:为程序添加了分布式配置注解后,开启Disconf则使用分布式配置;若关闭Disconf则使用本地配置;若开启Disconf后disconf-web不能正常Work,则Disconf使用本地配置。
    • 支持配置项多个项目共享,支持批量处理项目配置。
    • 配置监控:平台提供自校验功能(进一步提高稳定性),可以定时校验应用系统的配置是否正确。
      注:配置项是指某个类里的某个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 (数据库配置)
    • redis-config.properties (Redis配置,主要用于web登录使用)
    • zoo.properties (Zookeeper配置)
    • application.properties (应用配置)

    注意,记得执行将application-demo.properties复制成application.properties:
    cp application-demo.properties application.properties

    上线前的初始化工作
    初始化数据库:
    可以参考 sql/readme.md 来进行数据库的初始化。注意顺序执行

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

    里面默认有6个用户(请注意线上环境删除这些用户以避免潜在的安全问题

    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 请采用 产品线_服务名 格式
    app=absurd-app
    
    # 环境
    env=rd
    
    # debug
    debug=true
    
    # 忽略哪些分布式配置,用逗号分隔
    ignore=
    
    # 获取远程配置 重试次数,默认是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;
        }
    }
    

    上面这种写法是托管配置,通过简单的注解类方式 托管配置。托管后,本地不需要此配置文件,统一从配置中心服务获取。

    当配置被更新后,注解类的数据通过@Service实现自动同步

    ** 变量分布式配置 **

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

    静态配置

    @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;
        }
    }
    

    配置更新的通知

    实现IDisconfUpdate 接口的reload方法,注意这里此类必须是JavaBean,Spring托管的,且 “scope” 都必须是singleton的。
    添加 @DisconfUpdateService 注解,classes 值加上 OneConfig.class ,表示当 JedisConfig.class 这个配置文件更新时,此回调类将会被调用。或者,使用 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

    相关文章

      网友评论

        本文标题:配置中心

        本文链接:https://www.haomeiwen.com/subject/gespbttx.html