• 0
  • 0
分享

  一、配置架构

  在微服务的代码工程中,配置管理是一项复杂的事情,即需要做好各个环境的配置隔离措施,还需要确保生产环境的配置安全;如果划分的微服务足够的多,还要考虑配置更新时的效率;

2-1.png

  常规情况下,在配置管理的体系中,分为四个主要的环境:开发、测试、灰度、生产;通常来说除了运维团队之外,其他人员没有查看灰度和生产配置的权限,以此来保证配置的安全性;配置中心的服务也会搭建两套:研发与生产各自独立部署。

  二、配置方式

  在项目中涉及到的配置非常多,类型也很多,但是从大的结构上可以分为:工程级、应用级、组件级三大块;实际上这里只是单纯的从代码工程来看配置,如果把持续集成、自动化相关模块也考虑进来的话,配置的管理会更加复杂;

2-2.png

  站在开发的角度来看,主要还是对应用级的配置进行管理,而在微服务的架构下,多个不同的服务既有大量相同的配置,又存在各种差异化的自定义参数,所以在维护上有一定的复杂性;

2-3.png

  在单服务的工程中,应用中只会存在一个bootstrap.yml配置文件,配置内容基本就是服务名称,和配置中心地址等常规内容,其他复杂的配置都被封闭维护,避免核心内容泄露引发安全问题;

2-4.png

  配置主体通常会被拆分成如下几个层次:环境控制,用来识别灰度和生产;应用基础,管理和加载各个服务的通用配置;服务差异则配置在各自独立的文件内;并且对多个配置进行分类分层管理;以此保证配置的安全和降低维护难度。

  三、Nacos配置

  首先还是从bootstrap.yml文件作为切入点,以当下常见的Nacos组件为例,围绕基础原理作为思路,来分析服务工程是如何加载Nacos配置中心的参数;

  spring:
    profiles:
      active: dev,facade
    cloud:
      nacos:
        config:
          prefix: application
          server-addr: 127.0.0.1:8848
          file-extension: yml

2-5.png

  组件配置:配置逻辑中,单个服务端提供自身配置参数的信息,从上篇服务管理的源码中发现,这是一种很常用的手段;需要基于这些信息去Nacos服务中加载配置;

  @ConfigurationProperties("spring.cloud.nacos.config")
  public class NacosConfigProperties {
      public Properties assembleConfigServiceProperties() {
          Properties properties = new Properties();
          properties.put("serverAddr", Objects.toString(this.serverAddr, ""));
          properties.put("namespace", Objects.toString(this.namespace, ""));
          return properties ;
      }
  }

  加载逻辑:服务启动时,先基于相应参数读取Nacos中配置的,然后解析数据并被Spring框架进行加载,加载的过程通过MapPropertySource类进行Key和Value的读取;

  public class NacosPropertySourceBuilder {
      private List<PropertySource<?>> loadNacosData(String dataId, String group, String fileExtension) {
          // 查询配置
          String data = this.configService.getConfig(dataId, group, this.timeout);
          // 解析配置
          return NacosDataParserHandler.getInstance().parseNacosData(dataId, data, fileExtension);
      }
  }

  请求服务:服务端与Nacos中心通过Http请求的方式进行交互,通过Get请求携带参数,调用Nacos中心服务,从而获取相应配置;

  public class ClientWorker implements Closeable {
      public String[] getServerConfig(String dataId, String group, String tenant, long readTimeout) {
          // 核心参数
          Map<String, String> params = new HashMap<String, String>(3);
          params.put("dataId", dataId);
          params.put("group", group);
          params.put("tenant", tenant);
          // 执行请求
          HttpRestResult<String> result = agent.httpGet(Constants.CONFIG_CONTROLLER_PATH, null, params, agent.getEncode(), readTimeout);
      }
  }

  四、Spring加载

  从源码的结构图来看,配置文件的加载逻辑也是采用事件模型实现的,这在前面任务管理中有详细的描述;配置的核心作用就是在程序启动时进行加载引导,这里关键要理解EnvironmentPostProcessor的接口设计;

2-6.png

  public class ConfigFileApplicationListener implements EnvironmentPostProcessor, SmartApplicationListener, Ordered {
      // 基础配置
      private static final String DEFAULT_NAMES = "application";
      public static final String ACTIVE_PROFILES_PROPERTY = "spring.profiles.active";
      public static final String INCLUDE_PROFILES_PROPERTY = "spring.profiles.include";
      static {
      Set<String> filteredProperties = new HashSet<>();
      filteredProperties.add("spring.profiles.active");
      filteredProperties.add("spring.profiles.include");
      LOAD_FILTERED_PROPERTY = Collections.unmodifiableSet(filteredProperties);
      }
      // 加载逻辑
      void load() {
  FilteredPropertySource.apply(this.environment, DEFAULT_PROPERTIES, LOAD_FILTERED_PROPERTY,
  (defaultProperties) -> {
  });
      }
  }

  EnvironmentPostProcessor接口:加载应用的自定义环境;

  @FunctionalInterface
  public interface EnvironmentPostProcessor {
  void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application);
  }

  SpringApplication:用于启动和引导应用程序,提供创建程序上下文实例,初始化监听器,容器刷新等核心逻辑,可以围绕run()方法进行调试分析;

  ConfigurableEnvironment:环境配置的核心接口,涉及到当前配置文件识别,即profiles.active;以及配置文件的解析能力,即PropertyResolver;在Loader内部类中提供了构造方法和加载逻辑的实现。


作者:知了一笑    

来源:http://www.51testing.com/html/52/n-7796552.html

  • 【留下美好印记】
    赞赏支持
登录 后发表评论
+ 关注

热门文章

    最新讲堂

      • 推荐阅读
      • 换一换
          •   一、简介  我的jdk是1.8 Jmeter版本是3.3 其它可能会有冲突 导致不能正确安装 jdk和jmeter会有对应版本,大家注意。  二、打开Jmeter  在安装jmeter里面的bin目录下双击jmeter.bat文件即可本地启动。  三、添加虚拟用户组  入下图所示,右击“测试计划”,添加-Theard-线程组。 线程组:JMeter是由Java实现的,并且使用一个Java线程来模拟一个用户,因此线程组就是指一组用户的意思,这些虚拟用户用来模拟访问被测系统。  四、线程组常用设置  线程数:虚拟用户数,默认的输入是1,表明一个用户访问被测系统,如果想模拟100个用户...
            0 0 1298
            分享
          • 一、前言说到底,你真的会造火箭吗?常说面试造火箭,入职拧螺丝。但你真的有造火箭的本事吗,大部分都是不敢承认自己的知识盲区和技术瓶颈以及经验不足的自嘲。面试时:我希望你懂数据结构,因为这样的你在使用HashMap、ArrayList、LinkedList,更加得心应手。我希望你懂散列算法,因为这样的你在设计路由时,会有很多选择;除法散列法、平方散列法、斐波那契(Fibonacci)散列法等。我希望你懂开源代码,因为这样的你在遇到问题时,可以快速定位,还可能创造出一些系统服务的中间件,来更好的解耦系统。我希望你懂设计模式,因为这样的你可以写出可扩展、易维护的程序,让整个团队都能向更好的方向发展。所...
            14 15 1925
            分享
          •   疫情波及面广泛,2020年,因为疫情引发的一系列后续事件,很多人的生活受到影响,作为一个打工人心里也有诸多想法。  要说这一年怎么样?用一个字总结:难。  据统计,2020年9月份,全国城镇调查失业率达8.7%,按照现行标准下劳动人口年龄18岁-59岁来计算,截至现在,中国失业人数已超过8000万人!  在年末的时候,笔者曾分别在boss直聘和智联上关注了一段时间的测试岗位,发现招聘的公司和职位很少,有时甚至2天都没有新的招聘信息,即使有也是hr例行公事而已,想投简历都很难。  不过好在这一年终于过去,大家又可以开始投简历准备面试了!在面试之前,笔者就来给大家分享一下,面试过程中基本都会被...
            0 0 1217
            分享
          • 应用场景:测试上传大量文件时,如果手动创建的数量太多效率就会比较慢,通过Python脚本可以快速地批量创建任意数量的文件夹和文件。下面的代码以创建TXT文本和创建文件夹目录为例,也可以修改代码第20行,将文本后缀改成其他的格式。# ! usr/bin/env/ python # -*- coding: utf-8 -*- import os, sys def createF(file_num):     """  ...
            0 0 3379
            分享
          • 最近在项目过程中使用selenium 判断元素是否存在的时候 遇到一个很坑爹的问题,当某些元素不存在时,页面可能出现响应很久的情况,以下是本人总结的webdriver处理页面等待时间的几种方式:1、显式等待显式等待,就是明确的要等到某个元素的出现或者是某个元素的可点击等条件,等不到,就一直等除非在规定的时间之内都没找到,那么就跳出Exception。/** 设置元素等待时间 @param driver @param by @param timeOut //等待时间,以秒为单位 /public static void wait...
            0 0 790
            分享
      • 51testing软件测试圈微信