Apollo客户端配置获取深度解析_apollo could not find config for namespace - appid

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

try {

TimeUnit.SECONDS.sleep(5);

} catch (InterruptedException e) {

}

}

String appId = m_configUtil.getAppId();

String cluster = m_configUtil.getCluster();

String dataCenter = m_configUtil.getDataCenter();

String secret = m_configUtil.getAccessKeySecret();

Tracer.logEvent(“Apollo.Client.ConfigMeta”, STRING_JOINER.join(appId, cluster, m_namespace));

int maxRetries = m_configNeedForceRefresh.get() ? 2 : 1;

long onErrorSleepTime = 0; // 0 means no sleep

Throwable exception = null;

List configServices = getConfigServices();

String url = null;

retryLoopLabel:

for (int i = 0; i < maxRetries; i++) {

List randomConfigServices = Lists.newLinkedList(configServices);

Collections.shuffle(randomConfigServices);

//Access the server which notifies the client first

if (m_longPollServiceDto.get() != null) {

randomConfigServices.add(0, m_longPollServiceDto.getAndSet(null));

}

for (ServiceDTO configService : randomConfigServices) {

if (onErrorSleepTime > 0) {

logger.warn( “Load config failed, will retry in {} {}. appId: {}, cluster: {}, namespaces: {}”,onErrorSleepTime, m_configUtil.getOnErrorRetryIntervalTimeUnit(), appId, cluster, m_namespace);

try {

m_configUtil.getOnErrorRetryIntervalTimeUnit().sleep(onErrorSleepTime);

} catch (InterruptedException e) {

//ignore

}

}

url = assembleQueryConfigUrl(configService.getHomepageUrl(), appId, cluster, m_namespace, dataCenter, m_remoteMessages.get(), m_configCache.get());

logger.debug(“Loading config from {}”, url);

HttpRequest request = new HttpRequest(url);

if (!StringUtils.isBlank(secret)) {

Map<String, String> headers = Signature.buildHttpHeaders(url, appId, secret);

request.setHeaders(headers);

}

Transaction transaction = Tracer.newTransaction(“Apollo.ConfigService”, “queryConfig”);

transaction.addData(“Url”, url);

try {

HttpResponse response = m_httpUtil.doGet(request, ApolloConfig.class);

m_configNeedForceRefresh.set(false);

m_loadConfigFailSchedulePolicy.success();

transaction.addData(“StatusCode”, response.getStatusCode());

transaction.setStatus(Transaction.SUCCESS);

if (response.getStatusCode() == 304) {

logger.debug(“Config server responds with 304 HTTP status code.”);

return m_configCache.get();

}

ApolloConfig result = response.getBody();

logger.debug(“Loaded config for {}: {}”, m_namespace, result);

return result;

} catch (ApolloConfigStatusCodeException ex) {

ApolloConfigStatusCodeException statusCodeException = ex;

//config not found

if (ex.getStatusCode() == 404) {

String message = String.format(

"Could not find config for namespace - appId: %s, cluster: %s, namespace: %s, " +

“please check whether the configs are released in Apollo!”,

appId, cluster, m_namespace);

statusCodeException = new ApolloConfigStatusCodeException(ex.getStatusCode(),

message);

}

Tracer.logEvent(“ApolloConfigException”, ExceptionUtil.getDetailMessage(statusCodeException));

transaction.setStatus(statusCodeException);

exception = statusCodeException;

if(ex.getStatusCode() == 404) {

break retryLoopLabel;

}

} catch (Throwable ex) {

Tracer.logEvent(“ApolloConfigException”, ExceptionUtil.getDetailMessage(ex));

transaction.setStatus(ex);

exception = ex;

} finally {

transaction.complete();

}

// if force refresh, do normal sleep, if normal config load, do exponential sleep

onErrorSleepTime = m_configNeedForceRefresh.get() ? m_configUtil.getOnErrorRetryInterval() :

m_loadConfigFailSchedulePolicy.fail();

}

}

String message = String.format(

“Load Apollo Config failed - appId: %s, cluster: %s, namespace: %s, url: %s”,

appId, cluster, m_namespace, url);

throw new ApolloConfigException(message, exception);

}

配置实时生效的单靠短连接肯定是不能完成的,需要和长连接配合完成。下面将介绍长连接实现原理及长连接和短连接如何配合完成配置实时生效。

    1. 长连接实现原理

长连接,顾名思义就是客户端与服务端建立连接后不断开,一个客户端就是一个长连接,,而不是一个Namespace一个长连接,如果想要实现动态关闭某个appId长连接,是可以通过修改下面代码实现,同时通过修改短连接请求,添加开与关标志位实现。Apollo配置中心长连接实现逻辑是具体是什么呢?

      • 1.3.1. 客户端主要逻辑

private void doLongPollingRefresh(String appId, String cluster, String ataCenter, String secret) {

final Random random = new Random();

ServiceDTO lastServiceDto = null;

//循环发生请求,实现客户端长连接

while (!m_longPollingStopped.get() && !Thread.currentThread().isInterrupted()) {

if (!m_longPollRateLimiter.tryAcquire(5, TimeUnit.SECONDS)) {

//wait at most 5 seconds

try {

TimeUnit.SECONDS.sleep(5);

} catch (InterruptedException e) {

}

}

Transaction transaction = Tracer.newTransaction(“Apollo.ConfigService”, “pollNotification”);

String url = null;

try {

if (lastServiceDto == null) {

List configServices = getConfigServices();

//随机获取一个可用的节点

lastServiceDto =configServices.get(random.nextInt(configServices.size()));

}

//拼接请求URL

url = assembleLongPollRefreshUrl(lastServiceDto.getHomepageUrl(), appId, cluster, dataCenter, m_notifications);

logger.debug(“Long polling from {}”, url);

HttpRequest request = new HttpRequest(url);

request.setReadTimeout(LONG_POLLING_READ_TIMEOUT);

if (!StringUtils.isBlank(secret)) {

Map<String, String> headers = Signature.buildHttpHeaders(url, appId, secret);

request.setHeaders(headers);

}

transaction.addData(“Url”, url);

//请求发送

final HttpResponse<List> response =

m_httpUtil.doGet(request, m_responseType);

logger.debug(“Long polling response: {}, url: {}”, response.getStatusCode(), url);

if (response.getStatusCode() == 200 && response.getBody() != null) {

updateNotifications(response.getBody());

updateRemoteNotifications(response.getBody());

transaction.addData(“Result”, response.getBody().toString());

notify(lastServiceDto, response.getBody());

}

//try to load balance

//304: NOT_MODIFIED(304, “Not Modified”),

//random.nextBoolean:伪均匀分布的布尔值,保证长连接均匀分布在各节点上

if (response.getStatusCode() == 304 && random.nextBoolean()) {

lastServiceDto = null;

}

m_longPollFailSchedulePolicyInSecond.success();

transaction.addData(“StatusCode”, response.getStatusCode());

transaction.setStatus(Transaction.SUCCESS);

} catch (Throwable ex) {

lastServiceDto = null;

Tracer.logEvent(“ApolloConfigException”, ExceptionUtil.getDetailMessage(ex));

transaction.setStatus(ex);

long sleepTimeInSecond = m_longPollFailSchedulePolicyInSecond.fail();

logger.warn(

“Long polling failed, will retry in {} seconds. appId: {}, cluster: {}, namespaces: {}, long polling url: {}, reason: {}”,

sleepTimeInSecond, appId, cluster, assembleNamespaces(), url, ExceptionUtil.getDetailMessage(ex));

try {

TimeUnit.SECONDS.sleep(sleepTimeInSecond);

} catch (InterruptedException ie) {

//ignore

}

} finally {

transaction.complete();

}

}

}

img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

p(sleepTimeInSecond);

} catch (InterruptedException ie) {

//ignore

}

} finally {

transaction.complete();

}

}

}

[外链图片转存中…(img-Bfcbi5DR-1715799165899)]
[外链图片转存中…(img-cuSkAqpn-1715799165900)]
[外链图片转存中…(img-uFekyMUN-1715799165900)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值