Consul注销实例时候的问题

当我们在Spring Cloud应用中使用Consul来实现服务治理时,由于Consul不会自动将不可用的服务实例注销掉(deregister),这使得在实际使用过程中,可能因为一些操作失误、环境变更等原因让Consul中存在一些无效实例信息,而这些实例在Consul中会长期存在,并处于断开状态。它们虽然不会影响到正常的服务消费过程,但是它们会干扰我们的监控,所以我们可以实现一个清理接口,在确认故障实例可以清理的时候进行调用来将这些无效信息清理掉。

开始以为只要简单的调用注销接口就能轻松完成,但是实际实践的发现并非如此。因此,分享一下整个实现过程以及中间遇到的一些坑。

借鉴Spring Cloud Consul

在实现之初,先参考了Spring Cloud Consul在关闭程序时候实现的注销方法,具体如下:

public class ConsulLifecycle extends AbstractDiscoveryLifecycle {
...

private void deregister(String serviceId) {
if (!this.properties.isRegister()) {
return;
}
if (ttlScheduler != null) {
ttlScheduler.remove(serviceId);
}
log.info("Deregistering service with consul: {}", serviceId);
client.agentServiceDeregister(serviceId);
}

...
}

我们可以看到,当应用关闭时候的注销操作是通过调用client.agentServiceDeregister(serviceId)来实现的。其中client是consul-api的com.ecwid.consul.v1.ConsulClient实例。而agentServiceDeregister方法则是对/v1/agent/service/deregister/<serviceID> 接口的实现,该接口主要用来从Consul Agent中根据serviceId来注销实例。

以此实现为范例,于是开始的思路是这样的:

  • 先通过consulClient.getHealthServices(serviceId, false, null)根据serviceId来获取服务实例清单
  • 遍历实例清单中有不是PASSING状态的实例,就调用client.agentServiceDeregister(serviceId)来剔除

具体实现如下:

@RestController
public class ApiController {

@Autowired
private ConsulClient consulClient;

@RequestMapping(value = "/unregister/{id}", method = RequestMethod.POST)
public String unregisterServiceAll(@PathVariable String id) {
List<HealthService> response = consulClient.getHealthServices(id, false, null).getValue();
for(HealthService service : response) {
service.getChecks().forEach(check -> {
if(!check.getStatus().name().equals(Check.CheckStatus.PASSING.name())) {
logger.info("unregister : {}", check.getServiceId());
consulClient.agentServiceDeregister(check.getServiceId());
}
});
}
return null;
}
}

但是,在测试后发现该方法只能剔除同一个agent上的非PASSING实例。

Catalog误区

继续搜索了一下Consul的文档,发现了这个接口:/v1/catalog/deregister : Deregisters a node, service, or check。于是,尝试了用该接口来替换之前的consulClient.agentServiceDeregister(check.getServiceId());实现。

CatalogDeregistration catalogDeregistration = new CatalogDeregistration();
catalogDeregistration.setDatacenter("dc1");
catalogDeregistration.setNode(check.getNode());
catalogDeregistration.setServiceId(check.getServiceId());
catalogDeregistration.setCheckId(check.getCheckId());
consulClient.catalogDeregister(catalogDeregistration);

经过测试,该方法可以实现短暂的剔除,但是过一段时间之后这些被剔除的实例又都恢复回来了……也就是说这个接口完全没有什么卵用!

那么为什么会出现这种情况呢?我们可以在Github中找到这个维持了一年多的问题讨论:https://github.com/hashicorp/consul/issues/1188

整个讨论过程非常曲折,虽然当前该问题还依然在open状态,但是一些回复也基本够我们去理解它的原因了。比如下面这条评论:

You cannot deregister a service from the agent on a different node, service only exists on the agent you have registered with. It also exists in the catalog on all nodes, but that is not related to the agent itself. And to be honest I don’t understand why there is a catalog/deregister endpoint at all, in my opinion catalog should be a read-only service list.

从该评论中,我们可以知道一个重要信息:服务实例只能在注册的Agent上进行注销!另外,对于/v1/catalog/deregister接口,目前还是有不少争议的,因为根本没啥用。

最终实现

既然服务实例只能在注册的Agent上进行注销,那么我们的实现完全可以按照该思路来实现,方法很简单,只需要对一开始实现的内容做一些调整,依然使用client.agentServiceDeregister(serviceId)方法,只是我们需要调整client连接的agent必须是serviceId注册的agent。所以,最终的修改结果如下:

List<HealthService> response = consulClient.getHealthServices(id, false, null).getValue();
for(HealthService service : response) {
// 创建一个用来剔除无效实例的ConsulClient,连接到无效实例注册的agent
ConsulClient clearClient = new ConsulClient(service.getNode().getAddress(), 8500);
service.getChecks().forEach(check -> {
if(check.getStatus() != Check.CheckStatus.PASSING) {
logger.info("unregister : {}", check.getServiceId());
clearClient.agentServiceDeregister(check.getServiceId());
}
});
}

money.jpg

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

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

相关文章

刷榜思路少?顶级中文NLP比赛解题方法直播来了!

如何利用稠密向量表示学习方法提升模型在大规模中文段落数据中的检索能力&#xff1f;如何利用外部知识信息减少模型在智能音箱、语音助手等产品中因知识不足导致的“智商”掉线&#xff1f;深度学习在众多NLP任务取得惊艳表现&#xff0c;但如何缓解其黑盒属性造成的应用落地「…

LeetCode 1338. 数组大小减半

1. 题目 给你一个整数数组 arr。你可以从中选出一个整数集合&#xff0c;并删除这些整数在数组中的每次出现。 返回 至少 能删除数组中的一半整数的整数集合的最小大小。 示例 1&#xff1a; 输入&#xff1a;arr [3,3,3,3,5,5,5,2,2,7] 输出&#xff1a;2 解释&#xff1a…

技术动态 | 知识图谱的自监督学习与逻辑推理

分享嘉宾&#xff1a;胡子牛 UCLA PHD编辑整理&#xff1a;wei ai-fir出品平台&#xff1a;DataFunTalk导读&#xff1a;知识图谱是一种多关系的图结构&#xff0c;每个节点表示一个实体&#xff0c;每个边表示连接的两个节点之间的关系&#xff0c;可以将图谱中建模的节点和边…

为Spring Cloud Ribbon配置请求重试(Camden.SR2+)

当我们使用Spring Cloud Ribbon实现客户端负载均衡的时候&#xff0c;通常都会利用LoadBalanced来让RestTemplate具备客户端负载功能&#xff0c;从而实现面向服务名的接口访问&#xff08;原理可见《Spring Cloud源码分析&#xff08;二&#xff09;Ribbon》一文&#xff0c;如…

聊聊谷歌Pathways带来的想象力

声明&#xff1a;本文原创首发于公众号夕小瑶的卖萌屋&#xff0c;作者Severus--->【我是传送门】今年清明节&#xff0c;Google 搞了一点小动作&#xff0c;在 arxiv 上放出了自己的新工作&#xff0c;PaLM[1] &#xff08;PaLM: Scaling Language Modeling with Pathways&…

LeetCode 1339. 分裂二叉树的最大乘积(DP)

1. 题目 给你一棵二叉树&#xff0c;它的根为 root 。请你删除 1 条边&#xff0c;使二叉树分裂成两棵子树&#xff0c;且它们子树和的乘积尽可能大。 由于答案可能会很大&#xff0c;请你将结果对 10^9 7 取模后再返回。 示例 1&#xff1a; 输入&#xff1a;root [1,2…

大规模模型训练tricks集锦

文 | Connolly知乎大规模模型训练其实就是在和计算、存储和通信玩的过程&#xff0c;所以我列一下跟这些相关的文章。1. 大规模模型并行策略先来介绍一下几种经典的并行范式&#xff0c;以及他们对应的经典文章1.1 数据并行(Data parallelism)不同设备执行相同模型&#xff0c;…

Spring Cloud源码分析(二)Ribbon

断断续续看Ribbon的源码差不多也有7-8天了&#xff0c;总算告一段落。本文记录了这些天对源码的阅读过程与一些分析理解&#xff0c;如有不对还请指出。 友情提示&#xff1a;本文较长&#xff0c;请选择一个较为舒适的姿势来阅读 在之前介绍使用Ribbon进行服务消费的时候&…

LeetCode 1340. 跳跃游戏 V(DP)

1. 题目 给你一个整数数组 arr 和一个整数 d 。每一步你可以从下标 i 跳到&#xff1a; i x &#xff0c;其中 i x < arr.length 且 0 < x < d 。i - x &#xff0c;其中 i - x > 0 且 0 < x < d 。 除此以外&#xff0c;你从下标 i 跳到下标 j 需要满足…

论文浅尝 | TKGR with Low-rank and Model-agnostic Representations

笔记整理&#xff1a;李行&#xff0c;天津大学硕士链接&#xff1a;https://arxiv.org/pdf/2204.04783v1.pdf动机现有MKGC方法中的知识转移效率低下&#xff0c;因为它们分别对每个KG进行编码并通过强制对齐的实体共享相同的嵌入来转移知识。亮点本文的亮点主要包括&#xff1…

ICLR’22 最佳脑洞奖提名:《GPT 如何进行布朗运动?》

文 | 付瑶编 | 小轶今天给大家介绍一篇斯坦福大学的 ICLR22 论文。该文在 OpenReview 中获得了8/8/8/8的高分。在写这篇推送之前&#xff0c;小编身边有多位朋友都私下向我推荐过这篇文章。虽然这几位朋友所研究的任务并不相同&#xff0c;却都认为这篇文章“极具启发性&#x…

条件随机场(Conditional Random Field,CRF)

文章目录1. 概率无向图模型1.1 模型定义1.2 概率无向图模型的因子分解2. 条件随机场的定义与形成2.1 条件随机场的定义2.2 条件随机场的参数化形式例题2.3 条件随机场的简化形式2.4 条件随机场的矩阵形式例题3. 条件随机场的概率计算问题3.1 前向-后向算法3.2 概率计算3.3 期望…

Spring Cloud构建微服务架构(七)消息总线

先回顾一下&#xff0c;在之前的Spring Cloud Config的介绍中&#xff0c;我们还留了一个悬念&#xff1a;如何实现对配置信息的实时更新。虽然&#xff0c;我们已经能够通过/refresh接口和Git仓库的Web Hook来实现Git仓库中的内容修改触发应用程序的属性更新。但是&#xff0c…

2022中国最有钱大学排名出炉!北大只能排第三

文 | 大勇源 | 抓码计算机考研4月21日&#xff0c;教育部直属高校、工信部直属高校陆续在其信息公开网公布了2022年部门预算&#xff0c;高绩对各高校2022年预算数据进行了整理&#xff0c;从中可以一窥国内重点高校的经费情况。中国有各类型、各层次高校2000余所&#xff0c;就…

图谱实战 | 百度基于异构互联知识图谱的多模内容创作技术

分享嘉宾&#xff1a;卞东海 百度 高级研发工程师编辑整理&#xff1a;蒋郭鑫 河海大学出品平台&#xff1a;DataFunTalk导读&#xff1a;由于大数据时代的发展&#xff0c;知识呈指数级增长&#xff0c;而知识图谱技术又在近年来逐步火热&#xff0c;因此诞生了利用知识图谱技…

Spring Cloud构建微服务架构(四)分布式配置中心

Spring Cloud Config为服务端和客户端提供了分布式系统的外部化配置支持。配置服务器为各应用的所有环境提供了一个中心化的外部配置。它实现了对服务端和客户端对Spring Environment和PropertySource抽象的映射&#xff0c;所以它除了适用于Spring构建的应用程序&#xff0c;也…

华尔街投资人因股价暴跌起诉阿里巴巴,马云为起诉对象?

文 | 曹小灵知乎www.zhihu.com/question/530087383/answer/2458458738前几天发生了一个比较有意思的事情&#xff0c;直接上图&#xff1a;这新闻把我看乐了。这中国科技公司在美国股价下跌的原因&#xff0c;美国人自己不清楚么。2020年就开始闹&#xff0c;2021年落地的《外国…

Spring Cloud源码分析(一)Eureka

看过之前文章的朋友们&#xff0c;相信已经对Eureka的运行机制已经有了一定的了解。为了更深入的理解它的运作和配置&#xff0c;下面我们结合源码来分别看看服务端和客户端的通信行为是如何实现的。另外写这篇文章&#xff0c;还有一个目的&#xff0c;还是希望鼓励大家能够学…

手把手教你写出令人窒息的烂代码

源 | 机器之心在 GitHub 上有一个新项目&#xff0c;它描述了「最佳垃圾代码」的十九条关键准则。从变量命名到注释编写。这些准则将指导你写出最亮眼的烂代码。为了保持与原 GitHub 项目一致的风格&#xff0c;下文没有进行转换。读者们可以以相反的角度来理解所有观点&#x…

LeetCode 85. 最大矩形(DP/单调递增栈,难)

文章目录1. 题目2. 解题2.1 DP2.2 单调递增栈1. 题目 给定一个仅包含 0 和 1 的二维二进制矩阵&#xff0c;找出只包含 1 的最大矩形&#xff0c;并返回其面积。 示例: 输入: [["1","0","1","0","0"],["1",&quo…