Nacos源碼解析(1)-- ConfigService 客戶端

NacosFactory (獲取工廠的統(tǒng)一入口)

// 通過(guò)配置類獲取?ConfigService

public static ConfigService createConfigService(Properties properties) throws NacosException {

????return ConfigFactory.createConfigService(properties);

}

// 通過(guò)服務(wù)端地址獲取?ConfigService

public static ConfigService createConfigService(String serverAddr) throws NacosException {?

? ?return ConfigFactory.createConfigService(serverAddr);

}

com.alibaba.nacos.api.NacosFactory 工廠類?

提供獲取ConfigFactory晌坤、NamingFactory厨诸、NamingMaintainFactory工廠的靜態(tài)方法。

設(shè)計(jì)模式:典型的 工廠模式 應(yīng)用

ConfigService (分布式配置接口)


ConfigService UML

// 根據(jù)dataid自赔、group獲取配置信息

String getConfig(String dataId, String group, long timeoutMs) throws NacosException;

String getConfigAndSignListener(String dataId, String group, long timeoutMs, Listener listener) throws NacosException;

// 針對(duì)dataid、group增加監(jiān)聽(tīng)器

void addListener(String dataId, String group, Listener listener) throws NacosException;

// 發(fā)布配置

boolean publishConfig(String dataId, String group, String content) throws NacosException;

// 刪除配置

boolean removeConfig(String dataId, String group) throws NacosException;

// 刪除監(jiān)聽(tīng)器

void removeListener(String dataId, String group, Listener listener);

// 服務(wù)狀態(tài)

String getServerStatus();

// 關(guān)閉回收狀態(tài)

void shutDown() throws NacosException;

com.alibaba.nacos.api.config.ConfigService?

提供了一些針對(duì)配置的CRUD操作以及監(jiān)聽(tīng)配置的變更的能力

NacosConfigService (分布式配置接口實(shí)現(xiàn))

// http 代理類 根據(jù)名字就可以知道這個(gè)主要用于http協(xié)議對(duì)外交互

private final HttpAgent agent;

// long polling?

private final ClientWorker worker;

private String namespace;

// 關(guān)于配置的過(guò)濾器管理類?

private final ConfigFilterChainManager configFilterChainManager = new ConfigFilterChainManager();


NacosConfigService

HttpAgent (http 代理類)

HttpAgent UML

void start() throws NacosException;

HttpRestResult<String> httpGet(String path, Map<String, String> headers, Map<String, String> paramValues, String encoding, long readTimeoutMs) throws Exception;

HttpRestResult<String> httpPost(String path, Map<String, String> headers, Map<String, String> paramValues, String encoding, long readTimeoutMs) throws Exception;

HttpRestResult<String> httpDelete(String path, Map<String, String> headers, Map<String, String> paramValues, String encoding, long readTimeoutMs) throws Exception;

MetricsHttpAgent

public class MetricsHttpAgent implements HttpAgent {

? ? // 持有真正發(fā)起請(qǐng)求的 httpAgent

????private final HttpAgent httpAgent;

????public HttpRestResult<String> httpGet(String path, Map<String, String> headers, Map<String, String> paramValues, ????????String encode, long readTimeoutMs) throws Exception {

????????? ??Histogram.Timer timer = MetricsMonitor.getConfigRequestMonitor("GET", path, "NA");

????????????HttpRestResult<String> result;? ??????????

????????????try {? ??????????

? ? ? ? ? ? ? ? result = httpAgent.httpGet(path, headers, paramValues, encode, readTimeoutMs);

? ??????????} catch (IOException e) {

? ??????????????throw e;

? ??????????} finally {}

? ??????????return result;

? ? }

}


ServerHttpAgent?

public class ServerHttpAgent implements HttpAgent {

? ? // 核心類:nacosRestTemplate

? ? // 和springboot RestTemplate差不多 使用http協(xié)議對(duì)外交互

?????private static final NacosRestTemplate NACOS_RESTTEMPLATE = ConfigHttpClientManager.getInstance() .getNacosRestTemplate();

? ? // 針對(duì)?nacosRestTemplate 進(jìn)行安全配置

????private SecurityProxy securityProxy;

? ? // 調(diào)度器

? ??private ScheduledExecutorService executorService;

}

ServerHttpAgent

ServerListManager

public class ServerListManager implements Closeable {

? ??volatile List<String> serverUrls = new ArrayList<String>();

}

維護(hù)多個(gè)服務(wù)端地址

SecurityProxy

public class SecurityProxy {

? ??private String accessToken;

? ??private long tokenTtl;

? ??private long lastRefreshTime;

? ??public boolean login(List<String> servers) {

? ??????if ((System.currentTimeMillis() - lastRefreshTime) < TimeUnit.SECONDS .toMillis(tokenTtl - tokenRefreshWindow))? ? ? ? ? {

? ? ? ? ? ??return true;

? ? ? ? }

? ??????for (String server : servers) {

? ??????????if (login(server)) {

????????????????lastRefreshTime = System.currentTimeMillis();? ??????????

? ??????????????return true;

? ? ? ? ? ? }

? ? ? ? }

? ??????return false;

? ? }

}

SecurityProxy 會(huì)調(diào)用服務(wù)端進(jìn)行登錄,獲取到的accessToken和有效時(shí)間進(jìn)行儲(chǔ)存。如果失效了會(huì)重新發(fā)起登錄伦糯。

NacosRestTemplate

public class NacosRestTemplate extends AbstractNacosRestTemplate {

? ? // 具體的http client?

? ? // httpclient有兩種實(shí)現(xiàn) 1:使用Apache HttpClient? 2:使用JDK HttpUrlConnection

? ??private final HttpClientRequest requestClient;

? ? // http調(diào)用 攔截器 可以根據(jù)需求 定制自己的攔截器

? ??private final List<HttpClientRequestInterceptor> interceptors = new ArrayList<HttpClientRequestInterceptor>();

}


NacosRestTemplate UML


HttpClientRequest?

public interface HttpClientRequest extends Closeable {

? ? // 執(zhí)行請(qǐng)求并且返回結(jié)果

????HttpClientResponse execute(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity) throws Exception;

}

http調(diào)用統(tǒng)一接口

DefaultHttpClientRequest

public class DefaultHttpClientRequest implements HttpClientRequest {

? ? //?implementation that uses apache http client to execute streaming requests.

? ? // 使用 appche http client 實(shí)現(xiàn)

????private final CloseableHttpClient client;

}

HttpClientRequest 默認(rèn)實(shí)現(xiàn)

JdkHttpClientRequest

public class JdkHttpClientRequest implements HttpClientRequest {

? ??private HttpClientConfig httpClientConfig;

? ??public HttpClientResponse execute(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity){

? ? ? ? ………………

? ??????HttpURLConnection conn = (HttpURLConnection) uri.toURL().openConnection();

? ? ? ? ………………

? ? }

}

使用java? net包實(shí)現(xiàn)

InterceptingHttpClientRequest

public class InterceptingHttpClientRequest implements HttpClientRequest {

? ? // 持有httpClientRequest? 進(jìn)行包裝
? ? private final HttpClientRequest httpClientRequest;

? ? private final Iterator<HttpClientRequestInterceptor> interceptors;

? ??public HttpClientResponse execute(URI uri, String httpMethod, RequestHttpEntity requestHttpEntity){

? ??????while (interceptors.hasNext()) {

? ??????????HttpClientRequestInterceptor nextInterceptor = interceptors.next();

? ??????????if (nextInterceptor.isIntercept(uri, httpMethod, requestHttpEntity)) {

? ??????????????return nextInterceptor.intercept();

? ? ? ? ? ? }

? ??????????return httpClientRequest.execute(uri, httpMethod, requestHttpEntity);

? ? }

}

包裝了httpClientRequest,在執(zhí)行httpClientRequest.execute 增加了攔截邏輯嗽元。

ClientWorker

public class ClientWorker implements Closeable {

? ? …………

? ? // 緩存了 配置信息 key = dataId+GroupId

? ??private final AtomicReference<Map<String, CacheData>> cacheMap = new AtomicReference<Map<String, CacheData>>( new HashMap<String, CacheData>());

? ? …………

}


ClientWorker

checkConfigInfo 會(huì)根據(jù)cacheMap.size 進(jìn)行維護(hù)

ConfigService.getConfig 偽代碼

// 校驗(yàn)參數(shù) + 默認(rèn)配置

// 優(yōu)先使用本地配置??

String content = LocalConfigInfoProcessor.getFailover(agent.getName(), dataId, group, tenant);

if(content != null) return?content;

// 從服務(wù)端獲取配置信息 && 如果成功保存快照版本

try{

????String[] ct = worker.getServerConfig(dataId, group, tenant, timeoutMs);

} …………

// 如果從服務(wù)端獲取異常 直接獲取本地快照版本返回

content = LocalConfigInfoProcessor.getSnapshot(agent.getName(), dataId, group, tenant);

return?content;


涉及到的模式:

1舔株、工廠模式?NacosFactory 典型的簡(jiǎn)單工廠

2、模板模式 NacosRestTemplate

3还棱、裝飾器模式?MetricsHttpAgent

以上就是針對(duì)ConfigService客戶端的分析 载慈,下一章進(jìn)行服務(wù)端分析。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末珍手,一起剝皮案震驚了整個(gè)濱河市办铡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌琳要,老刑警劉巖寡具,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異稚补,居然都是意外死亡童叠,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)厦坛,“玉大人五垮,你說(shuō)我怎么就攤上這事《沤眨” “怎么了放仗?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)撬碟。 經(jīng)常有香客問(wèn)我诞挨,道長(zhǎng),這世上最難降的妖魔是什么呢蛤? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任惶傻,我火速辦了婚禮,結(jié)果婚禮上其障,老公的妹妹穿的比我還像新娘银室。我一直安慰自己,他們只是感情好静秆,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布粮揉。 她就那樣靜靜地躺著巡李,像睡著了一般抚笔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上侨拦,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天殊橙,我揣著相機(jī)與錄音,去河邊找鬼狱从。 笑死膨蛮,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的季研。 我是一名探鬼主播敞葛,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼与涡!你這毒婦竟也來(lái)了惹谐?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤驼卖,失蹤者是張志新(化名)和其女友劉穎氨肌,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體酌畜,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡怎囚,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了桥胞。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片恳守。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡考婴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出井誉,到底是詐尸還是另有隱情蕉扮,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布颗圣,位于F島的核電站喳钟,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏在岂。R本人自食惡果不足惜奔则,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蔽午。 院中可真熱鬧易茬,春花似錦、人聲如沸及老。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)骄恶。三九已至食铐,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間僧鲁,已是汗流浹背虐呻。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留寞秃,地道東北人斟叼。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像春寿,于是被迫代替她去往敵國(guó)和親朗涩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355