摘要:对于一个合格的CloudNative应用,应该把自己的程序当做开源软件来编写的,不该将数据库连接信息和密码放在代码里,一定要将配置外置。

对于一个合格的CloudNative应用,应该把自己的程序当做开源软件来编写的,不该将数据库连接信息和密码放在代码里,一定要将配置外置。

因此我试着在华为云上落地这套标准,期间尝试了从ServiceStage、CCE、CSE这三个入口进行配置注入,最终实现能够在应用启动时,主动拉取配置,覆盖本地配置文件里的调试配置,并能够在线配置并生效。

打法是:CCE配置启动参数,制定SpringProfiles;配合CSE做应用配置,将资源外置后的配置记录于此,并可以动态更新,最终实现了配置外置的诉求。

另外,通过这次增加的多版本管理,尝试梳理了一下ServiceStage的组件、CCE的workload、CSE的应用和微服务之间,错综复杂的概念之间的关系,个人浅见,欢迎指正:

1. 初始化配置

在系统初始化的时候,不可能一点配置都没有,所以保留一些基础配置在配置文件里是有必要的。配置外置并不意味着100%的配置都要外置,而是把外部依赖资源的配置,特别是容易变化配置外置。

1.1 启用Bootstrap和Spring profile

在代码层面,首先要进行基础配置。先看代码结构,这里除了最基本的application.yaml,增加了bootstrap.yaml和*-dev.yml等带后缀的文件。

介绍一下原理:

  • 首先介绍Bootstrap Application Context:
    它是Spring Cloud Context的父Context,所以从外部配置源里加载配置一般从这里来,且优先级高于其他一切配置文件。于是,我们也利用这个能力,借助CSE的微服务配置中心能力,进行Spring的外部参数写入。

  • 然后介绍Spring profiles:
    为了把通用配置和环境相关的配置区分开,比如DEV环境没有AK/SK认证,而线上环境都有认证,这种配置项上的区别,引入了Spring profiles的概念,当Springboot启动的时候,会根据profiles.active参数判断应该启用那个环境配置

PS:参考SpringCloud官方解释

另外,就是哪些配置应该放在配置文件里,理论上除了最基础的配置,在启动时使用的,其余的配置都可以放在CSE的微服务配置中心里,而不必在本地配置文件里存在,另外就是本地配置里存在的,也可以通过二次设置在微服务的配置中心里,进行覆盖,比如数据库连接池的大小,而不需要修改代码,至于改完以后,要不要重启,那就得看生效的逻辑了。

1.2 引入CSE配置中心

CSE配置中心引入,需要先引入依赖包,然后在bootstrap.yaml中配置CSE配置中心的地址、认证信息等。

这里可以参考官方文档,主要关注bootstrap.yaml的配置参数:使用分布式配置中心

补充:获取spring-cloud-starter-huawei-config的版本

参考地址:huaweicloud/spring-cloud-huawei

可以参考现有的SpringCloud基线版本,选择SpringCloud-Huawei的版本

补充:关于配置中心的优先级

微服务引擎提供了分层次的配置机制。按照优先级从高到低,分为:

  • 配置中心(动态配置)
  • Java System Property(-D参数)
  • 环境变量
  • 配置文件

参考官方文档:配置微服务

2. 本地CSE配置中心能力验证

前提条件,本地得安装一个Local-CSE并启动,这部分参考云上DevOps:2.1-本地环境准备

2.1 配置application.yaml和bootstrap.yml

原始文件可以参考Github的Demo,配置文件入口,我这里进行了修改,因为bootstrap.yaml优先级高于application.yaml,参数只要在bootstrap.yaml中出现过,就不会使用application.yaml中的配置了。

上代码,application.yaml,可以看到配置很少,因为大部分bootstrap.yml中已经包含,就都去掉了

这是bootstrap.yml,注意这里的spring.application.name、spring.cloud.servicecomb.discovery.appName和spring.cloud.servicecomb.discovery.version会组成一个微服务私有的参数作用域,这里的优先级高于全局作用域application。特别注意,云上的CSE环境,除了上面提到的,还需要增加server.env参数。另外,server.env有四个参数可以选development、testing、acceptance、production

关于如上参数的定义,参考官方文档:使用分布式注册中心官方文档:使用分布式配置中心

2.2 准备验证代码

直接上代码

2.3 静态配置能力

为了验证CSE配置中心的参数,是否能覆盖application.yaml中的参数配置,我选了一个很特别的参数:spring.datasource.password,如果能够覆盖成功,那么启动后,创建数据库连接池一定会报错。

  • 首先,打开本地CSE配置中心,地址为:http://localhost:30106/#/cse/services/config,创建一个配置项,作用域选VodMgrService@CabgOne#1.0.0,关于application的作用域后面再解释。

  • 重启本地微服务,启动后创建数据库连接池就报错了,符合预期。

结论:CSE配置中心的参数,能够覆盖application.yaml中的参数配置

2.4 动态配置能力

为了验证CSE配置中心的参数动态生效,需要使用注解@RefreshScope,同时也引入ConfigRefreshEvent来监听事件变化,这样就会得到一个效果,对于动态生效的参数,可能需要一些重建或刷新,比如连接池、缓存、Client等。

  • 首先,增加一个配置项config.value

  • 然后很快可以看到后台日志打印出来,包括自己的监听器,也响应了日志

  • 查看一下数据,已经响应为TryMe

  • 具体的配置,在后台是轮询的,响应周期配置参数为cloud.servicecomb.config.watch.delay,目前是10秒一次

  • 修改一下配置,为TryMeAgain

  • 再看后台日志,有新的触发器发生

  • 再次请求API,数据已经更新

  • 再深入去看,这里的getChange()返回是一个Set<String>,因此可以针对特定的参数做文章。

结论:本地CSE配置中心的参数能够动态刷新,并开放了ConfigRefreshEvent,以扩展配置更新后的业务动作。

2.5 配置的作用域限制

目前CSE的配置中心提供两级作用域限制,一个是全域,一个是私域,即微服务内部(不同版本有区分)。

  • 增加一个作用域为application的全域参数,一个作用域为VodMgrService@CabgOne#1.0.0的私域同名参数

  • 验证一下,生效的作用域是VodMgrService@CabgOne#1.0.0

  • 删除私域参数后,生效的作用域是application

结论:本地CSE配置中心的全域配置的优先级,低于微服务内部配置,即私域配置可以覆盖全域配置。

3. 云上配合外置落地

3.1 代码提交并自动打包推送SWR

代码提交,推送到CodeHub上,流水线在CloudPipeline自动驱动起来,开始执行,打包、制作镜像、推送SWR,并且展开了代码质量检查。这些得益于前面的WIKI:Phase2 - 云上DevOps

3.2 CCE启动参数配置

由于ServiceStage的自动部署能力还不满足,所以手工将DockerImage升级到环境上,这里直接使用CCE进行操作,原因在题记里介绍了,ServiceStage的参数配置不太好用

3.2.1 利用CCE的容器启动命令写入参数

  • 选择升级版本,点高级配置,CCE的核心配置入口都在这里了

  • 在启动时,注入最核心的一个参数-Dspring.profiles.active=uat

  • 此处的命令是Docker启动是的ENTRYPOINT,下面那个是CMD,会覆盖Dockerfile里的命令

  • 点击右下角的提交,会看到实例列表中已经有一个新的pod在启动

  • 回到AOM服务,查看日志,会发现The following profiles are active: uat,符合预期

3.3 CCE环境变量配置

3.3.1 利用CCE的环境变量写入参数

  • 首先回退上面那一步的配置,进入高级设置->环境变量
  • 增加环境变量JAVA_TOOL_OPTIONS,值设置为-Dspring.profiles.active=uat

  • 提交以后查看日志,符合预期

至于为啥JAVA_TOOL_OPTIONS能用,因为JVM原生就包含这个参数,可以用来在启动时写入配置,可以参考Oracle的官方文档

3.4 CCE配置中心

3.4.1 利用CCE的配置中心 + 环境变量写入参数

CCE的配置中心包含了两个大类,配置项ConfigMap和秘钥Secret,前面介绍的CCE环境变量,支持从配置中心导入参数,比如我可以在ConfigMap里写入这个参数,然后在CCE的环境变量中引入。

  • 首先创建一个配置项,这里的配置项是按照集群、命名空间区分的

  • 然后创建一套配置项,输入一套KV

  • 回到CCE升级的步骤,修改环境变量,增加一项配置项写入的变量,可以选到刚才输入的KEY,就不用输入VALUE了

然后再看看秘钥,玩儿法类似,但是有一点很“有趣”:这里的秘钥是要主动用BASE64转码过才能保存,不过在使用的时候,会解密的,因此不必关心转码回来的问题。

3.4.2 利用CCE的配置中心 + 数据存储写入参数

无论是配置项ConfigMap还是秘钥Secret,都可以支持利用CCE的数据存储挂载能力写入参数到容器里,简单理解,就是会自动帮你把配置下载到一个容器的存储位置上,文件名是KEY,内容是VALUE,可以在代码里读取这个配置。

配置方式很简单,选择配置项,然后写一个挂载目录即可

3.5 云上CSE配置中心

这里是另一个核心,线下验证过,云上的CSE类似,但是配置模型更复杂,增加了server.env维度,并且全域和私域参数配置位置不一样。

  • 首先,从ServiceStage->微服务CSE->配置管理,进入全域配置页面,选择环境为yaml里配置的server.env参数

返回结果为,生效

PS:如果这里不选环境,则参数无法读取,即环境为空也是一类环境,不同环境之间隔离

  • 然后,从ServiceStage->微服务CSE->微服务目录,进入私域页面

进而选择动态配置,在配置作用域时,选择不带version的,环境是固定值,

返回结果为,生效

  • 同样的页面下,在配置作用域时,选择带version的,

返回结果为,生效

总结:云上CSE配置中心参数加载优先级

  • P1:微服务私域,带Version
  • P2:微服务私域,无Version
  • P3:全域,带环境
    其余参数都不生效,包括全域无环境、全域不同环境、微服务私域不同Version

总结

综上,基于华为云ServiceStage、CCE、CSE的配置外置能力,可以支撑微服务在不同环境中灵活部署,而无需修改代码。目前的总结打法是:

  1. 利用CCE的容器启动参数,或环境变量,写入profiles.active参数
  2. 利用CSE的配置中心,写入业务参数,如MySQL连接串、连接池配置、GES引擎地址、VOD服务Endpoint地址等

本文分享自华为云社区《[CloudNative] 企业应用上云实践手记-Cloud Native Phase 3 - 云原生应用AutoConfig》,作者:关耳山石

点击关注,第一时间了解华为云新鲜技术~

一个合格的CloudNative应用:程序当开源软件编写,应用配置外置的更多相关文章

  1. (转)Linux-HA开源软件Heartbeat(配置篇)

    原文:http://ixdba.blog.51cto.com/2895551/548625 http://gzsamlee.blog.51cto.com/9976612/1828870 Linux-H ...

  2. 自由软件VS开源软件

    自由软件VS开源软件 “自由软件运动”是一项倡导软件这种知识产品应该免费共享的社会运动,它主要是从社会伦理学,道德的高度,强调我们每个人都有自由使用软件的权利.这种权利不应该被软件私有所破坏. 反对软 ...

  3. 几种常见的开源软件许可协议(GPL, LGPL, Apache License, BSD)

    GPL GPL授予程序接受人以下权利,或称“自由”: * 以任何目的运行此程序的自由 * 以学习程序工作机理为目的,对程序进行修改的自由(能得到源代码是前提) * 再发行复制件的自由 * 改进此程序, ...

  4. 介绍一个非常好用的跨平台C++开源框架:openFrameworks

    介绍一个非常好用的跨平台C++开源框架:openFrameworks 简介 首先需要说明的一点是: openFrameworks 设计的初衷不是为计算机专业人士准备的, 而是为艺术专业人士准备的, 就 ...

  5. 程序员快围观!2016年最受欢迎中国开源软件TOP 20

    [PConline 资讯]开源软件对程序员来说是一个经常接触的软件,作为一个经常接触的软件,当然想知道自己用的软件受欢迎程度,基于此,开源中国在近日公布"2016年度最受欢迎中国开源软件评选 ...

  6. 用Vue.js开发微信小程序:开源框架mpvue解析

    前言 mpvue 是一款使用 Vue.js 开发微信小程序的前端框架.使用此框架,开发者将得到完整的 Vue.js 开发体验,同时为 H5 和小程序提供了代码复用的能力.如果想将 H5 项目改造为小程 ...

  7. 【翻译】Sencha Touch 2入门:创建一个实用的天气应用程序之三

    原文:Getting Started with Sencha Touch 2: Build a Weather Utility App (Part 3) 作者:Lee BoonstraLee is a ...

  8. 郑晔谈 Moco 框架的开发:写一个好的内部 DSL ,写一个表达性好的程序

    作者:张龙 出处:http://www.infoq.com/cn/news/2013/07/zhengye-on-moco 郑晔谈Moco框架的开发:写一个好的内部DSL,写一个表达性好的程序 作者  ...

  9. 【Java】一个简单的Java应用程序

    简单记录,Java 核心技术卷I 基础知识(原书第10 版) 一个简单的Java应用程序"Hello, World!" Hello, World! Goodbye,World! 一 ...

  10. 一个简单的P2P传输程序

    写了一个简单的P2P传输程序,在P2P的圈子中传输文件,不过为了简便,这个程序没有真正的传输文件,只是简单的判断一下文件的位置在哪里.这个程序可以处理当有一个peer闪退的情况,在这种情况下,剩下的p ...

随机推荐

  1. 手写商用Java虚拟机HotSpot,疯狂磨砺技术中

    在当前Java行业激烈竞争的形式下,唯有掌握技术,心中才不能慌.在多年前,我就开始苦练底层技术,但是眼看百遍也不如手过一遍,所以我打算把虚拟机的精华实现部分用手敲出来,这个过程注定不会轻松,但是心态不 ...

  2. Maze 1D 题解

    题目大意 在数轴上给定一串行动指令,类型有两种:向左移动一个单位 / 向右移动一个单位.要求最后一步到达一个没有到达过的位置.可以在数轴上放置若干个障碍物阻碍移动,问在放置的障碍物最少的情况下有多少放 ...

  3. Epic资源转到unity的方法

    众所周知,unity中的素材主要是通过unity资源商店获取的.但是unity资源商店的白嫖机会太少了,而隔壁UE的Epic资源商店就有每月免费的资源,不白嫖成何体统?但是UE咱也不会用啊,白嫖的资源 ...

  4. AtCoder Beginner Contest 321(ABC321)

    A. 321-like Checker 直接模拟. Code B. Cutoff 直接暴力枚举 \([0\sim100]\),每次把第 \(n\) 个数当作当前枚举的 \(i\),然后看看条件是否满足 ...

  5. python实现汉诺塔的图解递归算法

    写在前面 工作闲来无事,看了python,写了一个汉诺塔. 还是蛮喜欢python这门语言的,很简洁. 正文 一.起源: 汉诺塔(又称河内塔)问题是源于印度一个古老传说的益智玩具.大梵天创造世界的时候 ...

  6. 文心一言 VS 讯飞星火 VS chatgpt (129)-- 算法导论11.1 4题

    四.用go语言,我们希望在一个非常大的数组上,通过利用直接寻址的方式来实现一个字典.开始时该数组中可能包含一些无用信息,但要对整个数组进行初始化是不太实际的,因为该数组的规模太大.请给出在大数组上实现 ...

  7. el-table 多表格弹窗嵌套数据显示异常错乱问题

    1.业务背景 使用vue+element开发报表功能时,需要列表上某列的超链接按钮弹窗展示,在弹窗的el-table列表某列中再次使用超链接按钮点开弹窗,以此类推多表格弹窗嵌套,本文以弹窗两次为例 最 ...

  8. Keepalived+Nginx高可用案例(抢占式与非抢占式)

    (1)下载安装Keepalived源码包 Keepalived官网源码包下载地址 在服务器上解压 tar -xf keepalived-2.2.8.tar.gz 安装相关前置依赖 yum -y ins ...

  9. C语言输入任意长度数组后,再在该数组中查找特定的值,并且可查找多个相同的值

    C语言输入任意长度数组后,再在该数组中查找特定的值,并且可查找多个相同的值 例:在a[20] = { 99,42,57,74,46,85,32,78,40,33,74,88,65,27,38,69,5 ...

  10. LabVIEW基于机器视觉的实验室设备管理系统(3)

    目录 行动计划 创建用户信息数据库 后面板连线 初始化 确认修改 确认id 判断旧密码是否正确 判断两次输入的新密码是否相同 修改用户数据库中的密码 结尾 效果演示 上一期我们完成了欢迎登录和信息查询 ...