Eureka vs. Nacos:注册中心角色之间的不同特性

此文章简要介绍一下Eureka和Nacos在注册中心功能上规则、功能的不同

服务拉取机制

这一部分内容我们可以引入两个远程调用最初的问题来引入

  • 消费者如何得知提供者信息,包括url,健康状态等?
  • 当程序并发量大,提供者以集群部署时,应该如何选择?

根据此二问题,衍生出了服务拉取等环节(服务拉取:经过负载均衡的服务调用)

也为了应对这样的问题,我们需要一个统一的中介角色,来管理提供者和消费者,并且登记提供者的地址等信息。同时,在出现集群时,有对应的算法均衡负载。Eureka便是这样的一个角色。在微服务启动时,提供者将自己的集群信息发送到Eureka中,并每隔30s向Eureka发送心跳响应,保证提供者的健康状态。(若提供者宕机则剔除出注册中心)。

但是这个拉取并不是每一次需要远程调用时都需触发的。Eureka中规定了定时拉取&缓存的机制,用以提高服务的效率。每一次拉取之后,所有的服务都将缓存在一个服务列表中。同时若长时间多次使用此服务时。也需要对提供者的健康状态等信息做出更新。于是Eureka中规定,对统一服务的列表缓存每隔30s做出更新。 (前提是过了30s中此提供者仍需再次提供服务)

而在Nacos中,其规则不尽相同

Nacos会将实例区分为临时实例非临时实例

  • 对于临时实例,其心跳响应机制跟Eureka大致相同,但是其响应频率更高。若其宕机,Nacos直接将其从服务列表中剔除
  • 对于非临时实例,其不会对Nacos进行心跳相应。而是由Nacos主动发送请求,并确认对应状态。(有点像是变相的心跳响应)若其宕机,Nacos也不会剔除,仅仅标记其为不健康服务

在Eureka中,服务消费者会对Eureka定时拉取 (pull) ,拉取更新服务列表的信息。而由于Nacos与服务提供者的不同特性,相比之下服务更新的状态时效性较差。于是Nacos中增加了新的特性。在提供者和Nacos的状态更新中,若有实例宕机或健康状态改变,Nacos会主动推送(push)实例的变更信息。 从而保证服务列表中状态的一致性。

但是主动推送这一特性,对服务器带来的压力会较大。所以需结合使用场景,斟酌好使用临时实例或非临时实例。

如何将服务配置为临时或 非临时实例?

修改配置文件如:

spring.cloud.nacos.discovery.ephemeral: flase
# 非临时实例
spring.cloud.nacos.discovery.ephemeral: true
# 临时实例

CAP

Eureka和Nacos在CAP模式规则设计上的差别

CAP 定理,也称为 Brewer 定理,是分布式系统中的一个基本原则,它阐明了三个关键属性之间的固有权衡:一致性、可用性和分区容错性。CAP 定理由计算机科学家 Eric Brewer 于 2000 年提出,现已成为架构师和工程师设计分布式系统的基石概念。这些模式描述了在分布式系统中不同的设计目标和优先级。

  • C -> 一致性(Consistency)

一致性强调在所有分布式节点具有同时的数据视图,当需要修改时,确保修改后的最新数据能同步到所有节点当中。

  • A -> 可用性(Availability)

可用性强调在系统面对故障or宕机等特殊情况时,整个分布式系统仍能继续处理请求,返回响应,不会因部分节点的故障导致整体宕机。但此时不能保证其含有最新版本的数据

  • P -> 分区容忍性(Partition Tolerance)

指即使部分服务出现故障宕机,从而导致节点之间时区通信。但系统仍能维持其运行的能力。

实际开发中,根据应用场景的不同,以及业务功能的要求不同。我们需要在一致性和可用性之间做平衡取舍。而CAP定理可以给我们带来一份范本。

而在Eureka和Nacos的集群部署当中

  • Nacos集群默认采用AP方式,当集群中存在非临时实例时,采用CP模式;
  • Eureka采用AP方式

注意,虽然两者默认采用的都是AP模式,但并不代表同时就牺牲了一致性。两者的心跳机制便是保证数据一致性的重要规则。另外还有注册表同步,集群选举等保证一致性的重要措施。

数据存储方式

  1. Eureka的数据存储方式

    • Eureka使用内存中的数据结构来存储服务实例信息,例如使用HashMap等数据结构。
    • 默认情况下,Eureka并不提供对服务实例信息的持久化支持,这意味着当Eureka服务器重启或者发生故障时,原有的服务实例信息将会丢失,需要重新注册。
  2. Nacos的数据存储方式

    • Nacos提供了多种数据存储方式,可以根据实际需求选择合适的存储方式来存储服务实例信息,包括内嵌数据库、MySQL、Redis等。
    • 内嵌数据库是Nacos的默认存储方式,可以在启动Nacos时自动创建并初始化数据库表,将服务实例信息持久化到数据库中。
    • 使用外部数据库(如MySQL、Redis)可以提供更高的可靠性和扩展性,保证了服务实例信息的持久化和高可用性,同时也方便了数据的管理和备份。

相较之下,Eureka的这种设计适合于轻量级的应用场景。其本身并没有内置的持久化机制,这种设计灵活性较高,用户可以根据自己的实际情况选择合适的持久化方式,并自定义持久化的规则。但同时也需要具备更多的开发能力,自行实现对Eureka Server的持久化支持。

在自定义配置项中,可以通过配置Eureka Server示例信息的过期时间eureka.server.eviction-interval-timer-in-ms,以及自我保护模式下的过期时间eureka.server.renewal-percent-threshold,确保示例信息不会因未更新而被删除。另外也可以结合Redis等配置持久化缓存,但没有直接的接口使Eureka进行持久化。

加载策略

在Eureka中,默认采用的是饥饿加载,Nacos则默认使用惰性加载

两者定义:

  1. 饥饿加载(Eager Loading)

    • 饥饿加载是指在需要使用对象或数据之前就提前加载它们到内存中。
    • 在关系数据库中,饥饿加载可以通过一次性查询所有相关数据来实现,例如使用 SQL 中的 JOIN 操作,将多个表的数据一次性加载到内存中。
    • 在对象关系映射(ORM)中,饥饿加载可以通过在查询对象时同时加载其关联对象的数据来实现,例如使用 Hibernate 中的 Fetch 操作。
    • 减少后续查询或访问时的延迟,提高系统性能和响应速度。
    • 可能会导致不必要的数据加载和内存消耗。

一次性把所有数据和服务都加载到内存当中,启动时缓慢,但是减少使用对应服务时的加载时间。

  1. 惰性加载(Lazy Loading)

    • 惰性加载是指在需要使用对象或数据时才进行加载,延迟加载到最后可能需要使用的时候。
    • 在关系数据库中,惰性加载可以通过延迟执行查询来实现,例如在 ORM 中使用延迟加载的关联对象,在需要访问关联对象数据时才真正执行查询。
    • 在前端开发中,惰性加载也常用于延迟加载页面内容或组件,例如使用懒加载技术来减少初始页面加载时的资源消耗。
    • 节省了不必要的资源消耗和加载时间。
    • 增加访问时的延迟。

用到什么再加载什么,大量使用不同的未加载的服务可能导致效率非常低

当Eureka Server启动时,它会立即尝试从所有注册的服务中心获取服务实例信息,并将这些信息加载到内存中。这一方式确保在系统启动后尽快获取和管理服务实例的信息,以便其他服务可以快速地发现和调用这些服务。

在Nacos中,服务注册和发现是惰性加载的。当Nacos Server启动时,并不会立即加载所有服务实例信息到内存中,而是在有具体的服务实例注册或者查询时才会进行加载和处理。节省了不必要的资源和内存消耗。

一般来说,Eureka的饥饿加载适合于对服务实例信息实时性要求较高的场景,如支付服务等,与内存资源充足的场景,如云原生应用。

而Nacos的惰性加载则适合于对系统资源消耗和加载时间有一定要求的场景,如电子商城中所有的商品具体信息。

你可能感兴趣的:(cloud,eureka,云原生,微服务,容器,网络)