springbootconfigjava

配置中心

2017-01-16  本文已影响272人  AbsurdOS

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

方案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

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

disconf-web安装

安装依赖软件

打开disconf-web文件夹

注意,记得执行将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配置

    <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"/>必须去掉否则会报错

    <!-- 使用托管方式的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

上一篇下一篇

猜你喜欢

热点阅读