Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Java面试系列之Nacos健康检查机制

Java面试系列之Nacos健康检查机制

作者头像
35岁程序员那些事
发布于 2022-09-23 10:01:23
发布于 2022-09-23 10:01:23
1.2K00
代码可运行
举报
文章被收录于专栏:架构随笔录架构随笔录
运行总次数:0
代码可运行

Nacos是阿里巴巴开源的注册中心配置中心的技术解决方案,目前有很多公司都在使用它,并落地到自己的业务产品中,好吧你们知不知道它是支持健康检查机制的呢?下面我将带着大家一起来理解它的健康检查机制的核心原理及业务背景。

为什么Nacos要支持健康检查机制

Nacos是一个注册中心,为什么它要支持健康检查机制呢?这主要是因为注册中心不应该仅仅提供服务注册和发现功能,还应该保证对服务可用性进行监测,对不健康的服务和过期的进行标识或剔除,维护实例的生命周期,以保证客户端尽可能的查询到可用的服务列表。因此本文将详细介绍 Nacos 注册中心中的健康检查机制。

Nacos中的实例分类

在搞清楚Nacos的健康检查机制之前,一定清楚Nacos中的实例分类,Nacos 提供了两 种服务类型供用户注册实例时选择,分为临时实例和永久实例。

临时实例只是临时存在于注册中心中,会在服务下线或不可用时被注册中心剔除,临时实例会与注 册中心保持心跳,注册中心会在一段时间没有收到来自客户端的心跳后会将实例设置为不健康,然 后在一段时间后进行剔除。

永久实例在被删除之前会永久的存在于注册中心,且有可能并不知道注册中心存在,不会主动向注 册中心上报心跳,那么这个时候就需要注册中心主动进行探活。

什么是临时实例的健康检查机制?

在 Nacos 中,用户可以通过两种方式进行临时实例的注册,通过 Nacos 的 OpenAPI 进行服务注 册或通过 Nacos 提供的 SDK 进行服务注册。

OpenAPI 的注册方式实际是用户根据自身需求调用 Http 接口对服务进行注册,然后通过 Http 接 口发送心跳到注册中心。在注册服务的同时会注册一个全局的客户端心跳检测的任务。在服务一段 时间没有收到来自客户端的心跳后,该任务会将其标记为不健康,如果在间隔的时间内还未收到心 跳,那么该任务会将其剔除。

SDK 的注册方式实际是通过 RPC 与注册中心保持连接(Nacos 2.x 版本中,旧版的还是仍然通过 OpenAPI 的方式),客户端会定时的通过 RPC 连接向 Nacos 注册中心发送心跳,保持连接的存 活。如果客户端和注册中心的连接断开,那么注册中心会主动剔除该 client 所注册的服务,达到下 线的效果。同时 Nacos 注册中心还会在注册中心启动时,注册一个过期客户端清除的定时任务, 用于删除那些健康状态超过一段时间的客户端。

从上面的特点我们可以发现,对于不同类型的使用方式,Nacos 对于健康检查的特点实际都是相同 的,都是由客户端向注册中心发送心跳,注册中心会在连接断开或是心跳过期后将不健康的实例移除。

(1)我们可以看一下Nacos2.1.0中的临时实例的健康检查机制的关键代码,下面是SDK健康检查机制的入口。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//代码来自于NamingHttpClientProxy类的registerService()方法
@Override
    public void registerService(String serviceName, String groupName, Instance instance) throws NacosException {
        NAMING_LOGGER.info("[REGISTER-SERVICE] {} registering service {} with instance: {}", namespaceId, 
        serviceName,instance);
        String groupedServiceName = NamingUtils.getGroupedName(serviceName, groupName);
        //如果是临时实例,则开启临时实例的健康检查机制
        if (instance.isEphemeral()) {
            //构造当前需要注册的服务实例的心跳信息,诸如服务名称、IP地址信息、端口号、集群名称、服务实例权重等
            BeatInfo beatInfo = beatReactor.buildBeatInfo(groupedServiceName, instance);
            //开启一个定时任务,定时的向Nacos Server发送心跳包,具体可以查阅BeatReactor类
            beatReactor.addBeatInfo(groupedServiceName, beatInfo);
        }
        //构造服务注册的请求参数
        final Map<String, String> params = new HashMap<String, String>(32);
        params.put(CommonParams.NAMESPACE_ID, namespaceId);
        params.put(CommonParams.SERVICE_NAME, groupedServiceName);
        params.put(CommonParams.GROUP_NAME, groupName);
        params.put(CommonParams.CLUSTER_NAME, instance.getClusterName());
        params.put(IP_PARAM, instance.getIp());
        params.put(PORT_PARAM, String.valueOf(instance.getPort()));
        params.put(WEIGHT_PARAM, String.valueOf(instance.getWeight()));
        params.put(REGISTER_ENABLE_PARAM, String.valueOf(instance.isEnabled()));
        params.put(HEALTHY_PARAM, String.valueOf(instance.isHealthy()));
        params.put(EPHEMERAL_PARAM, String.valueOf(instance.isEphemeral()));
        params.put(META_PARAM, JacksonUtils.toJson(instance.getMetadata()));
        //发起服务注册的请求
        reqApi(UtilAndComs.nacosUrlInstance, params, HttpMethod.POST);
        
    }

(2)生产健康检查心跳包的出口如下。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//源码来自于NamingHttpClientProxy类的sendBeat()方法
public JsonNode sendBeat(BeatInfo beatInfo, boolean lightBeatEnabled) throws NacosException {
        if (NAMING_LOGGER.isDebugEnabled()) {
            NAMING_LOGGER.debug("[BEAT] {} sending beat to server: {}", namespaceId, beatInfo.toString());
        }
        Map<String, String> params = new HashMap<String, String>(16);
        Map<String, String> bodyMap = new HashMap<String, String>(2);
        if (!lightBeatEnabled) {
            bodyMap.put("beat", JacksonUtils.toJson(beatInfo));
        }
        params.put(CommonParams.NAMESPACE_ID, namespaceId);
        params.put(CommonParams.SERVICE_NAME, beatInfo.getServiceName());
        params.put(CommonParams.CLUSTER_NAME, beatInfo.getCluster());
        params.put(IP_PARAM, beatInfo.getIp());
        params.put(PORT_PARAM, String.valueOf(beatInfo.getPort()));
        //发送健康检查的心跳包
        String result = reqApi(UtilAndComs.nacosUrlBase + "/instance/beat", params, bodyMap, HttpMethod.PUT);
        return JacksonUtils.toObj(result);
    }

定时器默认的周期为5s,业务服务可以在发起服务注册时,主动的调整健康检查心跳的周期,具体代码实现如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//源码来自于Nacos的Instance类
public static final long DEFAULT_HEART_BEAT_INTERVAL = TimeUnit.SECONDS.toMillis(5);

(3)Nacos Server用Open API去处理客户端发送的心跳包,部分代码实现如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@CanDistro
    @PutMapping("/beat")
    @Secured(action = ActionTypes.WRITE)
    public ObjectNode beat(HttpServletRequest request) throws Exception {
        ...
        //处理客户端的健康检查的心跳请求,设置服务实例为健康的状态
        int resultCode = getInstanceOperator().handleBeat(namespaceId, serviceName,ip, port, clusterName,    
            clientBeat, builder);
        result.put(CommonParams.CODE, resultCode);
        result.put(SwitchEntry.CLIENT_BEAT_INTERVAL,
                getInstanceOperator().getHeartBeatInterval(namespaceId, serviceName, ip, port, clusterName));
        result.put(SwitchEntry.LIGHT_BEAT_ENABLED, switchDomain.isLightBeatEnabled());
        return result;
    }

大家如果感兴趣可以查阅InstanceController类的beat()方法。

什么是永久实例健康检查机制?

Nacos 中使用 SDK 对于永久实例的注册实际也是使用 OpenAPI 的方式进行注册,这样可以保证即使是客户端下线后也不会影响永久实例的健康检查。

对于永久实例的的监看检查,Nacos 采用的是注册中心探测机制,注册中心会在永久服务初始化时 根据客户端选择的协议类型注册探活的定时任务。Nacos 现在内置提供了三种探测的协议,即 Http、TCP 以及 MySQL 。一般而言 Http 和 TCP 已经可以涵盖绝大多数的健康检查场景。MySQL 主要用于特殊的业务场景,例如数据库的主备需要通过服务名对外提供访问,需要确定当前 访问数据库是否为主库时,那么我们此时的健康检查接口,是一个检查数据库是否为主库的 MySQL命令。

由于持久化服务的实例的在被主动删除前一直存在的特性,探活的定时任务会不断探测服务的健康状态,并且将无法探测成功的实例标记为不健康。但是有些时候会有这样的场景,有些服务不希望去校验其健康状态,Nacos 也是提供了对应的白名单配置,用户可以将服务配置到该白名单,那么 Nacos 会放弃对其进行健康检查,实例的健康状态也始终为用户传入的健康状态。

(1)Nacos Server会启动一个定时任务,定时的执行任务HealthCheckTask,并调用永久实例健康检查机制的处理类HealthCheckProcessorDelegate去处理健康检查。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Component("healthCheckDelegate")
public class HealthCheckProcessorDelegate implements HealthCheckProcessor {
    
    private Map<String, HealthCheckProcessor> healthCheckProcessorMap = new HashMap<>();
    
    public HealthCheckProcessorDelegate(HealthCheckExtendProvider provider) {
        provider.init();
    }
    
    @Autowired
    public void addProcessor(Collection<HealthCheckProcessor> processors) {
        healthCheckProcessorMap.putAll(processors.stream().filter(processor -> processor.getType() != null)
                .collect(Collectors.toMap(HealthCheckProcessor::getType, processor -> processor)));
    }
    
    @Override
    public void process(HealthCheckTask task) {
        //处理健康检查
        String type = task.getCluster().getHealthChecker().getType();
        HealthCheckProcessor processor = healthCheckProcessorMap.get(type);
        if (processor == null) {
            processor = healthCheckProcessorMap.get(NoneHealthCheckProcessor.TYPE);
        }
        
        processor.process(task);
    }
    
    @Override
    public String getType() {
        return null;
    }
}

(2)Nacos Server服端的健康检查可以分为多种类型,比如MysqlHealthCheckProcessor、HttpHealthCheckProcessor和TcpSuperSenseProcessor等。

(3)HttpHealthCheckProcessor为Nacos支持的基于HTTP的永久实例健康检查机制的处理类,TcpSuperSenseProcessor为Nacos支持的基于TCP的永久实例健康检查机制的处理类,MysqlHealthCheckProcessor为Nacos支持的基于数据库健康检查的永久实例健康检查机制的处理类。

总之Nacos Server支持HTTP、TCP和MySQL三种永久性实例的健康检查机制。

公众号初衷

知识输出是笔者的初衷,借助知识输出,能够认识更多的牛人,能够和牛人沟通,也是自己技术提升的一个机会。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-07-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 架构随笔录 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
微服务:剖析一下源码,Nacos的健康检查竟如此简单
前面我们多次提到Nacos的健康检查,比如《微服务之:服务挂的太干脆,Nacos还没反应过来,怎么办?》一文中还对健康检查进行了自定义调优。那么,Nacos的健康检查和心跳机制到底是如何实现的呢?在项目实践中是否又可以参考Nacos的健康检查机制,运用于其他地方呢?
程序新视界
2021/12/07
1.5K0
Nacos心跳机制解读(含简单源码分析)
心跳机制是一种用于监测和管理微服务可用性的机制,它用来维护注册中心和服务提供者之间的连接状态,并及时更新服务实例的状态信息。
一个风轻云淡
2023/11/23
2.2K0
【Nacos源码系列】Nacos心跳机制原理
心跳机制是一种用于监测和管理微服务可用性的机制,它用来维护注册中心和服务提供者之间的连接状态,并及时更新服务实例的状态信息。
索码理
2023/08/21
1.6K0
【Nacos源码系列】Nacos心跳机制原理
Nacos2# 服务注册与发现客户端示例与源码解析(二)
上一篇客户端初始化没有撸完,这篇继续。Nacos从2.0以后增加了对grpc的支持,代码中HTTP的代理初始化还有保留,我们注册发现通常为临时节点,这部分已由gRPC接管。可以对比下新旧逻辑的实现差异。
瓜农老梁
2021/06/10
3.4K0
详解nacos注册中心服务注册流程
说起注册中心,我们首先要知道注册中心是用来做什么的,注册中心一般都是用在微服务架构中,而微服务架构风格是一种将一个单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,服务间通信通常采用HTTP的方式,这些服务共用一个最小型的集中式的管理。这个最小型的集中式管理的组件就是服务注册中心。
架构之家
2022/07/12
4.8K0
详解nacos注册中心服务注册流程
微服务组件-----Spring Cloud Alibaba 注册中心 Nacos源码(1.4.x版本)分析
【1】服务注册:Nacos Client会通过发送REST请求的方式向Nacos Server注册自己的服务,提供自身的元数据,比如ip地址、端口等信息。Nacos Server接收到注册请求后,就会把这些元数据信息存储在一个双层的内存Map中。
忧愁的chafry
2022/10/30
1.2K0
微服务组件-----Spring Cloud Alibaba 注册中心 Nacos源码(1.4.x版本)分析
Nacos 为什么这么强?
点击上方“芋道源码”,选择“设为星标” 管她前浪,还是后浪? 能浪的浪,才是好浪! 每天 10:33 更新文章,每天掉亿点点头发... 源码精品专栏 原创 | Java 2021 超神之路,很肝~ 中文详细注释的开源项目 RPC 框架 Dubbo 源码解析 网络应用框架 Netty 源码解析 消息中间件 RocketMQ 源码解析 数据库中间件 Sharding-JDBC 和 MyCAT 源码解析 作业调度中间件 Elastic-Job 源码解析 分布式事务中间件 TCC-Transaction
芋道源码
2022/10/09
4930
Nacos 为什么这么强?
从实现原理来讲,Nacos 为什么这么强?
这位朋友的简历上写了:对Spring、Spring Cloud Alibaba、MyBatis等源码有深入研究
田维常
2024/04/18
2440
从实现原理来讲,Nacos 为什么这么强?
Nacos 服务注册原理分析
服务是如何注册到注册中心,服务如果挂了,服务是如何检测?带着这些问题,我们从源码上对服务注册进行简单的源码分析。
用户10384376
2023/02/26
5710
Nacos 服务注册原理分析
Nacos 服务注册源码分析
本文我们一起以源码的维度来分析 Nacos 做为服务注册中心的服务注册过程,我会以服务端、客户端两个角度来进行分析,Nacos 客户端我主要是采用 spring-cloud-alibaba 作为核心的客户端组件。对于 Nacos 服务端我会讲解到, Nacos 如何实现 AP/CP 两种模式共存的,以及如何区分的。最后还会分享我在源码调试过程中如何定位核心类的一点经验。
没有故事的陈师傅
2021/07/21
9750
聊聊NacosNamingService的registerInstance
本文主要研究一下NacosNamingService的registerInstance
code4it
2019/10/06
9200
聊聊NacosNamingService的registerInstance
10.Nacos 在客户端实现服务注册的工作原理及源码分析
接下来我会给大家如何从日志入手,找到出发点,然后贯穿整个Nacos 客户端注册源码分析。
AI码师
2023/08/18
5320
10.Nacos 在客户端实现服务注册的工作原理及源码分析
聊聊NacosNamingService的deregisterInstance
本文主要研究一下NacosNamingService的deregisterInstance
code4it
2019/10/07
6610
聊聊NacosNamingService的deregisterInstance
Nacos架构与原理 - 健康检查机制
前者依赖客户端自我报告,较易失效或延迟发现问题。后者由服务端定期检查,可更快准确发现客户端异常。但也增加服务端负载。
小小工匠
2023/07/11
4900
Nacos架构与原理 - 健康检查机制
两种健康检查机制
Spring Cloud Alibaba Nacos 作为注册中心不止提供了服务注册和服务发现功能,它还提供了服务可用性监测的机制。有了此机制之后,Nacos 才能感知服务的健康状态,从而为服务调用者提供健康的服务实例,最终保证了业务系统能够正常的执行。
磊哥
2022/05/09
8870
两种健康检查机制
Nacos实战(19)-Nacos健康检查机制:保障你的服务稳定运行!
注册中心不应仅提供服务注册和发现功能,还应保证对服务可用性监测,对不健康的服务和过期的进行标识或剔除,维护实例的生命周期,以保证客户端尽可能的查询到可用的服务列表。
JavaEdge
2023/09/10
1K0
Nacos实战(19)-Nacos健康检查机制:保障你的服务稳定运行!
Nacos10# 健康检查类型与场景
Nacos支持众多健康检查类型,心跳、HTTP、TCP、MySQL等类型,这些都作用于什么场景?他们又是如何实现的呢?本文就撸一撸这个。
瓜农老梁
2021/08/06
1.1K0
源码阅读|年轻人可以不讲武德,但是你得会阅读Naocs源码
这篇文章将会带大家阅读Nacos源码 以及 教大家阅读源码的技巧,我们正式开始吧!
AI码师
2021/01/20
6790
源码阅读|年轻人可以不讲武德,但是你得会阅读Naocs源码
nacos健康检查和重试机制简述
健康检查机制的作用在于确保服务注册中心中的服务列表始终保持最新和准确的状态,以便客户端能够查询到可用的服务实例。
jack.yang
2025/04/05
2030
Nacos服务发现原理分析
ribbon依赖包含spring-cloud-commons依赖,而在spring-cloud-commons包中spring.factories自动配置LoadBalancerAutoConfiguration类:
用户10384376
2023/02/26
1.3K0
Nacos服务发现原理分析
相关推荐
微服务:剖析一下源码,Nacos的健康检查竟如此简单
更多 >
交个朋友
加入腾讯云官网粉丝站
蹲全网底价单品 享第一手活动信息
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验