程序配置的原则和实践以及 Spring Boot 支持方式
原则
软件需要在不同的环境中部署,代码是保持不变的,但是不同的运行环境存在差异,所以需要使用配置适应不同的环境。比如:
- 数据库,Redis,以及其他 后端服务 的配置;
- 第三方服务的证书,如 oAuth、支付接口 等;
- 每份部署特有的配置,如域名等。
配置的原则是:代码与配置要严格分离,不允许在代码中使用常量保存配置。
最常见的配置方式就是配置文件,按照配置文件的存储位置,可以分为内部配置和外部配置:
- 内部配置:部署文件是发布产物的一部分,存储在发布目录中,甚至打包在一起,比如 jar 包里面的 properties 文件。这些配置文件在不同的环境间不存在差异,其实他们可以看做是部署产物的一部分,比如 Spring 用来定义类创建和注入关系的 xml 文件。从运维的角度来看,尽管他们是配置文件,实际上和写死代码没有什么区别。反过来说,如果某个配置项在不同环境中是有差异的,就不应该放到内部;
- 外部配置:不在部署产物内,需要在部署环境上修改。需要注意不要把这样的文件提交到代码控制系统,总是有人不小心这样做。
配置漂移
构建好的程序被部署在服务器上后,为了解决故障、性能优化、适应新的需求,需要对服务器和应用的配置进行更改。如果直接登录服务器修改某个配置,随着时间的推移和管理的复杂化,就会引发配置漂移。
这种可以直接登录修改的服务器称为可变服务器。可变服务器会造成开发、测试、生产服务器不一致,生产环境中不同的节点也不一致,容易出现运行问题。
要防止配置漂移,服务器要禁止手动修改,只能通过自动化部署形式更改配置,这种服务器就叫不可变服务器。不可变服务器消除了不一致性,开发、测试环境中得到的程序包和最终到达服务器的程序包是完全相同的。这样就能防止配置漂移。
推荐方式
生产环境使用以下几配置种技术:
- 配置文件:使用外部配置,按照 Linux 的目录规范在
/etc
目录,或者其他合适的位置; - 启动参数:在启动参数中注入配置数据,这是防止配置漂移的好办法;
- 环境变量:与启动参数相似,也是推荐的方式;
- 配置服务:使用某种集中配置平台,比如 etcd、Zookeeper、Spring Cloud Config. 这些平台使用不同的协议,在数据结构、存储一致性方面有不同的设计思想,可以选择一个合适的。配置服务可以支持动态修改,比如 Spring Cloud Config 提供了
refresh
端口,可以调动这个端口在不重启进程的情况下修改配置项。
Spring Boot 配置方式
示例程序演示了 Spring Boot 配置方式,打包运行:
mvn package
export message=bonjour
java -Dmessage=hello \
-jar spring-boot-config-sample-1.0.0-SNAPSHOT.jar \
--message=hi \
--spring.config.name=application,conf
message
配置出现在 4 个位置:
- 系统环境变量
export message=bonjour
- Java 属性
-Dmessage=hello
- 命令行参数
--message=hi
- 内部配置文件
application.properties
启动之后在 env
端口查看设置:
$ curl http://localhost:8080/actuator/env
{
"propertySources":
[
{
"name": "commandLineArgs",
"properties":
{
"message":
{
"value": "hi"
}
}
},
{
"name": "systemProperties",
"properties":
{
"message":
{
"value": "hello"
}
}
},
{
"name": "systemEnvironment",
"properties":
{
"message":
{
"value": "bonjour",
"origin": "System Environment Property \"message\""
}
}
},
{
"name": "applicationConfig: [classpath:/application.properties]",
"properties":
{
"message":
{
"value": "nihao",
"origin": "class path resource [application.properties]:9:9"
}
}
}
]
}
这里删掉了一些无关的内容,可以看到 message
设置是按照 commandLineArgs
、systemProperties
、systemEnvironment
、applicationConfig
的顺序加载的,以最先出现的为准。
spring.config.name
启动参数定义了配置文件的名称。Spring Boot 默认的配置文件是 application.properties
,这里添加了一个 conf.properties
。
Spring Boot 按照特定的顺序加载配置项,位置和顺序如下:
DevTool
定义的配置项@TestPropertySource
标签定义的配置项@SpringBootTest#properties
标签定义的配置项- 启动参数
SPRING_APPLICATION_JSON
环境变量ServletConfig
定义的init
参数ServletContext
定义的init
参数- JNDI 属性
- Java 系统属性,使用
-Dkey=value
定义,System.getProperties()
可以查看到 - 操作系统环境变量
RandomValuePropertySource
定义的随机值- 带
profile
的外部配置文件 - 带
profile
的内部配置文件 - 不带
profile
的外部配置文件 - 不带
profile
的内部配置文件 @Configuration
类型里面的@PropertySource
标签定义的配置SpringApplication.setDefaultProperties
方法设置的默认值
内外部配置文件的加载位置和顺序如下:
config
目录.
当前目录classpath:/config
classpath:/
Docker
使用 Dockerfile
是在生产环境创建 Docker 镜像的唯一推荐方式,示例程序提供了 Dockerfile
样例。Dockerfile
将运行包和配置文件复制到镜像里:
RUN mkdir -p /opt/stack
COPY target/spring-boot-config-sample-1.0.0-SNAPSHOT.jar /opt/stack/
COPY ./conf.properties /opt/stack/
在环境变量和启动参数中注入配置项:
ENV message=bonjour
ENTRYPOINT ["java", \
"-jar", \
"spring-boot-config-sample-1.0.0-SNAPSHOT.jar", \
"--spring.config.name=application,conf"]
定义了健康检查规则:
HEALTHCHECK --interval=30s --timeout=10s \
CMD curl -f http://localhost:8080/actuator/health || exit 1
Dockerfile
里面还对镜像系统进行了设置,提高了打开文件句柄数。Docker 是实现不可变服务器的最佳方式。
RUN ulimit -n 65536
使用 docker build
命令制作镜像,第一次运行会下载一个 primetoninc/jdk
基础镜像,需要花一些时间:
docker build -t config-sample .
使用 docker run
命令运行程序:
docker run -it -p 8080:8080 config-sample
在实际环境上可以使用 Kubernetes、Mesos 这样的平台管理和运行 Docker 镜像,完全可以避免直接登录服务器操作。
本文代码示例:https://github.com/lane-cn/spring-boot-config-sample
程序配置的原则和实践以及 Spring Boot 支持方式的更多相关文章
- Spring Boot 支持多种外部配置方式
Spring Boot 支持多种外部配置方式 http://blog.csdn.net/isea533/article/details/50281151 这些方式优先级如下: 命令行参数 来自java ...
- Spring Boot 支持 Https 有那么难吗?
https 现在已经越来越普及了,特别是做一些小程序或者公众号开发的时候,https 基本上都是刚需了. 不过一个 https 证书还是挺费钱的,个人开发者可以在各个云服务提供商那里申请一个免费的证书 ...
- Spring Boot 支持 HTTPS 如此简单,So easy!
这里讲的是 Spring Boot 内嵌式 Server 打 jar 包运行的方式,打 WAR 包部署的就不存在要 Spring Boot 支持 HTTPS 了,需要去外部对应的 Server 配置. ...
- Spring Boot 支持 HTTPS 如此简单,So easy!
这里讲的是 Spring Boot 内嵌式 Server 打 jar 包运行的方式,打 WAR 包部署的就不存在要 Spring Boot 支持 HTTPS 了,需要去外部对应的 Server 配置. ...
- spring boot: 支持jsp,支持freemarker
spring boot: 支持jsp,支持freemarker 支持jsp: 加入依赖 <!--jsp--> <dependency> <groupId>org.a ...
- 后端开发实践:Spring Boot项目模板
在我的工作中,我从零开始搭建了不少软件项目,其中包含了基础代码框架和持续集成基础设施等,这些内容在敏捷开发中通常被称为"第0个迭代"要做的事情.但是,当项目运行了一段时间之后再来反 ...
- Spring REST实践之Spring Boot
Spring Boot基本描述 可以利用http://start.spring.io网站的进行Spring Boot的初始化构建.这个初始化构建器允许你输入工程基本信息.挑选工程支持的功能,最后会生成 ...
- 55. spring boot 服务配置和部署【从零开始学Spring Boot】
Spring Boot 其默认是集成web容器的,启动方式由像普通Java程序一样,main函数入口启动.其内置Tomcat容器或Jetty容器,具体由配置来决定(默认Tomcat).当然你也可以将项 ...
- Spring Boot 实践 :Spring Boot + MyBatis
Spring Boot 实践系列,Spring Boot + MyBatis . 目的 将 MyBatis 与 Spring Boot 应用程序一起使用来访问数据库. 本次使用的Library spr ...
随机推荐
- rsync命令简单用法介绍
rsync有两种常用的认证方式,一种为rsync-daemon方式,另外一种则是ssh.在一些场合,使用rsync-daemon方式会比较缺乏灵活性,ssh方式则成为首选.但是今天实际操作的时候发现当 ...
- 2018-2019-2 20175202实验一《Java开发环境的熟悉》实验报告
2018-2019-2 20175202实验一<Java开发环境的熟悉>实验报告 一.实验内容 1.使用JDK编译.运行简单的Java程序: 2.使用IDEA 编辑.编译.运行.调试Jav ...
- Jquery 一个页面多个倒计时 实现
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- element-ui 点击获取table的行索引
<el-table :data="list" v-loading.body="listLoading" element-loading-text=&quo ...
- php7带来的性能升级
前言本文是一篇讲座听后+后续研究的总结. 话说当年追时髦,php7一出就给电脑立马装上了,php5和php7共存,也是立马写了个超级耗时间的循环脚本测了一番,确实php7给力很多,然后也是注意了一些新 ...
- 一个HTTP打趴80%面试者
面试多年,每当我问起面试者对HTTP的了解时,个个回答令我瞠目结舌,这些开发者都有3-5年的经验.请不要让我叫你野生程序员,是时候了解HTTP了,让我们当个正规军. 起因 面试官:请问你了解HTTP协 ...
- Windows下面Node和NPM的绿色安装及配置
1,Node安装 Windows版本可以在http://nodejs.org/#download下面选择msi安装版或者绿色版.其实Node的安装主要是Node.exe文件deploy和有关环境变量的 ...
- 2018-2019-2 20175311 实验二 《Java开发环境的熟悉》实验报告
2018-2019-2 20175303 实验二 <Java开发环境的熟悉>实验报告 一.实验准备 1.了解掌握实验所要用到的三种代码 伪代码 产品代码 测试代码 2.IDEA中配置单元测 ...
- python:面向对象初级
面向对象编程类的概念 : 具有相同属性和技能的一类事物 人类 抽象对象 : 就是对一个类的具体的描述 具体的人 具体 使用面向对象的好处: 使得代码之间的角色关系更加明确 增强了代码的可扩展性 规范了 ...
- python with as的用法
With语句是什么? 有一些任务,可能事先需要设置,事后做清理工作.对于这种场景,Python的with语句提供了一种非常方便的处理方式.一个很好的例子是文件处理,你需要获取一个文件句柄,从文件中读取 ...