Eurka和Nacos

Nacos和Eureka都是服务注册和发现的开源项目,用于构建分布式系统和微服务架构。它们的主要区别如下:

服务注册和发现机制:

  • Nacos:Nacos提供了基于实例的服务注册和发现机制。服务提供者在启动时向Nacos注册自己的服务实例,并定期发送心跳来保持注册。服务消费者通过向Nacos查询服务列表来发现可用的服务实例。
  • Eureka:Eureka采用了基于中心化的服务注册和发现模式。服务提供者在启动时向Eureka注册自己的服务实例,并周期性地发送心跳来保持注册。服务消费者通过向Eureka服务器获取服务注册表来发现可用的服务实例。
  • Nacos支持服务端主动检测提供者状态:临时实例采用心跳模式,非临时实例采用主动检测模式临时实例心跳不正常会被剔除,非临时实例则不会被剔除。另外Nacos支持服务列表变更的消息推送模式,服务列表更新更及时

容错性和高可用性:

  • Nacos:Nacos支持多节点的集群部署,具有高可用性和容错性。它使用Raft算法来保证数据的一致性和可用性,并支持自动的主从切换和故障恢复。
  • Eureka:Eureka的设计目标是在AWS云平台上实现高可用性。它使用了主从架构,其中一个Eureka服务器作为主服务器,其他服务器作为从服务器。当主服务器失效时,会触发Eureka客户端的自我保护机制,但这可能导致注册信息的延迟和不一致。
  • Nacos集群默认采用AP方式,当集群中存在非临时实例时,采用CP模式。Eureka只有AP模式

配置管理:

  • Nacos:Nacos提供了功能强大的配置管理功能。它支持动态配置的发布、监听和刷新,可以动态地修改配置参数而无需重启服务。Nacos还提供了命名空间、配置组和配置版本等概念,可以对配置进行灵活的管理和隔离。
  • Eureka:Eureka本身并没有内置的配置管理功能。如果需要配置管理,可以结合其他的配置中心(如Spring Cloud Config)与Eureka一起使用。

自我保护机制

​ 相同点: 保护阈值都是个比例,0-1 范围,表示健康的 instance 占全部instance 的比例。
​ 不同点:
​ (1)保护方式不同
​ Eureka保护方式:当在短时间内,统计续约失败的比例,如果达到一定阈值,则会触发自我保护的机制,在该机制下Eureka Server不会别除任何的微服务,等到正常后,再退出自我保护机制。自我保护开关(eureka.server.enable-self.preservation. false)
​ Nacos保护方式: 当域名健康实例 (nstance) 占总服务实例(nstance)的比例小于阈值时,无论实例(Instance) 是否健康,都会将这个实例 (instance)返回给客户端。这样做虽然损失了一部分流量,但是保证了集群的剩余健康实例(Instance)能正常工作。
​ (2)范围不同
​ Nacos 的阈值是针对某个具体 Service 的,而不是针对所有服务的。但 Eureka的自我保护阈值是针对所有服务的.

社区支持和集成:

  • Nacos:Nacos由阿里巴巴开源,得到了广泛的社区支持。它与Spring Cloud紧密集成,并提供了丰富的文档和示例来帮助开发者使用。
  • Eureka:Eureka最初由Netflix开发,虽然已经开源并得到了一定的社区支持,但相比Nacos而言,社区支持相对较少。然而,Eureka与Netflix的开源项目(如Ribbon和Hystrix)紧密集成,并在Netflix的生态系统中被广泛应用。

Hystrix和Sentinel

​ Sentinel和Hystrix都是用于实现服务容错和熔断的开源项目。 Hystrix 的关注点在于以 隔离熔断 为主的容错机制,超时或被熔断的调用将会快速失败,并可以提供 fallback 机制。而 Sentinel 的侧重点在于:多样化的流量控制、熔断降级、系统负载保护、实时监控和控制台。

资源模型和执行模型上的对比

​ Hystrix 的资源模型设计上采用了命令模式,将对外部资源的调用和 fallback 逻辑封装成一个命令对象(HystrixCommand / HystrixObservableCommand),其底层的执行是基于 RxJava 实现的。每个 Command 创建时都要指定 commandKey 和 groupKey(用于区分资源)以及对应的隔离策略(线程池隔离 or 信号量隔离)。线程池隔离模式下需要配置线程池对应的参数(线程池名称、容量、排队超时等),然后 Command 就会在指定的线程池按照指定的容错策略执行;信号量隔离模式下需要配置最大并发数,执行 Command 时 Hystrix 就会限制其并发调用。

​ Sentinel 的设计则更为简单。相比 Hystrix Command 强依赖隔离规则,Sentinel 的资源定义与规则配置的耦合度更低。Hystrix 的 Command 强依赖于隔离规则配置的原因是隔离规则会直接影响 Command 的执行。在执行的时候 Hystrix 会解析 Command 的隔离规则来创建 RxJava Scheduler 并在其上调度执行,若是线程池模式则 Scheduler 底层的线程池为配置的线程池,若是信号量模式则简单包装成当前线程执行的 Scheduler。而 Sentinel 并不指定执行模型,也不关注应用是如何执行的。Sentinel 的原则非常简单:根据对应资源配置的规则来为资源执行相应的限流/降级/负载保护策略。在 Sentinel 中资源定义和规则配置是分离的。用户先通过 Sentinel API 给对应的业务逻辑定义资源(埋点),然后可以在需要的时候配置规则。埋点方式有两种:

  • try-catch 方式(通过 SphU.entry(...)),用户在 catch 块中执行异常处理 / fallback
  • if-else 方式(通过 SphO.entry(...)),当返回 false 时执行异常处理 / fallback

​ Sentinel 还支持基于注解的资源定义方式,可以通过 @SentinelResource 注解参数指定异常处理函数和 fallback 函数。

隔离设计上的对比

​ 隔离是 Hystrix 的核心功能之一。Hystrix 提供两种隔离策略:线程池隔离(Bulkhead Pattern)和信号量隔离,其中最推荐也是最常用的是线程池隔离。Hystrix 的线程池隔离针对不同的资源分别创建不同的线程池,不同服务调用都发生在不同的线程池中,在线程池排队、超时等阻塞情况时可以快速失败,并可以提供 fallback 机制。线程池隔离的好处是隔离度比较高,可以针对某个资源的线程池去进行处理而不影响其它资源,但是代价就是线程上下文切换的 overhead 比较大,特别是对低延时的调用有比较大的影响。

​ 但是,实际情况下,线程池隔离并没有带来非常多的好处。首先就是过多的线程池会非常影响性能。考虑这样一个场景,在 Tomcat 之类的 Servlet 容器使用 Hystrix,本身 Tomcat 自身的线程数目就非常多了(可能到几十或一百多),如果加上 Hystrix 为各个资源创建的线程池,总共线程数目会非常多(几百个线程),这样上下文切换会有非常大的损耗。另外,线程池模式比较彻底的隔离性使得 Hystrix 可以针对不同资源线程池的排队、超时情况分别进行处理,但这其实是超时熔断和流量控制要解决的问题,如果组件具备了超时熔断和流量控制的能力,线程池隔离就显得没有那么必要了。

​ Hystrix 的信号量隔离限制对某个资源调用的并发数。这样的隔离非常轻量级,仅限制对某个资源调用的并发数,而不是显式地去创建线程池,所以 overhead 比较小,但是效果不错,也支持超时失败。Sentinel 可以通过并发线程数模式的流量控制来提供信号量隔离的功能。并且结合基于响应时间的熔断降级模式,可以在不稳定资源的平均响应时间比较高的时候自动降级,防止过多的慢调用占满并发数,影响整个系统。

熔断降级对比

​ Sentinel 和 Hystrix 的熔断降级功能本质上都是基于熔断器模式(Circuit Breaker Pattern)。Sentinel 与 Hystrix 都支持基于失败比率(异常比率)的熔断降级,在调用达到一定量级并且失败比率达到设定的阈值时自动进行熔断,此时所有对该资源的调用都会被 block,直到过了指定的时间窗口后才启发性地恢复。上面提到过,Sentinel 还支持基于平均响应时间的熔断降级,可以在服务响应时间持续飙高的时候自动熔断,拒绝掉更多的请求,直到一段时间后才恢复。这样可以防止调用非常慢造成级联阻塞的情况。

实时指标统计实现对比

​ Hystrix 和 Sentinel 的实时指标数据统计实现都是基于滑动窗口的。Hystrix 1.5 之前的版本是通过环形数组实现的滑动窗口,通过锁配合 CAS 的操作对每个桶的统计信息进行更新。Hystrix 1.5 开始对实时指标统计的实现进行了重构,将指标统计数据结构抽象成了响应式流(reactive stream)的形式,方便消费者去利用指标信息。同时底层改造成了基于 RxJava 的事件驱动模式,在服务调用成功/失败/超时的时候发布相应的事件,通过一系列的变换和聚合最终得到实时的指标统计数据流,可以被熔断器或 Dashboard 消费。

​ Sentinel 目前抽象出了 Metric 指标统计接口,底层可以有不同的实现,目前默认的实现是基于 LeapArray 的高性能滑动窗口,后续根据需要可能会引入 reactive stream 等实现。

总结

Sentinel Hystrix
隔离策略 信号量隔离 线程池隔离/信号量隔离
熔断降级策略 基于慢调用比例或异常比例 基于失败比率
实时指标实现 滑动窗口 滑动窗口(基于 RxJava)
规则配置 支持多种数据源 支持多种数据源
扩展性 多个扩展点 插件的形式
基于注解的支持 支持 支持
限流 基于 QPS,支持基于调用关系的限流 有限的支持
流量整形 支持慢启动、匀速排队模式 不支持
系统自适应保护 支持 不支持
控制台 开箱即用,可配置规则、查看秒级监控、机器发现等 不完善
常见框架的适配 Servlet、Spring Cloud、Dubbo、gRPC 等 Servlet、Spring Cloud Netflix