当前位置: 首页 > 科技观察

微服务的灵魂摆渡人——Nacos,这里有完整的原理指南

时间:2023-03-16 19:38:45 科技观察

转载请联系程序新视野公众号。前言肉眼可见的是,Nacos在微服务系统的服务注册和发现领域势头正猛。在微服务系统中,服务的注册和发现是另一个灵魂。如果没有注册中心的存在,数百个服务之间调用的复杂度是难以想象的。如果你计划或已经使用Nacos,但仅仅停留在使用层面,那么这篇文章值得一读。在本文中,我们从服务发现机制入手,然后对Nacos的基本介绍、实现原理、架构等进行讲解,真正深入浅出地了解Nacos。服务注册与发现说起Nacos,就不得不说说微服务架构中的服务发现。其实servicediscovery已经在文章?中得到了充分的解释。让我们在这里简单回顾一下。在传统应用中,当一个服务A访问另一个服务B时,??我们只需要在服务A的静态配置文件中配置服务B的服务地址和端口即可。但是在微服务架构中,这种情况发生了变化,如下图下图:上图中,服务实例的IP是动态分配的。同时也面临着服务的增减、失效、升级等变化。在这种情况下,对于客户端程序来说,就需要使用更精确的服务发现机制。为了解决这个问题,etcd、Consul、ApacheZookeeper、Nacos等服务注册中间件应运而生。Nacos简介Nacos一般发音为/nɑ:k??s/,这个名字来源于《动态命名与配置服务》。其中na取自“Naming”的前两个字母,co取自“Configuration”的前两个字母,s取自“Service”的第一个字母。官方用一句话描述Nacos的功能:“一个动态的服务发现、配置管理、服务管理平台,更容易构建云原生应用”。也就是说,Nacos不仅提供了服务注册和发现功能,还提供了配置。管理功能还提供可视化管理平台。官方文档中还提到“服务(Service)是Nacos世界的一等公民”。也就是说,Nacos是围绕Service展开的。如果你查看源码,你会发现Nacos核心API定义了两个接口,NamingService和ConfigService。服务注册和发现围绕NamingService,而配置管理围绕ConfigService。官网给出了Nacos的四大核心特性:服务发现与服务健康监控、动态配置服务、动态DNS服务、服务及其元数据管理。我们主要讲一下服务发现功能。NacosServer和ClientNacos注册中心分为Server和Client。Nacos提供了SDK和openApi。如果没有SDK,也可以根据openApi手动编写服务注册发现和配置拉取的逻辑。Server使用Java编写,基于SpringBoot框架,为Client提供注册发现和配置服务。客户端支持包括目前已知的Nacos多语言客户端和Spring生态的相关客户端。客户端和微服务嵌套在一起。Nacos的DNS实现依赖于CoreDNS,其项目为nacos-coredns-plugin。本插件提供基于CoreDNS的DNS-F客户端,开发语言为go。Nacos注册中的交互过程作为注册中心的一个功能,Nacos提供的功能与其他主流框架非常相似,基本都是围绕服务实例注册、实例健康检查、服务实例获取三个核心来实现的。以Java版Nacos客户端为例,服务注册的基本流程:服务实例启动并向Nacos注册中心注册自己,然后与注册中心保持心跳;心跳维护策略是每5秒向NacosServer发送一次心跳,并携带Instance信息(服务名、实例IP、端口等);NacosServer也会主动向Client发起健康检查,支持TCP/Http;如果15秒内没有心跳,健康检查失败,则认为实例不健康。如果在30秒内健康检查失败,则该实例被淘汰;服务消费者通过注册中心获取实例并发起调用;服务发现支持两种场景:一是服务消费者直接向注册中心发送请求获取服务实例,注册中心返回所有可用的实例,但一般不推荐这种方式;其次,服务消费者向注册中心订阅服务并提交监听器。当注册中心的服务发生变化时,监听器会收到通知,消费者会更新本地服务实例列表,确保所有服务可用。Nacos数据模型关于数据模型,官网描述:Nacos数据模型的key由三元组唯一确定,Namespace默认为空字符串,公共命名空间(public),group默认为DEFAULT_GROUP。上图是官方提供的,大家可以仔细看一下:如果还是看不懂,我们可以直接从代码层面看Namespace、Group、Service是怎么存储的:/***Map(namespace,Map(group::serviceName,Service)).*/privatefinalMap>serviceMap=newConcurrentHashMap<>();也就是说Nacos的服务注册中心结构是:MapNacos基于命名空间的设计是为了做多环境多租户的数据(配置和服务)隔离。如果用户有多个环境(开发、测试、生产等),可以构建三个不同的命名空间,比如上图中的dev-namespace和prod-namespace。Nacos服务领域模型在上面的数据模型中,我们可以定位到一个服务(Service),那么服务模型呢?官网提供了下图:从图中的分层存储模型可以看出,在serviceLevel中,保存的是健康检查开关、元数据、路由机制、保护阈值等设置,而集群保存的数据是这样的如健康检查方式、元数据、同步机制等,实例保存ip、端口、权重、实例的健康检查状态、离线状态、元数据、响应时间。此时,我们忽略一对多的情况。整个Nacos中的数据存储关系如下:可以看出整个层次的包含关系是Namespace包含多个Group,Group可以包含多个Service,Service可以包含多个Cluster,Cluster包含Instance集合。对应部分源码如下://ServiceManager类,Map(namespace,Map(group::serviceName,Service))privatefinalMap>serviceMap=newConcurrentHashMap<>();//服务类,Map(cluster,Cluster)privateMapclusterMap=newHashMap<>();//集群类privateSetpersistentInstances=newHashSet<>();privateSetephemeralInstances=newHashSet<>();//实例类privateStringinstanceId;privateStringip;privateintport;privatedoubleweight=1.0D;其中,实例分为临时实例和持久实例。它们之间的主要区别在于健康检查的方式。临时实例使用客户端报告模式,而持久实例使用服务器端反向检测模式。临时实例需要能够自动移除不健康的实例,而不需要持久存储实例。持久化实例采用服务端检测的健康检查方式,由于客户端不上报心跳,自然无法自动移除掉线的实例。小结我们从微服务系统为什么要使用服务发现开始,然后介绍Nacos,Nacos的实现机制,底层数据模型,以及一些源码实现。除了在使用过程中关注服务的注册、发现、健康检查,还需要关注服务的数据模型中的Namespace、Group、Service、Instance。当你了解了这些背后的工作原理后,你就可以轻松使用上层应用的集成和配置。