首页 > 自考资讯 > 自考知识

nacos架构原理,nacos client

头条共创 2024-07-05

前言

根据目前市场主流使用场景,Nacos分为服务注册发现(命名)和配置中心(Config)两个功能。在上一篇文章中,我们介绍了Nacos配置中心的实现原理。今天的文章,我们将介绍Nacos服务的注册检测功能相关的内容。

说到服务模型,其实我们需要区分用户的视角和内核的视角。这意味着Nacos用户角度的服务模型和Nacos开发者设计的内核模型可能有很大不同。今天这篇文章旨在从用户的角度来看,探讨Nacos服务发现的最佳实践。

服务模型介绍

通常当我们谈论招生中心时,我们指的是Zookeeper。这也是很多人最熟悉的报名中心。但如果您实际编写或见过任何使用Zookeeper 作为注册中心的自适应代码,您会注意到这一点,再加上注册中心涉及的一致性原则,导致许多人的第一印象您就会理解。我的印象是:“这很难!” 但归根结底,Zookeeper根本就不是专门为招生中心设计的。 Zookeeper提供的API和内核设计忽略了“服务模型”的概念,需要开发人员设计自己的模型来填充Zookeeper。和服务发现。

微服务架构逐渐采用后,Nacos、Consul、Eureka等注册中心组件开始崭露头角。这些“真正的”注册中心有自己的“服务模式”,你会发现它们更容易使用。

为什么我们需要一个“服务模型”?理论上,你也可以将基本组件塑造成你想要的任何形状。这并不是阿里巴巴某人实际采用的“夸张”技术。那么,它要花多少钱?当业务发展到一定规模时,必然会遇到瓶颈,甚至出现无法正常运行的极端情况,导致可扩展性下降。就像学生第一次学习数据结构时一样,学生中常见的一些问题是:为什么堆栈只能先进后出?并非所有开发人员都是中间件专家,因此Nacos 设计了独特的“服务模型”。这限制了用户的“想象力”,但却能让用户正确使用Nacos。

我们花了一些篇幅来解释为什么Nacos 需要设计一个“服务模型”。我们来看看实际的Nacos模型是什么样的。其实从照片上就可以清楚的表达出来。

7ae0143e7cf148d3bd5831666bc77e52~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1720761226&x-signature=AgBdUiQdotNIJzy9VobaZKGhcqc%3D 与Consul和Eureka的设计不同,Nacos Service Discovery使用的领域模型是多层命名空间-组-服务-集群-实例结构。服务和实例是核心模型,但命名空间、组和集群实现了不同粒度的服务分离。

为了更好地理解服务和实例这两个核心模型,我们以Nacos 注册中心适配的两个微服务框架Dubbo 和SpringCloud 为例,介绍一下它们与对应模型的映射方式_______。

销钉。将接口三元组(接口名称+组名称+版本号)映射到服务,并定义实例IP和端口号作为实例。 Nacos 上注册的典型Dubbo 服务:Providers:com.alibaba.mse.EchoService:1.0.0:DUBBOSpring Cloud。将应用程序名称映射为服务,并将实例IP 和端口号定义为实例。一个典型的注册到Nacos 的Spring Cloud 服务:helloApp 下面,我们将详细讲解Nacos 提供的API 与服务模型的关系。

环境准备

需要部署Nacos服务器进行测试。我选择直接在https://mse.console.aliyun.com/购买MSE托管的Nacos。读者可以选择购买MSE Nacos或者搭建自己的Nacos服务器。

c0fed51425694e69915242a4002a2bfb~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1720761226&x-signature=LIL3%2FcBcywpaEQiQlrVda84EEDk%3DMSE Nacos提供了可视化控制台,也可以帮助您更好地了解Nacos服务模型。下面的一些屏幕截图来自MSE Nacos 商业控制台。

快速开始

首先我们来实现一个最简单的服务注册和发现demo。 Nacos支持客户端注册和订阅服务实例。具体代码如下。

PropertiesProperty=new Properties();properties.setProperty(PropertyKeyConst.SERVER_ADDR, 'mse-xxxx-p.nacos-ans.mse.aliyuncs.com:8848');String serviceName='nacos.test.service.1';String instanceIp=InetAddress.getLocalHost().getHostAddress(); ininstancePort=8080; NamingService.registerInstance(serviceName,instanceIp,instancePort); System.out.println(namingService.getAllInstances(serviceName));实际注册使用localhost 作为IP,8080 作为端口号。

0e90dee0a880469487b98fbb0af76e29~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1720761226&x-signature=Liang8a7JFAHMIwrxUP7mBaAagA%3D 09e8de92431c467281667c51c5c13e27~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1720761226&x-signature=DpZCYDZMhZfg%2FOatf9dueOL8rqk%3D 控制台还打印服务详细信息。至此,我们就完成了一个最简单的Nacos服务发现demo。让我快速解释一些细节。

属性PropertyKeyConst.SERVER_ADDR代表Nacos服务器的地址。当客户端创建NamingService实例时,它会为该实例创建一个独立的资源空间,包括缓存、线程池、配置等。 Nacos 客户端对此实例没有单例限制。小心维护此实例,以避免创建比预期更多的实例。注册服务registerInstance使用最简单的重载方法,只传递服务名称、IP和端口。在上面的示例中,未显示命名空间、组和集群等服务模型。下一节将提供更多详细信息。本示例主要展示Nacos支持的一些默认配置,例如服务、集群等。需要实例。这也证明上述服务和实例是Nacos的一等公民。

您可以通过截图找到默认配置的默认值。

命名空间:默认值为public或空字符串,两者都可以代表默认命名空间。组:默认值为DEFAULT_GROUP。集群:默认值为DEFAULT。

构建自定义实例

为了完整地了解Nacos的服务模型,我们还需要引入实例相关的API。例如,您可以为您注册的某些实例分配更多的流量,也可以将某些实例的元信息传递给Nacos服务器(例如IP所属的应用程序或IP所属的机房)进行存储我希望你能做到。已到位,因此客户端可以下载已安装实例的元信息来自定义负载平衡模式。 Nacos还提供了单独的注册实例的接口,允许用户在注册实例时指定实例属性。

/** * 使用指定的实例属性向服务注册实例。 * * @param serviceName 服务名称* @param groupName 服务组* @param instance 要注册的实例* @throws NacosException nacos 异常*/void registerInstance(String serviceName, String groupName, Instance instance) throws NacosException;注册时可以传入一个Instance实例,其属性为:

public class Instance { /** * 该实例的唯一ID。 */private String ip; /** * 实例的端口。实例权重。 */private double Weight=1.0D; /** * 实例健康状态。 */private boolean allowed=true; * * 如果实例是临时实例* * @since 1.0.0 */private boolean ephemeral=true; /** * 实例的集群信息*/private String clusterName;实例的服务信息信息。 serviceName; /** * user extensions. */private MapString, Stringmetadata=new HashMapString, String();} 有些字段从字面上看是可以理解的,有些字段通过Nacos 的设计很难理解。我认为重要的属性是:

健康实例的健康状态。判断实例是否健康。心跳健康检查通常会自动更新此字段。启用是否启用。与Healthy的区别在于,Healthy一般是通过内核健康检查来更新,而Enabled则有更多的业务语义,可以根据业务场景进行完全控制。例如,在Dubbo中,该字段通常用于标识实例IP的在线和离线状态。 ephemeral 临时或持久实例。这是一个非常重要的字段,要理解这个字段的含义我们需要更深入地了解Nakos。区别在于心跳检测失败一段时间后实例是自动下线还是标记为不健康。通常,注册中心场景使用临时实例。这样,心跳检测失败后,消费者可以通过DNS方式收到离线通知,并使用更持久的实例。我们在《一文详解 Nacos 高可用特性》中也介绍过,该字段也会影响Nacos完整性协议。元数据元数据。映射结构可以存储您的实例的自定义扩展信息,例如机房信息、路由标签、应用程序信息和权重信息。该信息由服务提供者上报,然后由服务消费者检索,从而完成信息的传递。以下是完整的实例注册演示代码。

PropertiesProperty=new Properties();//指定Nacos服务器的地址propertyKeyConst.SERVER_ADDR, 'mse-xxxx-p.nacos-ans.mse.aliyuncs.com:8848');//指定命名空间property .setProperty ( PropertyKeyConst.NAMESPACE, '9125571e-bf50-4260-9be5-18a3b2e3605b');NamingService NamingService=NacosFactory.createNamingService(properties);String serviceName='nacos.test.service.1';String group='DEFAULT_GROUP'; hangzhou';StringinstanceIp=InetAddress.getLocalHost().getHostAddress();intinstancePort=8080;Instance instance=new Instance();//指定集群名称。 instance.setClusterName(clusterName);instance.setIp(instanceIp) ;instance.setPort(instancePort);//指定实例元数据MapString, Stringmetadata=new HashMap();metadata.put('app', 'nacos- demo' );metadata.put('site' , 'cn -hangzhou');metadata.put('protocol', '1.3.3');instance.setMetadata(metadata);//设置服务名称、组、实例指定namingService.registerInstance(serviceName, group,instance); System.out .println(namingService.getAllInstances(serviceName));035671a2ed374b368c440d0307e3f130~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1720761226&x-signature=BEL7h066ASR95MBdaw2WFbWp5aE%3D fcc9f6b1df514436801cbe372eab401a~noop.image?_iz=58558&from=article.pc_detail&lk3s=953192f4&x-expires=1720761226&x-signature=hqrf2qKiIQN4hd32HkLw8RajV8U%3D

构建自定义服务

除了实例之外,还可以自定义Nacos服务以及所有的实例将在实例上注销。然后死去。不过Nacos目前对于定制服务的支持还不是很多。除了使用OpenApi 更改服务的属性之外,您还只能使用为自定义配置注册实例时传递的服务属性。因此,在实际的Dubbo和SpringCloud中,自定义服务一般使用的不多,而使用自定义实例信息的相对较多。

Nacos的服务与Consul和Eureka的模型不同。 Consul和Eureka服务相当于Nacos的实例;服务本身不是独立的模型。在我看来,Nacos 的设计更加合理,考虑到服务本身也有影响服务内所有实例的配置和权限控制等数据存储需求。实例属性必须继承自服务属性,并且实例级别可以覆盖服务级别。服务数据结构如下:

/** * 服务名称*/private String name; /** * 保护阈值*/private float protectedThreshold=0.0F; /** * 该服务的应用程序名称*/private String app */private String group; * * 健康检查模式*/private MapString, Stringmetadata=new HashMapString();只需如开篇介绍的那样使用ServiceName标记服务即可。

服务隔离:NamespaceGroupCluster

由于篇幅原因,这三个概念放在一起提出。

项王感兴趣,神女却无意。 Nacos提出了这些分离策略,但目前在实际应用中仅使用命名空间较多,组和集群似乎没有被认真考虑。

集群的集群分离在阿里巴巴内部非常常用。通常情况下,该服务的一个实例必须配置多种健康检查方法。有些实例使用TCP健康检查方法,有些实例使用HTTP健康检查方法。另一种场景是当一个服务下挂载的机器属于不同的环境时,通过集群隔离可以一劳永逸地路由特定环境内的所有流量。 Nacos 2.0还刻意弱化了集群的概念。毕竟,开源在某些情况下对阿里巴巴是有利的,但不一定对开源的未来有利。集群的概念可能又回到了大家的脑海中。历史最终会重演。

组组分离的概念可以参考Dubbo的服务分离策略,它也有组。支持分组扩容的意图当然是一件好事。在实际使用中,有些公司实际上习惯使用组来进行分离。需要注意的一点是,Dubbo 注册三元组(接口名称+组+版本)时,Dubbo 组包含在Nacos 服务名称中,并没有映射到Nacos 组。 Nacos 注册的服务通常默认位于DEFAULT_GROUP 组中。

我认为命名空间分离对于Nacos来说是更好的设计。它也常用于现实场景中,常用于分隔多个环境,例如分隔日常、开发、测试、UAT、生产等环境。使用命名空间进行逻辑分离是一种节省成本的策略,尤其是在您拥有许多环境的情况下。但是,我们强烈建议命名空间仅用于非在线环境中的隔离。例如,跨多个测试环境共享一套Nacos集,在线环境中构建单独的Nacos集群,以防止离线测试流量对其进行干扰。在线环境。

服务发现:

推拉模型上面介绍完了 Nacos 服务发现的 5 大领域模型,最后一节,介绍下如何获取服务模型。 Nacos 的服务发现,有主动拉取和推送两种模式,这与一般的服务发现架构相同。以下是拉模型的相关接口: /** * Get all instances of a service * * @param serviceName name of service * @return A list of instance * @throws NacosException */List<Instance> getAllInstances(String serviceName) throws NacosException;/** * Get qualified instances of service * * @param serviceName name of service * @param healthy a flag to indicate returning healthy or unhealthy instances * @return A qualified list of instance * @throws NacosException */List<Instance> selectInstances(String serviceName, boolean healthy) throws NacosException;/** * Select one healthy instance of service using predefined load balance strategy * * @param serviceName name of service * @return qualified instance * @throws NacosException */Instance selectOneHealthyInstance(String serviceName) throws NacosException;Nacos 提供了三个同步拉取服务的方法,一个是查询所有注册的实例,一个是只查询健康且上线的实例,还有一个是获取一个健康且上线的实例。一般情况下,订阅端并不关心不健康的实例或者权重设为 0 的实例,但是也不排除一些场景下,有一些运维或者管理的场景需要拿到所有的实例。细心的读者会注意到上述 Nacos 实例中有一个 weight 字段,便是作用在此处的selectOneHealthyInstance接口上,按照权重返回一个健康的实例。个人认为这个功能相对鸡肋,一般的 RPC 框架都有自身配套的负载均衡策略,很少会由注册中心 cover,事实上 Dubbo 和 Spring Cloud 都没有用到 Nacos 的这个接口。 除了主动查询实例列表,Nacos还提供订阅模式来感知服务下实例列表的变化,包括服务配置或者实例配置的变化。可以使用下面的接口来进行订阅或者取消订阅: /** * Subscribe service to receive events of instances alteration * * @param serviceName name of service * @param listener event listener * @throws NacosException */void subscribe(String serviceName, EventListener listener) throws NacosException;/** * Unsubscribe event listener of service * * @param serviceName name of service * @param listener event listener * @throws NacosException */void unsubscribe(String serviceName, EventListener listener) throws NacosException;在实际的服务发现中,订阅接口尤为重要。消费者启动时,一般会同步获取一次服务信息用于初始化,紧接着订阅服务,这样当服务发生上下线时,就可以感知变化了,从而实现服务发现。

总结

Nacos 为了更好的实现服务发现,提供一套成熟的服务模型,其中重点需要关注的是 Namespace、Service 和 Instance,得益于这一套服务模型的抽象,以及对推拉模型的支持,Nacos 可以快速被微服务框架集成。 理解了 Nacos 的服务模型,也有利于我们了解 Nacos 背后的工作原理,从而确保我们正确地使用 Nacos。但 Nacos 提供的这些模型也不一定所有都需要用上,例如集群、分组、权重等概念,被实践证明是相对鸡肋的设计,在使用时,也需要根据自身业务特点去评估特性用量,不要盲目地为了使用技术而去用。 作者:岛风 本文为阿里云原创内容,未经允许不得转载。 版权声明:本文转载于今日头条,版权归作者所有,如果侵权,请联系本站编辑删除

猜你喜欢