前言

基于现代服务的云原生十二要素理论,我们在采用容器化部署时,要保证同一个镜像可以满足不同环境的部署要求,而不是不同环境打包不同的镜像。本文档主要介绍一种基于spring框架的满足不同环境配置的编译打包方案,满足同一个镜像可以在环境分组下通过启动项配置实现不同环境的部署。

现有方案及问题

我们见过最常见的配置文件管理方案,是基于Maven的profile配置来实现多环境切换的,它的弊端在于,我们将profile配置在pom.xml中,每次编译打包时,需要通过编译指令-P来标识当前环境配置。这样导致的问题是,我们打包的镜像具有了环境属性,不符合一个镜像多环境部署的要求。

还有一种配置方案,就是基于Spring profile进行配置文件管理。针对这两种方案,我接下来会进行一些分析和对比。

两种profiles配置的不同和优劣对比

a. 两种profiles方案对比

  1. Maven 的 profiles:

◦ Maven 的 profiles 是在构建时根据环境或其他条件激活不同的配置集合。可以在项目的pom.xml文件中定义多个 profile,并使用 Maven 命令行参数或其他配置来激活特定的 profile。

◦ 优势:

灵活性高,可以根据不同的构建环境或条件激活不同的 profile。

可以在构建过程中使用不同的依赖、插件配置等。

◦ 劣势:

配置相对分散,需要在 Maven 的pom.xml文件中定义和管理多个 profile。

配置与代码分离,不够直观。

  1. Spring 的application.properties的 profile 配置:

◦ Spring 的application.properties文件可以根据激活的 profile 来加载不同的配置。可以在application.properties文件中定义多个 profile 下的配置,并使用配置文件或环境变量来激活特定的 profile。

◦ 优势:

配置集中,可以在一个文件中定义多个 profile 下的配置,更易于管理和维护。

配置与代码相近,更直观易读。

◦ 劣势:

激活 profile 的方式相对有限,通常需要通过配置文件或环境变量来指定。

不适用于构建过程中的配置,主要用于应用程序的运行配置。

总的来说,Maven profiles 更适用于构建过程中的配置,可以根据构建环境或条件激活不同的 profile,而 Spring 的application.properties的 profile 配置更适用于应用程序的运行配置,可以根据不同的 profile 加载不同的配置。具体选择哪种方式取决于你的需求和偏好。

b. 在云原生和容器化的部署场景分析

在云原生和容器化的部署场景下,我更倾向使用 Spring 的application.properties的 profile 配置方式。

以下是在云原生和容器化部署场景下,使用application.properties的 profile 配置方式的优势:

  1. 环境无关性:application.properties可以根据激活的 profile 加载不同的配置,使得应用程序在不同的环境中运行时具有一致的行为。这对于云原生和容器化的部署非常重要,因为应用程序可能需要在不同的环境(例如开发、测试、生产)中运行。
  2. 配置集中化:使用application.properties的 profile 配置方式,可以在一个文件中定义多个 profile 下的配置,使得配置管理更加集中和方便。这对于云原生和容器化的部署场景非常有帮助,因为可以根据不同的 profile 加载适当的配置,而无需分散地管理多个 Maven profiles。
  3. 容器友好性:在容器化的部署场景中,通常使用容器编排工具(如 Kubernetes)来管理应用程序的配置和部署。使用application.properties的 profile 配置方式,可以通过环境变量或配置文件中的属性来指定激活的 profile,从而实现与容器编排工具的集成。

综上所述,使用 Spring 的 application.properties 的 profile 配置方式更适合云原生和容器化的部署场景,因为它提供了环境无关性、配置集中化和容器友好性的优势。

基于properties的多环境配置方案实践

以下方案以springboot为例,当然springMVC方案也是可以适配,只是需要额外配置一下,介于我们新项目基本都是基于springboot搭建,此处不展开springMVC的实线方案,如有需要,我再额外提供mvc的配置方案。

a. 配置文件树

如上图所示

  • properties文件夹:我们在properties文件夹下,基于不同的环境,简历单独文件夹,比如dev,online, test, uat等,每个文件夹下存放当前环境的配置信息。
  • spring文件夹: 下存放xml配置信息,比如常见的JSF配置(jsf.xml),以及其他需要通过xml配置注入的业务场景。当然基于springboot官网建议,大家尽量用注解代码方式实现bean注入,尽量减少xml的方式。
  • application.properties文件: 该文件里通过核心的配置spring.profiles.active=**来标识当前是哪个profile环境。当然一些其他全局类配置也可以放在此处。需要注意application.properties文件需要配置在行云部署中分组配置里,因为此文件需要基于不同的部署分组进行文件覆盖,以改变spring.profiles.active的值,如下图所示。当然,也可以通过运行时启动指令,进行不同的profile选择。
  • important.properties文件: 该文件为京东行云部署规约,把秘钥等安全性高的文件以加密存储的方式存放在该文件中,并部署到行云部署分组的远程配置里。

具体行云部署里的配置如下:

b. properties文件加载

正常情况下,properties//*.properties下的配置文件是不会自动加载到启动项里的。所以需要通过额外的方式动态加载,具体方法是通过spring框架下的PropertySourcesPlaceholderConfigurer的类属性,结合环境变量,动态批量加载配置文件。(额外说明,如果是springMVC框架,也可以通过xml配置context:property-placeholder属性来实现。**)

具体代码如下:

/**
* 配置文件环境配置
*
* @Author zhaoyongping
* @date 2023/7/10 15:13
* @ClassName EnvPropertiesConfig
* @Descripiton 配置文件环境配置
**/
@Configuration
public class EnvPropertiesConfig {
/**
* 加载属性配置
*
* @param environment 环境属性
* @return PropertySourcesPlaceholderConfigurer
* @author zhaoyongping
* @date 2023/7/10 15:13
* @description 加载属性配置
*/
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfig(Environment environment) throws IOException {
PropertySourcesPlaceholderConfigurer config = new PropertySourcesPlaceholderConfigurer();
String[] activeProfiles = environment.getActiveProfiles();
if (activeProfiles.length > 0) {
String resourceUrl = "classpath:properties/"
+ environment.getActiveProfiles()[0] + "/*.properties";
config.setLocations(
new PathMatchingResourcePatternResolver().getResources(resourceUrl));
} else {
//兜底策略
config.setLocations(
new PathMatchingResourcePatternResolver()
.getResources("classpath:properties/dev/*.properties"));
}
return config;
} }

总结

通过以上步骤,我们可以实现编译打包镜像不需要跟环境变量绑定,而只需要在启动运行时基于不同的分组动态配置的applicaiton.properties文件,来实现不同环境的适配。这种可以在运行时变更配置文件的机制,更适合在云原生时代下的容器化部署方案,也利于我们的服务的可移植性。当然,以上只是笔者个人的一个实践经验,并不能代表它是最优实践方案。

作者:京东物流 赵勇萍

来源:京东云开发者社区 自猿其说Tech 转载请注明来源

Spring配置文件的魔法炼金术:如何制造容器化时代的完美配方的更多相关文章

  1. 容器化时代我们应当选择Kubernetes

    前天发的文章<基于Kubernetes 构建.NET Core 的技术体系>,有同学问.NET Core上有Spring Cloud类似的平台吗? .NET Core出现这么久了,这个为云 ...

  2. 【Day03】Spring cloud:源码讲解与容器化初探

    今日内容 原理和源码 容器化过度 一.Naocs 1.介绍 server端 启动入口类(Spring Boot项目,提供8848端口的监听访问) 源码包含InstanceController类(ser ...

  3. 一份.NET 容器化的调查小结

    小编在上个月在微信公众号"dotnet跨平台" 做了一个针对.NET 容器化的调查:https://mp.weixin.qq.com/s/oszbuIORT0G8XLLgMZzkn ...

  4. 监听器如何获取Spring配置文件(加载生成Spring容器)

    Spring容器是生成Bean的工厂,我们在做项目的时候,会用到监听器去获取spring的配置文件,然后从中拿出我们需要的bean出来,比如做网站首页,假设商品的后台业务逻辑都做好了,我们需要创建一个 ...

  5. 你不知道的Spring配置文件

    Spring配置文件是用于指导Spring工厂进行Bean生产.依赖关系注入(装配)及Bean实例分发的"图纸".Java EE程序员必须学会并灵活应用这份"图纸&quo ...

  6. Spring配置文件详解

      转自: http://book.51cto.com/art/201004/193743.htm 此处详细的为我们讲解了spring2.5的实现原理,感觉非常有用 spring配置文件是用于指导Sp ...

  7. spring配置文件详解--真的蛮详细

    spring配置文件详解--真的蛮详细   转自: http://book.51cto.com/art/201004/193743.htm 此处详细的为我们讲解了spring2.5的实现原理,感觉非常 ...

  8. Spring 配置文件详解 (以2.5为例)

    转载自:http://blog.csdn.net/zzjjiandan/article/details/22922847          Spring配置文件是用于指导Spring工厂进行Bean生 ...

  9. Spring配置文件详解:<context:annotation-config/>和<context:component-scan base-package=""/>和<mvc:annotation-driven />

    <context:annotation-config/> 在基于主机方式配置Spring时,Spring配置文件applicationContext.xml,你可能会见<contex ...

  10. Spring 配置文件applicationContext.xml

    Spring配置文件是用于指导Spring工厂进行Bean生产.依赖关系注入(装配)及Bean实例分发的"图纸". Spring配置文件是一个或多个标准的XML文档,applica ...

随机推荐

  1. 《VTK图形图像开发进阶》第1-2章——一个稍微复杂的VTK程序

    VTK概览 数据可视化主要是通过计算机图形学的方法,以图形.图像等形式清晰有效地传递.表达信息,VTK是数据可视化的工具包. VTK全称(Visualization Toolkit),即可视化工具包, ...

  2. 如何将 dubbo filter 拦截器原理运用到日志拦截器中?

    业务背景 我们希望可以在使用日志拦截器时,定义属于自己的拦截器方法. 实现的方式有很多种,我们分别来看一下. 拓展阅读 java 注解结合 spring aop 实现自动输出日志 java 注解结合 ...

  3. 如何用windows任务视图管理多个程序,提高.net开发效率

    在 Windows 操作系统中,任务栏是一个非常重要的工具栏,用来显示当前正在运行的程序和任务.如果同时运行了很多程序,任务栏上的图标就会变得非常拥挤,不方便管理和切换.为了提高工作效率,可以通过任务 ...

  4. [golang]gin框架接收websocket通信

    前言 WebSocket是一种在单个TCP连接上进行全双工通信的协议.WebSocket让客户端和服务端之间的数据交换变得非常简单,且允许服务器主动向客户端推送数据,并且之后客户端和服务端所有的通信都 ...

  5. 【Unity3D】素描特效

    1 非真实渲染 ​ 法线贴图和凹凸映射中讲述了普通光照的渲染原理,实现的效果比较贴近真实世界(照相写实主义,Photorealism),非真实渲染(Non-Photorealism Rendering ...

  6. Protobuf vs JSON

    Protobuf(Protocol Buffers)和 JSON 都是数据序列化格式,但它们在许多方面有着显著的不同.以下是对两者的一些主要比较: 数据大小和速度: Protobuf:由于 Proto ...

  7. Log4j疯狂写日志问题排查

    一.问题是怎么发现的 最近有个 Java 系统上线后不久就收到了磁盘使用率告警,磁盘使用率已经超过了 90% 以上,并且磁盘使用率还在不停增长. 二.问题带来的影响 由于服务器磁盘被打满,导致了系统正 ...

  8. vue3探索——组件通信之事件总线

    Vue2.x使用EventBus进行组件通信,而Vue3.x推荐使用mitt.js. 比起Vue实例上的EventBus,mitt.js好在哪里呢?首先它足够小,仅有200bytes,其次支持全部事件 ...

  9. Linux 内核音频数据传递主要流程 (上)

    Linux 用户空间应用程序通过声卡驱动程序(一般牵涉到多个设备驱动程序)和 Linux 内核 ALSA 框架导出的 PCM 设备文件,如 /dev/snd/pcmC0D0c 和 /dev/snd/p ...

  10. 手写raft(三) 实现日志压缩

    手写raft(三) 实现日志压缩 在上一篇博客中MyRaft实现了日志复制功能,按照计划接下来需要实现日志压缩. 手写raft(一) 实现leader选举 手写raft(二) 实现日志复制 1. 什么 ...