【Archaius技术专题】「Netflix原生态」动态化配置服务之微服务配置组件变色龙

前提介绍

  • 如果要设计开发一套微服务基础架构,参数化配置是一个非常重要的点,而Netflix也开源了一个叫变色龙Archaius的配置中心客户端,而且Archaius可以说是比其他客户端具备更多生产级特性,也更灵活。
  • *在NetflixOSS微服务技术栈中,几乎所有的其它组件(例如Zuul, Hystrix, Eureka, Ribbon等)都依赖于Archaius,可以说理解Archaius是理解和使用Netflix其它微服务组件的基础。

Archaius是什么

Netflix Archaius是一个配置管理库,其重点是来自多个配置存储的动态属性。它包括一组用于Netflix的Java配置管理API。它主要实现为Apache Commons Configuration库的扩展。提供的主要功能有:

注意,Netflix只是开源了其配置中心的客户端部分(也就是Archaius),没有开源配套的服务器端。Archaius其实是配置源实现无关的,可以对接各种配置中心作为数据源,本文后面会介绍Archaius如何和Apollo配置中心进行集成。

Archaius项目的由来

  • 在微服务环境下,配置常常需要根据不同的上下文环境进行调整,或者说配置应该是多维度的。例如在Netflix,上下文维度包括环境(开发、测试和生产)。
  • Netflix希望能够根据发布的环境,甚至请求的上下文,动态地调整服务的配置,让Netflix的整个系统的行为和逻辑变得动态可调配,以适应互联网应用快速多变的需求。为此,Netflix平台团队开发了配置中心产品,团队将这个产品形象地称为变色龙Archaius,因为变色龙这种动物能够根据自己所处的环境动态调整身体的颜色。

Archaius在Netflix的用例场景

  1. 根据请求上下文开启或关闭某项功能。
  2. 某个页面缺省显示10个商品,在某些情况下,可以通过Archaius调整配置,只显示5个商品。
  3. 动态调整Hystrix熔断器的行为。
  4. 调整服务调用客户端的连接和请求超时参数。
  5. 如果某个线上服务产生出错告警,可以动态调整日志输出级别(粒度可以细到包或者组件级别),这样可以通过详细日志排查问题。问题定位以后,再将日志输出级别恢复到默认级别。
  6. 对于多区域或者多国家部署的应用,通过动态配置,可以根据不同区域和国家开启不同的功能。
  7. 可以根据用户的实际访问模式动态调整一些基础中间件的配置,例如缓存的存活时间TTL(Time To Live)。
  8. 数据库访问客户端的连接池配置,可以对不同服务配不同的值。例如,一个请求频率RPS(Request Per Second)小的服务,可以配置较小的连接数,而一个请求频率大的服务,可以配置较大的连接数。
  9. 运行期配置的变更可以在不同维度生效,例如集群中的单个实例维度,多区域部署下的某个区域维度,某个服务栈维度,或者某个应用集群维度。
  10. 功能开关(Feature Flag)发布,有些功能虽然上线,但是并不马上启用,而是通过配置开关动态启用,这样可以根据情况灵活开启或者关闭某项线上功能。
  11. 金丝雀发布(Canary Release),新功能上线时,让新老集群同时并存一段时间,通过配置将到老集群的流量逐步动态调整到新集群,如果监控显示无异常,则完成新集群的上线,如异常,则快速切回老集群。

Archaius的技术基础

  • archaius是netflix开源的动态属性配置框架,基于apache commons configuration, 提供在运行时获取配置值的功能。
  • Archaius的核心是可以容纳一个或多个配置的复合配置的概念。每个配置都可以从诸如JDBC、REST接口、xxx.properties文件等配置源中获取。可以选择在运行时对配置源进行轮询以进行动态更改,
  • 属性的最终值取决于包含该属性的最顶层配置(因为是复合配置)。即,如果一个属性存在于多个配置中,则应用程序看到的实际值将是配置层次结构中最顶层插槽中的值,当然这种层次结构是可以配置的。

Archaius的架构设计

Archaius实际上是对Apache Common Configuration Library的一个封装和扩展,提供了一组基于Java的配置API,主要的特性包括:

  • 配置可动态调整:动态、类型属性
  • 配置支持类型(Int, Long, Boolean等)。
  • 高性能和线程安全:高吞吐量和线程安全的配置操作
  • 提供一个拉(pulling)配置的框架,可以从配置源动态拉取变更的配置。(一个轮询框架,允许用户获取对配置源的属性更改)
  • 支持回调(callback)机制,在配置变更时自动调用。
  • 支持JMX MBean,可以通过JConsole查看配置和修改配置。

对于愿意使用基于约定的属性文件位置的应用程序(以及大多数web应用程序),提供开箱即用的复合配置(这是强大功能之一),对于符合配置官网给了一副示例图如下:

Achaius的核心是一个称为**组合配置(Composite Configuration)**的概念,简单可以理解为一个分层级的配置,层级有优先级,高优先级的层级的配置会覆盖低优先级的配置。每一个层级可以从某个配置源获取配置,例如本地配置文件,JDBC数据源,远程REST API等。配置源还可以在运行时动态拉取变更,例如在上图中,持久化数据库配置(Persisted DB Configuration)是指将配置存在关系数据库中,相应的配置源会定期从数据库拉取变更)。配置的最终值由顶级配置决定,例如,如果多个层级都含有某个配置项,那么应用最终见到的值是配置层级中最顶层的值。配置分层的顺序是可以调整的。

通过archaius获取配置值,有两种方式:
  • 一种是通过ConfigurationManager获取到配置中心实例,然后通过propName获取配置值,通过ConfigurationManager获取配置
  • 另外一种方式是通过DynamicPropertyFactory,获取配置项的DynamicProperty wrapper。

Archaius的实现原理

Archaius是什么?

Archaius提供了动态修改配置的值的功能,在修改配置后,不需要重启应用服务。其核心思想就是轮询配置源,每一次迭代,检测配置是否更改,有更改重新更新配置。

底层archaius提供实现了Apache-common-configuration的AbstractConfiguration的具体实现。

  • ConcurrentMapConfiguration提供将配置项配置值放在ConcurrentHashMap中维护的功能。

  • DynamicConfiguration提供动态从数据源获取所有配置值的功能,通过轮询数据源更新配置值。

  • DynamicWatchedConfiguration也是提供动态更新配置的功能,与DynamicConfiguration不同的是,配置更新是数据源有变化时触发的。

  • DynamicConfiguration是pull方式,DynamicWatchedConfiguration是push方式。

ConcurrentCompositeConfiguration使用了组合模式,组合不同的AbstractConfiguration实现。对于有多个配置源的配置中心,可以使用ConcurrentCompositeConfiguration。对于同一个配置项,多个配置源都有配置值的时候,取第一个匹配到的配置源的数据。

DynamicPropertyFactory是怎么运行的?

  • DynamicPropertyFactory持有AbstractConfiguration实例。
  • 创建DynamicProperty对象时,DynamicProperty对象会获取DynamicPropertyFactory持有的AbstractConfiguration实例。
  • DynamicProperty对象会向AbstractConfiguration实例注册DynamicPropertyListener, 当AbstractConfiguration有增删改查变化时,会通知到当前的DynamicProperty对象。

当创建的DynamicProperty实例数量比较大的时候,这里可能有性能问题。每创建一个任何一个DynamicProperty,都会增加一个listener,同时,任何一个配置项发生变化,都会触发listener。

可能是考虑到生产环境中不会有那么多的配置项变更吧。像zk-config那种对应配置项变更才触发watcher要好一点。

AbstractConfiguration是怎么注入的?

archaius仅允许一个AbstractConfiguration的实现类。如果有多个配置源,可以使用上面提到的ConcurrentCompositeConfiguration将不同的AbstractConfiguration组合起来。

有以下几种方式注入AbstractConfiguration。
  1. 配置archaius.default.configuration.class 指定AbstractConfiguration实现类
  2. 配置 archaius.default.configuration.factory 指定AbstractConfiguration实例工厂方法类,工厂方法类需要实现getInstance方法返回AbstractConfiguration实例
  3. 调用 ConfigurationManager 的 install(AbstractConfiguration config) 方法
  4. 调用DynamicPropertyFactory 的 initWithConfigurationSource(AbstractConfiguration config) 方法

以上方法是互斥的,只能使用其中的一种,一种生效后,其他的就不能调用了。

一个简单的例子:
Maven依赖配置
<dependency><groupId>com.netflix.archaiusgroupId><artifactId>archaius-coreartifactId><version>0.7.7version>
dependency>
复制代码
获取配置源

public class DynamicConfigurationSource implements PolledConfigurationSource {public PollResult poll(boolean initial,Object checkPoint) throws Exception {Map map = new HashMap<>();map.put("test",UUID.randomUUID().toString());return PollResult.createFull(map);}
}
复制代码
定义调度器
AbstractPollingScheduler scheduler = new FixedDelayPollingScheduler(2000,2000,false);
复制代码
定义动态配置
DynamicConfiguration configuration = new DynamicConfiguration(source,scheduler);
复制代码
简单单元测试
.testng.annotations.Testpublic void testArchaius() throws Exception {PolledConfigurationSource source = new DynamicConfigurationSource();AbstractPollingScheduler scheduler = new FixedDelayPollingScheduler(2000,2000,false);DynamicConfiguration configuration = new DynamicConfiguration(source,scheduler);ConfigurationManager.install(configuration);final DynamicStringProperty stringProperty = DynamicPropertyFactory.getInstance().getStringProperty("test","nodata");Helpers.subscribePrint(Observable.interval(1,TimeUnit.SECONDS).take(20).doOnNext(new Action1() {public void call(Long aLong) {System.out.println(stringProperty.get());}}),"test");TimeUnit.MINUTES.sleep(1);}
复制代码

实现

启动轮询任务
public synchronized void startPolling(PolledConfigurationSource source, AbstractPollingScheduler scheduler) {this.scheduler = scheduler;this.source = source;init(source, scheduler);scheduler.startPolling(source, this);
}
复制代码
轮询的Runnable和初始化:实现是一致的
PollResult result = null;try {result = source.poll(false,getNextCheckPoint(checkPoint));checkPoint = result.getCheckPoint();fireEvent(EventType.POLL_SUCCESS, result, null);} catch (Throwable e) {log.error("Error getting result from polling source", e);fireEvent(EventType.POLL_FAILURE, null, e);return;}try {populateProperties(result, config);} catch (Throwable e) {log.error("Error occured applying properties", e);}
复制代码

注意到,会调用source.poll方法,即PolledConfigurationSource的polled,我们实现的数据源接口,可以自定义数据源(jdbc,文件,scm等)

总结

在深入理解Archaius过程中,有一个绕不开的"障碍"便是Apache Commons Configuration,由于前者强依赖于后者进行配置管理。正所谓你对Apache Commons Configuration有多了解,决定了你对Netflix Archaius的认识有多深。

分享资源

资源分享
获取以上资源请访问开源项目 点击跳转

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/87038.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

资源限制类题目解法,看这一篇就够了!

算法拾遗三十七资源限制类题目 资源限制技巧汇总32位无符号整数的范围是0~4,294,967,295&#xff0c;现在有一个正好包含40亿个无符号整数的文件&#xff0c;可以使用最多1GB的内存&#xff0c;怎么找到出现次数最多的数32位无符号整数的范围是0~4294967295&#xff0c;现在又一…

人工智能讲师AIGC讲师叶梓:大模型这么火,我们在使用时应该关注些什么?-2

以下为叶老师讲义分享&#xff1a; P6-P9 一些考验大模型的经典问题: 1、鲁迅与周树人是同一个人吗?2、圆周率的最后一位3、蓝牙耳机坏了4、最新的&#xff1a;奶奶的睡前故事 关于事实的问答结果: 知识的时效性&#xff1a; 未完&#xff0c;下一章继续……

【Unity实战系列】Unity的下载安装以及汉化教程

君兮_的个人主页 即使走的再远&#xff0c;也勿忘启程时的初心 C/C 游戏开发 Hello,米娜桑们&#xff0c;这里是君兮_&#xff0c;怎么说呢&#xff0c;其实这才是我以后真正想写想做的东西&#xff0c;虽然才刚开始&#xff0c;但好歹&#xff0c;我总算是启程了。今天要分享…

数据库活动监控(DAM)

在当今数据驱动的世界中&#xff0c;组织在保护存储在数据库中的机密数据并确保其完整性方面面临着越来越多的挑战。数据库审计通过提供全面的数据库活动监控方法&#xff0c;在应对这些挑战方面发挥着至关重要的作用。 数据库活动监控&#xff08;Database Activity Monitori…

2023河南萌新联赛第(五)场:郑州轻工业大学-F 布鲁特佛斯

2023河南萌新联赛第&#xff08;五&#xff09;场&#xff1a;郑州轻工业大学-F 布鲁特佛斯 https://ac.nowcoder.com/acm/contest/62977/F 文章目录 2023河南萌新联赛第&#xff08;五&#xff09;场&#xff1a;郑州轻工业大学-F 布鲁特佛斯题意解题思路代码 题意 给定一个…

SpringCloudGateway配置跨域设置以及如何本地测试跨域

问题背景 有个服务A &#xff0c;自身对外提供服务&#xff0c;几个系统的前端页面也在调用&#xff0c;使用springboot 2.6.8开发的&#xff0c;自身因为有前端直接调用已经配置了跨域。 现在有网关服务&#xff0c;一部分前端通过网关访问服务A&#xff08;因为之前没有网关…

预测知识 | 预测技术流程及模型评价

预测知识 | 预测技术流程及模型评价 目录 预测知识 | 预测技术流程及模型评价技术流程模型评价参考资料 技术流程 1&#xff09;模型训练阶段&#xff1a;预测因素和结局&#xff0c;再加上预测模型进行模型拟合&#xff1b; 2&#xff09;预测阶段&#xff1a;将预测因素代入拟…

大数据课程I2——Kafka的架构

文章作者邮箱&#xff1a;yugongshiyesina.cn 地址&#xff1a;广东惠州 ▲ 本章节目的 ⚪ 掌握Kafka的架构&#xff1b; ⚪ 掌握Kafka的Topic与Partition&#xff1b; 一、Kafka核心概念及操作 1. producer生产者&#xff0c;可以是一个测试线程&#xff0c;也…

web-xss

目录 一、简介 二、xss的攻击方式 三、xss 常见标签语句 a标签 img标签 iframe标签 audio标签 video标签 svg标签 button标签 div标签 object标签 script标签 p标签 input标签 details标签 select标签 form标签 body标签 四、xss 常见绕过 编码绕过 1.htm…

(5)所有角色数据分析页面的构建-5

所有角色数据分析页面&#xff0c;包括一个时间轴柱状图、六个散点图、六个柱状图(每个属性角色的生命值/防御力/攻击力的max与min的对比)。 """绘图""" from pyecharts.charts import Timeline from find_type import FindType import pandas …

模仿火星科技 基于cesium+角度测量+高度测量+可编辑

1. 创建提示窗&#xff1a; 启动Cesium应用&#xff0c;地图场景将打开&#xff0c;欢迎您进入编辑模式。 在屏幕的一角&#xff0c;一个友好的提示窗将呈现&#xff0c;随着您的操作&#xff0c;它会为您提供有用的信息和指导。 2. 绘制面积&#xff1a; 轻轻点击鼠标左键&a…

iOS- git对单个或者多个文件权限设置,使用pre-commit hook 和shell脚本,拦截校验

前提&#xff1a;最近&#xff0c;由于团队代码规范和安全问题&#xff0c;有一些文件只能是指定用户才能修改。 对比&#xff1a;调查了一下资料&#xff0c;发现好多人都在使用pre-commit技术。于是&#xff0c;就朝着这个方向去研究。于是抽空写了脚本&#xff0c;在提交的…

【golang】数组和切片底层原理

数组类型的值&#xff08;以下简称数组&#xff09;的长度是固定的&#xff0c;而切片类型的值&#xff08;以下简称切片&#xff09;是可变长的。 数组的长度在声明它的时候就必须给定&#xff0c;并且之后不会再改变。可以说&#xff0c;数组的长度是其类型的一部分。比如&a…

【C语言】扫雷 小游戏

文章目录 一、游戏规则二、 代码逻辑三、游戏实现1. 游戏菜单设计2.设计雷区并随机布置雷(1) 设置雷区(2) 布置雷 3.排查雷 四、源码 一、游戏规则 1. 在9*9的小格子中&#xff0c;任意选取一个坐标&#xff08;格子&#xff09;&#xff0c;选择后发现&#xff0c;如果没点中雷…

Substack 如何在去中心化内容创作领域掀起波澜

面对数字内容广告化的困境&#xff0c;Substack回归做内容的初心&#xff0c;通过产品和平台双轮驱动&#xff0c;重塑一个去中心化的多元文化内容聚集地&#xff0c;实现了增长突破。其核心策略在于先使用简洁的创作工具赋能内容生产&#xff0c;进而通过平台的互动机制促进用…

图像处理技巧形态学滤波之膨胀操作

1. 引言 欢迎回来&#xff0c;我的图像处理爱好者们&#xff01;今天&#xff0c;让我们继续研究图像处理领域中的形态学计算。在本篇中&#xff0c;我们将重点介绍腐蚀操作的反向效果膨胀操作。 闲话少说&#xff0c;我们直接开始吧&#xff01; 2. 膨胀操作原理 膨胀操作…

【JVM】JVM中的分代回收

文章目录 分代收集算法什么是分代分代收集算法-工作机制MinorGC、 Mixed GC 、 FullGC的区别是什么 分代收集算法 什么是分代 在java8时&#xff0c;堆被分为了两份&#xff1a; 新生代和老年代【1&#xff1a;2】 其中&#xff1a; 对于新生代&#xff0c;内部又被分为了三…

Object.assign详解

一、Object.assign是什么&#xff1f; Object.assign( )方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。 二、用法 Object.assign(target, ...sources) 参数&#xff1a;target ——>目标对象 source ——>源对象 返回值&#xff1a;…

【springboot项目】在idea中启动报错合集

一、IDEA中报错 “Error running ‘Application‘: Command line is too long.“ 的解决办法 报错详情&#xff1a; Error running Application: Command line is too long.Shorten command line for Application or also for Spring Boot default configuration.报错原因&am…

Mybatis查询

返回实体类&#xff0c;必须指定返回类型&#xff0c; resultType不能省略&#xff0c;并且数据库字段名与实体类不一致会填充NULL&#xff0c;实体类我们一般都是驼峰&#xff0c;数据库字段一般都是下划线&#xff0c;所以在查询的时候可以起别名解决,属性填充本质上调用的是…