打造环境感知的应用

打造环境感知的应用

这里说的环境感知的应用是指,应用放在不同的环境,就可以使用不同环境的配置,不需要重新打包.

1.我眼中理想的环境和应用

  • 应用不用管环境配置
  • 参数配置在配置管理系统中的
  • 框架从配置管理中加载配置
  • 只有操作系统或者应用服务器知道环境的概念

理想很丰满,现实很惨…,揉醒了,继续面对现实.要实现这个目标,还有很多需要做的.现在我们尽可能要做的是,开发童鞋自己把环境搞定,不给其他童鞋添堵.

2.适合我们的环境感知的应用

我们的系统大多数用的是tomcat作为应用服务器,最好是让应用服务器来提供环境标识,在应用中结合spring profile机制来实现环境感知

3.如何操作

3.1在操作系统中添加环境变量

比如在10测试环境,在/etc/profile中增加如下东东:

export CATALINA_OPTS=' -Dspring.profiles.active=dev '

然后执行. /etc/profile解析

3.2配置日志

并不是所有系统都会针对不同环境启用不同的日志配置文件,即便有logback可以很方便的来解决这些问题.

3.2.1 在logback配置内区分环境

比如我们在本地测试的时候,把日志输出到console,便于我们查问题.
可以在logback.xml中加入:

<if condition='property("os.name").toUpperCase().contains("WINDOWS")||property("os.name").toUpperCase().contains("MAC")'>
    <then>
        <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
            <encoder>
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{0}:%L-%X{ID}- %msg%n</pattern>
            </encoder>
        </appender>
        <root>
            <appender-ref ref="STDOUT" />
        </root>
    </then>
</if>

上面的配置会在windows和mac中启用console日志输出

在logback中引入外部配置文件,也可以区分不同的环境

<property resource="spring/log/log-${spring.profiles.active}.properties" />

上面会根据spring.profiles.active的配置读取不同的配置文件

3.2.2 不同环境区分不同的日志配置文件

如果您有针对不同环境不同的日志文件,com.yjf.common.log.LogbackConfigListener提供了支持.

<context-param>
      <param-name>logbackConfigLocation</param-name>
      <param-value>WEB-INF/logback-${spring.profiles.active}.xml</param-value>
  </context-param>

3.3 配置应用

数据库和外部资源配置,一般会放入到单独的配置文件中,我们可以使用spring提供的能力来实现环境感知

3.3.1 使用properties文件
<bean id="propertyConfigurerForJDBC"
    class="com.yjf.common.dal.EncryptablePropertyPlaceholderConfigurer">
    <property name="order" value="1" />
    <property name="ignoreUnresolvablePlaceholders" value="true" />
    <property name="location"
        value="classpath:jdbc-${spring.profiles.active}.properties" />
</bean>

上面会根据spring.profiles.active的配置读取不同jdbc配置文件

3.3.2 使用spring profile
<beans profile="production">
     <bean id="xxx" class="xxxxBEAN" />  
</beans>
<beans profile="test">
     <bean id="xxx" class="xxxxBEAN" />  
</beans>

spring profile通过读取系统或者环境变量spring.profiles.active来启用不同的bean.

3.3.2 硬编码实现

com.yjf.common.env.Env提供了在编写java code时,区分不同的环境

private void doIt() {
    if (Env.isOnline()) {
        //do anything you like.
    }
}

上面的代码只在生成环境运行,com.yjf.common.env.Env通过读取spring.profiles.active来判断环境

3.4 配置测试

通过上面的一些列配置,环境都由spring.profiles.active控制.在本地测试时,也需要启用此环境变量.

3.4.1 tomcat/jetty 启动类

TomcatBootstrapHelper启动时,默认会在系统变量里增加spring.profiles.active=dev

new TomcatBootstrapHelper(11111).start();

上面的代码会使用dev环境配置.如果您按照3.3.1配置,此时会读取jdbc-dev.properties

我没有写jetty的启动帮助类,主要原因是为了和线上保持一致,减少一些不可预知的问题.如果要使用jetty,请增加如下代码:

static{
    System.setProperty("spring.profiles.active", "dev");
}
3.4.1 单元测试

在测试类或者测试父类中增加:

static{
    System.setProperty("spring.profiles.active", "dev");
}
给攻城狮一个小小的鼓励!