您好,登錄后才能下訂單哦!
Archaius 配置管理API,包含一系列配置管理API,提供動(dòng)態(tài)類型化屬性、線程安全配置操作、輪詢框架、回調(diào)機(jī)制等功能。
archaius是Netflix公司開(kāi)源項(xiàng)目之一,基于java的配置管理類庫(kù),主要用于多配置存儲(chǔ)的動(dòng)態(tài)獲取。主要功能是對(duì)apache common configuration類庫(kù)的擴(kuò)展。在云平臺(tái)開(kāi)發(fā)中可以將其用作分布式配置管理依賴構(gòu)件。同時(shí),它有如下一些特性:
動(dòng)態(tài)類型化屬性
高效和線程安全的配置操作
配置改變時(shí)的回調(diào)機(jī)制
輪詢框架
JMX,通過(guò)Jconsole檢查和調(diào)用操作屬性
組合配置
p_w_picpath.png
對(duì)于傳統(tǒng)的單體應(yīng)用,properties等配置文件可以解決配置問(wèn)題,同時(shí)也可以通過(guò)maven profile配置來(lái)區(qū)別各個(gè)環(huán)境,但在一個(gè)幾百上千節(jié)點(diǎn)的的微服務(wù)生態(tài)中,微服務(wù)采用多種語(yǔ)言開(kāi)發(fā),配置文件格式多樣,如何把每個(gè)微服務(wù)的配置文件都進(jìn)行更新,并且很多時(shí)候還需要重啟服務(wù),是一件無(wú)法忍受的事情。所以,對(duì)于微服務(wù)架構(gòu)而言,一個(gè)通用的配置中心是必不可少的。
新接口邏輯上線,老接口面臨遷移,開(kāi)發(fā)測(cè)試完成后,馬上要上線。但是接口調(diào)用發(fā)的研發(fā)同學(xué)對(duì)新接口的穩(wěn)定性、性能存在一定的質(zhì)疑,為了避免風(fēng)險(xiǎn),要求可以上線后緊急切換回老接口。這時(shí)候我們就需要一個(gè)手動(dòng)開(kāi)關(guān)。所以對(duì)于類似需求,一個(gè)通用的配置中心是必不可少的。
Archaius提供的DynamicIntProperty類可以在配置發(fā)生變化時(shí)動(dòng)態(tài)地獲取配置,并且不需要重啟應(yīng)用,而底層的配置存儲(chǔ),建議使用zookeeper進(jìn)行存儲(chǔ),Archaius作為客戶端的類庫(kù)使用。
<dependency> <groupId>com.netflix.archaius</groupId> <artifactId>archaius-core</artifactId> </dependency>
public class PropertiesConfiguration extends DynamicConfiguration { private static final Logger LOGGER = LoggerFactory.getLogger(PropertiesConfiguration.class); private static final int INITIAL_DELAY_MILLIS = 0; private static final int DELAY_MILLIS = 60 * 1000; private static final boolean IGNORE_DELETES_FROM_SOURCE = true; public PropertiesConfiguration(String confDir) { this(new String[]{confDir}); } public PropertiesConfiguration(final String...confDirs) { String[] propertiesPaths = Lists.newArrayList(Iterables.concat(Iterables.transform(Arrays.asList(confDirs), new Function<String, List<String>>() { @Nullable @Override public List<String> apply(String confDir) { Assert.isTrue(new File(confDir).isDirectory(), StringUtil.format("路徑[{}]無(wú)法查找[.properties]文件", confDirs)); String[] propertiesPaths = getPaths(confDir); if (ArrayUtils.isNotEmpty(propertiesPaths)) { return Lists.newArrayList(propertiesPaths); } else { return Lists.newArrayList(); } } }))).toArray(new String[0]); if (ArrayUtils.isNotEmpty(propertiesPaths)) { super.startPolling(new URLConfigurationSource(propertiesPaths), new FixedDelayPollingScheduler(INITIAL_DELAY_MILLIS, DELAY_MILLIS, IGNORE_DELETES_FROM_SOURCE)); } ConfigurationLog.successInit(PropertiesConfiguration.class, this.getProperties()); } private static String[] getPaths(String confDir) { try { URL configHome = new File(confDir).toURI().toURL(); List<String> urls = new ArrayList<String>(); for (String filename : FileUtil.scan(confDir, ".properties$")) { String url = configHome.toString() + filename; urls.add(url); } return urls.toArray(new String[urls.size()]); } catch (MalformedURLException e) { throw Throwables.propagate(e); } } }
public class SystemConfiguration extends ConcurrentMapConfiguration { private static final Logger LOGGER = LoggerFactory.getLogger(SystemConfiguration.class); public SystemConfiguration() { super(); this.loadProperties(System.getProperties()); ConfigurationLog.successInit(SystemConfiguration.class, this.getProperties()); } }
同理,可以使用zookeeper client 封裝一個(gè)基于zookeeper的 ConcurrentMapConfiguration
private static final ConcurrentCompositeConfiguration compositeConfig = new ConcurrentCompositeConfiguration(); public synchronized static void init() { Preconditions.checkState(! hadInit, StringUtil.format("[{}]只能加載一次!", ConfigAdapter.class.getSimpleName())); Preconditions.checkState(compositeConfig.getConfigurations().size() > 1, StringUtil.format("[{}]沒(méi)有加載任何配置", ConfigAdapter.class.getSimpleName())); if (! ConfigurationManager.isConfigurationInstalled()) { ConfigurationManager.install(compositeConfig); Preconditions.checkState(ConfigurationManager.isConfigurationInstalled(), StringUtil.format("[{}]加載失敗!", ConfigAdapter.class.getSimpleName())); } Iterable<String> configurationNames = Iterables.transform(compositeConfig.getConfigurations(), new Function<AbstractConfiguration, String>() { @Nullable @Override public String apply(AbstractConfiguration input) { return input.getClass().getSimpleName(); } }); ConfigurationLog.successInit(ConfigAdapter.class, getAll()); hadInit = true; }
public static DynamicBooleanProperty getDynamicBool(String key, boolean defaultValue) { return getFactory().getBooleanProperty(key, defaultValue); } private static DynamicPropertyFactory getFactory() { return DynamicPropertyFactory.getInstance(); }
在設(shè)置的時(shí)刻獲取配置,配置源不會(huì)隨著System#properties里面的配置更新而更新
更新配置方法不會(huì)更新實(shí)際的property文件,僅僅為更新內(nèi)存數(shù)據(jù),重啟后失效
微服務(wù)都從配置中心動(dòng)態(tài)的讀取配置信息,而配置中心又在從配置源同步配置,所以這里就很自然的出現(xiàn)了一個(gè)讀寫安全的問(wèn)題,好消息是Archaius已經(jīng)解決了這個(gè)問(wèn)題,Archaius是線程安全的,讀寫可以并發(fā)進(jìn)行。
個(gè)人介紹:
高廣超:多年一線互聯(lián)網(wǎng)研發(fā)與架構(gòu)設(shè)計(jì)經(jīng)驗(yàn),擅長(zhǎng)設(shè)計(jì)與落地高可用、高性能互聯(lián)網(wǎng)架構(gòu)。
本文首發(fā)在 高廣超的簡(jiǎn)書博客 轉(zhuǎn)載請(qǐng)注明!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。