zoukankan      html  css  js  c++  java
  • 一个合格的CloudNative应用:程序当开源软件编写,应用配置外置

    摘要:对于一个合格的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》,作者:关耳山石

     

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

  • 相关阅读:
    316 Remove Duplicate Letters 去除重复字母
    315 Count of Smaller Numbers After Self 计算右侧小于当前元素的个数
    313 Super Ugly Number 超级丑数
    312 Burst Balloons 戳气球
    309 Best Time to Buy and Sell Stock with Cooldown 买股票的最佳时间含冷冻期
    Java 类成员的初始化顺序
    JavaScript 全局
    HTML字符实体
    Java中的toString()方法
    JavaScript 弹窗
  • 原文地址:https://www.cnblogs.com/huaweiyun/p/14557948.html
Copyright © 2011-2022 走看看