㈠ Spring Cloud
本文中我们主要介绍微服务开发框架——Spring Cloud。尽管Spring Cloud带有"Cloud"的字样,但它并不是云计算解决方案,而是Spring Boot的基础上构建的,用于快速构建分布式系统的通用模式的工具集。
Spring Cloud有以下特点:
由上图可知,Spring Cloud是以 英文单词+SR+数字 的形式命名版本号的。那么英文单词和SR分别表示什么呢?
因为Spring Cloud是一个综合项目,它包含很多子项目。由于子项目也维护着自己的版本号,Spring Cloud采用了这种命名方式,从而避免与子项目的版本混淆。其中英文单词如Edware是伦敦某地铁站名,它们按照字母顺序发行,可以将其理解为主版本的演进。SR表示"Service Release",一般表示Bug修复。
版本兼容性如下
版本内容
可参考官方文档: https://spring.io/projects/spring-cloud#overview
我的上一篇博客(微服务理论篇)中谈到,对单体应用进行服务拆分得到各个微服务,而这些服务又是相互独立的,那么我们如何知道各个微服务的健康状态、如何知道某个微服务的存在呢?由此、一个拥有服务发现的框架显得尤为重要。这也就是Eureka诞生的原因。
综上,Eureka通过心跳检查、客户端缓存等机制,确保了系统的高可用性、灵活性和可伸缩性。
通过使用Eureka已经实现了微服务的注册与发现。启动各个微服务时,Eureka Client会把自己的网络信息注册到Eureka Server上。似乎一切更美好了一些。然而,这样的架构依然有一些问题,如负载均衡。一般来说,各个微服务都会部署多个实例。那么服务消费者要如何将请求分摊到多个服务提供实例上呢?
如果服务提供者相应非常慢,那么消费者对提供者的请求就会被强制等待,知道提供者响应或超时。在高负载场景下,如果不作任何处理,此类问题可能会导致服务消费者的资源耗竭甚至整个系统崩溃。
微服务架构的应用系统通常包含多个服务层。微服务之间通过网络进行通信,从而支撑起整个应用系统,因此,微服务之间难免存在依赖关系。而这种由于"基础服务故障"导致"级联故障"的现象称为雪崩效应。
如图所示,A最为服务提供者(基础服务),B为A的服务消费者,C和D是B的服务消费者。当A不可用引起了B的不可用,并将不可用像滚雪球一样放大到C和D时,雪崩效应就形成了。
那么Hystrix是如何容错的呢?
以下对该图做个简单讲解:
Zuul作为微服务架构中的微服务网关。微服务架构经过前几个组件的组合,已经有了基本的雏形了,那么我们为什么还要使用微服务网关呢?我们可以想象,一般情况下我们一个业务并不是只调用一个接口就可以完成一个业务需求。
如果让客户端直接与各个微服务通信,会有以下问题:
如图,微服务网关封装了应用程序的内部结构,客户端只须跟网关交互,而无须直接调用特定微服务接口。同时,还有以下优点:
为什么要同一管理微服务配置?
对于传统的单体应用,常常使用配置文件管理所有配置。例如一个Spring Boot 项目开发的单体应用,可以将配置内容放到application.yml文件中。如果需要切换环境,可以设置多个Profile,并在启用应用时指定spring.profile.active={profile}。
而在微服务架构中,微服务的配置管理一般有以下需求:
㈡ nacos和eureka的区别
nacos和eureka的范围不同,Nacos的阈值是针对某个具体Service的,而不是针对所有服务的;但Eureka的自我保护阈值是针对所有服务的。nacos支持CP和AP两种;eureka只支持AP。nacos使用netty,是长连接;eureka是短连接,定时发送。
Nacos与Eureka的保护方式不同
Eureka保护方式:当在短时间内,统计续约失败的比例,如果达到一定阈值,则会触发自我保护的机制,在该机制下,Eureka Server不会剔除任何的微服务,等到正常后,再退出自我保护机制。自我保护开关(eureka.server.enable-self-preservation: false)
Nacos保护方式:当域名健康实例 (Instance) 占总服务实例(Instance) 的比例小于阈值时,无论实例 (Instance) 是否健康,都会将这个实例 (Instance) 返回给客户端。这样做虽然损失了一部分流量,但是保证了集群的剩余健康实例 (Instance) 能正常工作。
㈢ Eureka工作流程
是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的。
注册中心服务端主要对外提供了三个功能:
服务提供者启动时,会通过 Eureka Client 向 Eureka Server 注册信息,Eureka Server 会存储该服务的信息,Eureka Server 内部有二层缓存机制来维护整个注册表
服务消费者在调用服务时,如果 Eureka Client 没有缓存注册表的话,会从 Eureka Server 获取最新的注册表
Eureka Client 通过注册、心跳机制和 Eureka Server 同步当前客户端的状态。
Eureka Client 是一个 Java 客户端,用于简化与 Eureka Server 的交互。Eureka Client 会拉取、更新和缓存 Eureka Server 中的信息。因此当所有的 Eureka Server 节点都宕掉,服务消费者依然可以使用缓存中的信息找到服务提供者,但是当服务有更改的时候会出现信息不一致。
服务的提供者,将自身注册到注册中心,服务提供者也是一个 Eureka Client。当 Eureka Client 向 Eureka Server 注册时,它提供自身的元数据,比如 IP 地址、端口,运行状况指示符 URL,主页等。
Eureka Client 会每隔 30 秒发送一次心跳来续约。 通过续约来告知 Eureka Server 该 Eureka Client 运行正常,没有出现问题。 默认情况下,如果 Eureka Server 在 90 秒内没有收到 Eureka Client 的续约,Server 端会将实例从其注册表中删除。
当服务进行正常关闭操作时,它会触发一个服务下线的REST请求给Eureka Server,告诉服务注册中心:“我要下线 了”。服务中心接受到请求之后,将该服务置为下线状态
有时我们的服务可能由于内存溢出或网络故障等原因使得服务不能正常的工作,而服务注册中心并未收到“服务下线”的请求。相对于服务提供者的“服务续约”操作,服务注册中心在启动时会创建一个定时任务,默认每隔一段时间 (默认为60秒)将当前清单中超时(默认为90秒)没有续约的服务剔除,这个操作被称为失效剔除。 可以通过 eureka.server.eviction-interval-timer-in-ms 参数对其进行修改,单位是毫秒。
我们关停一个服务,在Eureka面板看到一条警告: 这是触发了Eureka的自我保护机制。
当一个服务未按时进行心跳续约时,Eureka会统计最近15分钟心跳失败的服 务实例的比例是否超过了85%,当EurekaServer节点在短时间内丢失过多客户端(可能发生了网络分区故障)。在 生产环境下,因为网络延迟等原因,心跳失败实例的比例很有可能超标,但是此时就把服务剔除列表并不妥当,因 为服务可能没有宕机。Eureka就会把当前实例的注册信息保护起来,不予剔除。生产环境下这很有效,保证了大多 数服务依然可用。
Eureka 自我保护机制是为了防止误杀服务而提供的一个机制。当个别客户端出现心跳失联时,则认为是客户端的问题,剔除掉客户端;当 Eureka 捕获到大量的心跳失败时,则认为可能是网络问题,进入自我保护机制;当客户端心跳恢复时,Eureka 会自动退出自我保护机制。
如果在保护期内刚好这个服务提供者非正常下线了,此时服务消费者就会拿到一个无效的服务实例,即会调用失败。对于这个问题需要服务消费者端要有一些容错机制,如重试,断路器等。
了解完 Eureka 核心概念,自我保护机制,以及集群内的工作原理后,我们来整体梳理一下 Eureka 的工作流程:
1、Eureka Server 启动成功,等待服务端注册。在启动过程中如果配置了集群,集群之间定时通过 Replicate 同步注册表,每个 Eureka Server 都存在独立完整的服务注册表信息
2、Eureka Client 启动时根据配置的 Eureka Server 地址去注册中心注册服务
3、Eureka Client 会每 30s 向 Eureka Server 发送一次心跳请求,证明客户端服务正常
4、当 Eureka Server 90s 内没有收到 Eureka Client 的心跳,注册中心则认为该节点失效,会注销该实例
5、单位时间内 Eureka Server 统计到有大量的 Eureka Client 没有上送心跳,则认为可能为网络异常,进入自我保护机制,不再剔除没有上送心跳的客户端
6、当 Eureka Client 心跳请求恢复正常之后,Eureka Server 自动退出自我保护模式
7、Eureka Client 定时全量或者增量从注册中心获取服务注册表,并且将获取到的信息缓存到本地
8、服务调用时,Eureka Client 会先从本地缓存找寻调取的服务。如果获取不到,先从注册中心刷新注册表,再同步到本地缓存
9、Eureka Client 获取到目标服务器信息,发起服务调用
10、Eureka Client 程序关闭时向 Eureka Server 发送取消请求,Eureka Server 将实例从注册表中删除
参考链接: https://blog.csdn.net/qwe86314/article/details/94552801
㈣ 如何启动eureka服务
使用Eureka做服务发现
Zookeeper做注册中心的缺陷
Peter Kelley(个性化教育初创公司Knewton的一名软件工程师)发表了一篇文章说明为什么ZooKeeper用于服务发现是一个错误的做法,他主要提出了三个缺点[1]:
ZooKeeper无法很好的处理网络分区问题,当网络分区中的客户端节点无法到达Quorum时,会与ZooKeeper失去联系,从而也就无法使用其服务发现机制。
服务发现系统应该是一个AP系统,设计上针对可用性;而ZooKeeper是一个CP系统。
ZooKeeper的设置和维护非常困难,实际操作的时候也容易出错,比如在客户端重建Watcher,处理Session和异常的时候。
当然,Peter Kelley提出的这几个问题并不是不能克服的,并不能说明基于ZooKeeper就不能做好一个服务发现系统,但是我们可能有更简洁的方案来实现。
Eureka介绍
什么是Eureka
官方的介绍在这里Eureka wiki。Eureka是Netflix开源的一个RESTful服务,主要用于服务的注册发现。Eureka由两个组件组成:Eureka服务器和Eureka客户端。Eureka服务器用作服务注册服务器。Eureka客户端是一个java客户端,用来简化与服务器的交互、作为轮询负载均衡器,并提供服务的故障切换支持。Netflix在其生产环境中使用的是另外的客户端,它提供基于流量、资源利用率以及出错状态的加权负载均衡。
在我看来,Eureka的吸引力来源于以下几点:
开源:大家可以对实现一探究竟,甚至修改源码。
可靠:经过Netflix多年的生产环境考验,使用应该比较靠谱省心
功能齐全:不但提供了完整的注册发现服务,还有Ribbon等可以配合使用的服务。
基于Java:对于Java程序员来说,使用起来,心里比较有底。
spring cloud可以使用Spring Cloud, 与Eureka进行了很好的集成,使用起来非常方便。
Eureka架构
Netflix主要是在AWS中使用Eureka的,虽然同时也支持本地环境,但是了解AWS的一些基础概念对于理解Eureka的设计非常有帮助。
㈤ nacos和eureka的区别是什么
nacos和eureka的区别区别如下:
springcloud eureka是注册中心,负责微服务的注册与发现,起到承上启下的作用,在微服务架构中相当于人体的 大脑,很重要,nacos是阿里巴巴出的,功能类似eureka。
nacos的部署方式与springcloud eureka不太一样,euraka是需要创建springboot项目,然后将euraka服务端通过gav的方式加载进来,然后部署项目。nacos是直接从阿里巴巴nacos的官网下载jar包,启动服务。
Eureka Server:
之间通过复制的方式完成数据的同步,Eureka还提供了客户端缓存机制,即使所有的Eureka Server都挂掉,客户端依然可以利用缓存中的信息消费其他服务的API。综上,Eureka通过心跳检查、客户端缓存等机制,确保了系统的高可用性、灵活性和可伸缩性。
㈥ 字节三面:到底知不知道什么是Eureka
什么是服务注册?
首先我们来了解下,服务注册、服务发现和服务注册中心的之间的关系。
举个形象的例子,三者之间的关系就好像是供货商,顾客和商店。
首先各地的供货商会将各种商品提供给商店,然后顾客需要商品的时候会去商店购买。
注册中心就好比是这个商店,供货商的动作就是服务注册,商品就是注册的服务。
当部署的服务启动后,会注册到注册中心,消费者需要什么样的服务,就自己去注册中心拉取。
那么到底什么是服务注册,为什么要将服务注册到注册中心呢?
服务注册指的是服务在启动时将服务的信息注册到注册中心中,由注册中心统一对所有的注册的服务进行管理。
现在我们想想,假如你是消费者,你需要买一个商品,你可以去商店,也可以直接去供货商。
但是如果今天你要买很多商品,而且我们并不知道每个商品对应的供应商的地址,那么你就得挨家挨户的去跑供货商购买商品。
是不是就很麻烦了,倘若此时有一家商店,汇总了多家供货商的商品,那你是不是只需要去这一家商店就能购买到你需要的所有的商品了呢?
这样是不是就方便了。
在我们现实开发中,比如我们需要获取用户信息的时候,而此时,我们的用户服务只部署了一个节点,那我们就可以使用IP+端口的形式访问服务。
当此时我们的服务部署了10个节点后,我们可以通过域名访问,通过nginx转发到某一个节点上,访问该节点的服务。
使用过nginx的小伙伴们都知道,每当我们需要新增一个节点的时候,我们就需要去修改nginx的配置文件,一旦服务部署的节点过多,频繁修改配置文件就变成了一件极其麻烦的事情。
这个时候,我们的注册中心,就应该粉墨登场了。
注册中心一登场,我们就尽管部署服务节点,部署完成后,服务启动,服务的信息就会被注册到注册中心,我们就不需要担心是不是又要去修改配置文件了。
什么是服务发现?
服务发现有两种模式:一种是客户端发现模式,一种是服务端发现模式。Eureka采用的是客户端发现模式。
客户端发现模式就好比我是一个土豪顾客,我去了商店,我把所有的商品都买回家,需要的时候在这些商品里面寻找。
因为我是土豪,所以我当然不能忍受商店里有新品上架,而我却没有,所以我每隔一段时间就会商店增量获取最新的商品。
这就是Eureka中的Fetch Registry,抓取注册信息。
Eureka Client 从 Eureka Server 获取注册表信息并在本地缓存。
这里我们注意一下,Eureka Client并不是直接去服务注册表中获取数据,而是从ReadOnly缓存中获取数据。
并且会通过在上一个获取周期和当前获取周期之间获取增量更新,这些信息会定期更新(每30秒更新一次)。
获取的时候可能返回相同的实例。Eureka Client会自动处理重复信息。
因为我的土豪行为,我已经被商店老板记录在它的VVIP名单上了。可惜天有不测风云,我破产了,我再也不能这么土豪了,没办法,我告诉了老板我破产了,老板听了我的话,想都没想,直接从他的VVIP名单上将我的名字给剔除了,社会就是这么现实。
这就是Eureka中的Cancel,取消。
每一个微服务节点关闭时,Eureka Client会向Eureka Server发送一个取消请求。
Eureka Server收到你的取消请求后,就会将你从服务注册表中给剔除。
商店老板是个傲娇的人,她制定了一个规则,如果你是她VVIP名单上的人,你必须每隔一段时间就要去商店采购商品。
一旦你在一段时间内没有来采购,她就觉得你已经没有购买能力,不适合在她的VVIP名单上存在了。
她就会狠心的将你从她的VVIP名单上将我的名字给剔除了。
这就是Eureka中的Renew(更新 / 续借)
Eureka Client 内部具备一个内置的负载均衡器,它使用轮训(round-robin)负载算法。
在服务启动后,每隔一定周期(默认30秒)向Eureka Server发送心跳。
如果Eureka Server在多个心跳周期内(默认90秒)没有收到Eureka Client发送过来的心跳,Eureka Server将会在服务注册表中将该节点剔除。
当然了,服务发现去注册中心拉取的是服务的信息,然后需要从服务信息中获取到服务部署的节点信息,然后通过域名地址访问到该节点的服务。
就好像一家商店,因为空间太小,只是存放了一些商品的微缩模型,模型上写着该商品所属的供货商地址,我们去商店拿到该模型后,看到供货商的地址,然后我们就可以直接去供货商那儿直接购买商品了。
什么是注册中心,注册中心的作用?
注册中心就是一个管理器,各个服务提供者将服务注册到注册中心,由注册中心进行统一的存储和管理。
注册中心同时还有着判断服务是否可用,对于不可用的服务进行剔除的功能。
至于如何判断服务的可用性和如何剔除不可用的服务,后续会有详细的讲解。
什么是 Eureka,有什么作用?
Eureka采用CS架构,它分为两大组件。
一个是Eureka Server,注册中心服务端。
当各个微服务节点启动后,Eureka Server 会存储服务提供者注册上来的服务信息,并且提供二层缓存机制来维护整个注册中心。
另一个是Eureka Client,注册中心客户端。
Eureka Client是一个java客户端,它用来简化和Eureka Server交互。
Eureka Client 会拉取、更新和缓存 Eureka Server 中的信息。
因此当所有的 Eureka Server 节点都宕掉,服务消费者依然可以使用缓存中的信息找到服务提供者,但是当服务有更改的时候会出现信息不一致。
Eureka 架构详解
如下图所示,这是官网提供给我们的Eureka的架构图Eureka 的架构,主要分为 Eureka Server 和 Eureka Client 两部分,Eureka Client 又分为 Applicaton Service 和 Application Client,Applicaton Service 就是服务提供者,Application Client 就是服务消费者。
我们首先会在应用程序中依赖 Eureka Client,项目启动后 Eureka Client 会向 Eureka Server 发送请求,进行注册,并将自己的一些信息发送给 Eureka Server。
注册成功后,每隔一定的时间,Eureka Client 会向 Eureka Server 发送心跳来续约服务,也就是汇报健康状态。如果客户端长时间没有续约,那么 Eureka Server 大约将在 90 秒内从服务器注册表中删除客户端的信息。
Eureka Client 还会定期从 Eureka Server 拉取注册表信息,然后根据负载均衡算法得到一个目标,并发起远程调用,关于负载均衡在后面的课时会详细介绍,也就是 Ribbon 组件。
应用停止时也会通知 Eureka Server 移除相关信息,信息成功移除后,对应的客户端会更新服务的信息,这样就不会调用已经下线的服务了,当然这个会有延迟,有可能会调用到已经失效的服务,所以在客户端会开启失败重试功能来避免这个问题。
Eureka Server 会有多个节点组成一个集群,保证高可用。Eureka Server 没有集成其他第三方存储,而是存储在内存中。
所以 Eureka Server 之间会将注册信息复制到集群中的 Eureka Server 的所有节点。
这样数据才是共享状态,任何的 Eureka Client 都可以在任何一个 Eureka Server 节点查找注册表信息。
Eureka 的工作流程
Eureka 的自我保护机制
什么是自我保护机制
官方定义:自我保护模式正是一种针对网络异常波动时的安全保护措施,使用自我保护模式能使Eureka集群更加健壮稳定的运行。
为什么要开启自我保护机制?
如果Eureka Server在一定时间内(默认90s)(可优化)没有收到某一个服务节点的心跳,Eureka Server将会移除该服务实例。
但是在某些时候,遇到网络分区故障,服务节点实际上是正常存活状态,但是却无法和Eureka Server正常通信,此时如果没有引入自我保护机制,Eureka Server就会将该服务节点剔除。
自我保护模式的工作机制
如果15分钟内超过85%的客户端节点都没有正常的心跳,那么Eureka Server就会认为客户端与注册中心发生了网络故障,Eureka Server进入自我保护机制。
自我保护机制的缺点
如果在自我保护机制中,刚好某些服务节点非正常下线,但是Eureka Server并不会剔除该服务节点,服务消费者就会获取到一个无效的服务实例。
解决方案
① :关闭自我保护机制(不推荐)
② :切换请求或断路器,使用负载均衡的方式,设置当一个请求超过多少秒还未得到响应,速度切换请求到下一个注册服务,例如使用Ribbon+Hystrix配置负载均衡和断路器。
Eureka Server 进入自我保护机制后
1、Eureka Server不再从注册表中剔除因为长时间没有和注册中心续约的服务节点
2、Eureka Server仍然能够接受新服务的注册和查询请求,但是不会同步到其他Eureka Server节点上
3、网络正常后,当前Eureka Server节点会将新的服务节点信息同步到其他Eureka Server节点上
如何开启自我保护
通过
eureka.server.enable-self-preservation=true/false来开启或关闭自我保护机制。
其他关键配置:
清理失效服务节点的时间间隔:
eureka.server.evication-interval-timer-in-ms默认60s
续约间隔时间:
eureka.instance.lease-renewal-interval-in-seconds默认30s
续约到期时间:
eureka.instance.lease-expiration-ration-in-seconds默认90s
通过源码窥探Eureka是如何开启自我保护机制的
第一步,我们引入Eureka Server 依赖。
第二步,我们找到eureka-core jar包下的路径为com.netflix.eureka下的registry包
第三步,进入AbstractInstanceRegistry 类,找到evict方法,这个是定期剔除任务的线程最终执行的方法
第四步,我们找到isLeaseExpirationEnabled()方法的实现
第五步,我们注意到
numberOfRenewsPerMinThreshold这个变量很关键,它的含义是每分钟最小的续约次数
在服务注册register和服务下线cancel两个方法中会更新这个变量,更新该变量方法如下:
以上就是Eureka开启自我保护的整个逻辑流程。
解除自我保护机制
1.当服务的网络分区故障解除之后,客户端能够和服务进行交互时,在续约的时候,更新每分钟的续约数,当每分钟的续约数大于85%时,则自动解除。
2.重启服务
Eureka 的健康检查
其实很多框架的健康状态监控都是通过 actuator 来管理健康状态的,并且扩展了 health 端点。
所以说我们只要在项目中集成Actuator,我们就能管理监控项目的健康状态。
Eureka也是一样,我们可以将某些不健康的服务节点的状态告知Eureka Server,然后Eureka Server 会主动让其下线。
这个就是Eureka的健康检查。
如何实现Eureka-Actuator健康检查?
首先我们要在pom中依赖
spring-boot-starter-actuator。
第二步,配置文件中添加
eureka.client.healthcheck.enabled=true 配置
原理分析:
首先在 中根据 eureka.client.healthcheck.enabled 的值来决定是否要装配 EurekaHealthCheckHandler ,然后在 EurekaClientAutoConfiguration 中会注册 HealthCheck ,但我们注册完成后会有调用任务来进行状态的更新,在 com.netflix.discovery.InstanceInfoReplicator.run() 中会进行状态更新。
Eureka 的多级缓存机制
什么是多级缓存机制
Eureka Server 为了避免同时读取内存数据造成的并发冲突问题,采用了多级缓存机制提升服务请求的响应速度。
Eureka Server的缓存是通过一个只读,一个读写缓存来实现的。
一级缓存:concurrentHashMap<key,value>readOnlyCacheMap本质是HashMap,无过期时间,保存数据信息对外输出。
readOnlyCacheMap依赖于定时器的更新,通过与readWriteCacheMap的值做对比,以readWriteCacheMap为准。
responseCacheUpdateIntervalMs:readOnlyCacheMap缓存更新间隔,默认30s
二级缓存:LoaDing<key,value>readWriteCacheMap本质是Guava缓存,包含失效机制,保护数据信息对外输出。
:readWriteCacheMap 缓存过期时间,默认180s。
当服务节点发生注册,下线,过期,状态变更等变化时
1.在内存中更新注册表信息
2.同时过期掉readWriteCacheMap缓存,缓存清除只是会去清除readWriteCacheMap这个缓存, readOnlyCacheMap 只读 缓存并没有更新,也就说当客户端的信息发生变化之后, 只读缓存不是第一时间感知到的。只读缓存的更新只能依赖那个30秒的定时任务来更新。
3.一段时间后(默认30s),后台线程发现readWriteCacheMap缓存为空,于是也将readOnlyCacheMap中的缓存清空
4.当有服务消费者拉取注册表信息时,会调用ClassLoader的load方法,将内存中的注册表信息加载到各级缓存中,并返回注册表信息。
在Eureka Server 中会有两个线程,一个是定时同步两个缓存的数据,默认30s,一个是定时检测心跳故障,默认90s。
服务拉取
1.服务消费者,默认每30s,拉取注册表信息
2.从readOnlyCacheMap中获取信息,如果获取为空
3.从readWriteCacheMap中获取,如果还是为空
4.调用ClassLoader的load方法,将内存中的注册表信息加载到各级缓存中,并返回注册表信息。
Eureka的区域配置
当用户地理分布范围很广的时候,比如公司在上海、杭州、青岛等都有分公司的时候,一般都会有多个机房。
那么对于用户而言,当然是希望调用本地分公司的机房中的微服务应用。
比如:上海用户A,调用OAuth2服务,用户A当然希望调用上海机房里面的微服务应用。如果上海用户A调用杭州机房的OAuth2服务,就增加的延时时间。
所以我们希望一个机房内的服务优先调用同一个机房内的服务,当同一个机房的服务不可用的时候,再去调用其它机房的服务,以达到减少延时的作用。
为此,eureka提供了region和zone两个概念来进行分区,Eureka基于Amazon设计的,所以对于地域的区分也与Amazon一致,Amazon分为多个region,每个region包含多个zone,所以Eureka设计时也是可以设置region与zone,请求时可以优先选择与请求服务在同一个zone的服务。
基本配置
此时无论我们调用多少次,调用的都是shanghai下面的zone1下面的服务。
一般来说我们都会结合Ribbon来实现微服务的负载均衡,而Ribbon内部会有一些专门的负载策略算法,虽然刚刚我们说过会优先请求的是指定region下指定 Zone 区域的服务实例。
但有些时候比如当在Region=shanghai下没有可用的zone,系统会默认加载 DEFAULT_ZONE,或者说或者同区域的服务负载过高...等等,也会自动切换成其他区域的服务。
Eureka的重试机制
由于 Spring Cloud Eureka 实现的服务治理机制强调了 CAP 原理中的 AP,即可用性与可靠性,牺牲了一定的一致性(在极端情况下它宁愿接受故障实例也不要丢掉"健康"实例,如同如我们上面所说的自我保护机制)。
但不论是由于触发了保护机制还是服务剔除的延迟,引起服务调用到这些不正常的服务,调用就会失败,从而导致其它服务不能正常工作!
这显然不是我们愿意看到的,我们还是希望能够增强对这类问题的容错。所以,我们在实现服务调用的时候通常会加入一些重试机制。
从 Camden SR2 版本开始,Spring Cloud 就整合了 Spring Retry 来增强 RestTemplate 的重试能力,对于开发者来说只需通过简单的配置,原来那些通过 RestTemplate 实现的服务访问就会自动根据配置来实现重试策略。
开启Eureka的重试机制很简单,首先我们在pom中引入Spring Retry的依赖:
然后在配置文件中配置
spring.cloud.loadbalancer.retry.enabled参数来控制重试机制的开关,因为 Spring Retry默认是开启的,所以说我们只要引入依赖即可,如果说我们想要关闭的话只需要将 spring.cloud.loadbalancer.retry.enabled设置为false即可。
其实在SpringCloud的架构组件中无论是Fegin,Ribbon,还是Zuul都提供了重试机制,这些暂且不论,后续再讲到具体的组件时再进行具体的分析。
实战 Eureka 注册中心的部署
Eureka Server 项目搭建
1、创建一个 springcloud-eureka-server 的项目,然后在 pom 中增加
spring-cloud-starter-netflix-eureka-server 的依赖。
2.在pom.xml文件中新增
spring-cloud-starter-netflix-eureka-server依赖
3.在启动类
上使用 @EnableEurekaServer 开启 EurekaServer 的自动装配功能。
4.添加配置文件application.properties
5.启动项目,然后访问 http://localhost:8761/ ,可以看到 Eureka 的管理页面,表示 Eureka 启动成功了。
1、创建一个 springcloud-eureka-client 的项目,然后在 pom 中增加
spring-cloud-starter-netflix-eureka-client 的依赖。
2.在启动类
上使用 @EnableEurekaClient 开启 EurekaServer 的自动装配功能。
配置
eureka.client.serviceUrl.defaultZone 的地址,也就是刚刚启动的 Eureka Server 的地址, http://localhost:8761/eureka/ 。
启动客户端,然后刷新刚刚打开的Eureka主页,我们发现服务已经注册成功。
Eureka 注册中心添加密码认证
上面我们看到我们搭建好Eureka Server 后访问 http://localhost:8761/ ,没有登陆就可以直接看到 Eureka 的管理页面。
如果在实际使用中,注册中心地址有公网 IP 的话,必然能直接访问到,这样是不安全的。所以我们需要对 Eureka 进行改造,通过集成 Spring-Security 来进行安全认证,加上权限认证来保证安全性。
首先,在 pom.xml 中引入 Spring-Security 的依赖
然后在 application.properties 中加上认证的配置信息
最后增加Spring Security 配置类
这样我们启动Eureka Server成功后在访问 http://localhost:8761/ ,此时浏览器会提示你输入用户名和密码,输入正确后才能继续访问 Eureka 提供的管理页面。
总结
本章我们主要学习了Eureka相关知识,虽然Eureka已经停更了,但是很多公司还在使用它,而它也足够稳定,它所提供的功能也足够大多数公司使用。所以说现在面试中,Eureka相关题目还是经常出现的。反正学到了就是自己的。
祝愿大家早日成为大牛,有一头乌黑秀发的大牛。
㈦ Spring Cloud Eureka服务注册中心
服务治理:Spring Cloud Eureka
Spring Cloud Eureka是Spring Cloud Netflix微服务套件中的一部分,它基于Netflix
Eureka做了二次封装,主要负责完成微服务架构中的服务治理功能。Spring Cloud通过为
Eureka增加了Spring Boot风格的自动化配置,我们只需通过简单引入依赖和注解配置就能
让Spring Boot构建的微服务应用轻松地与Eureka服务治理体系进行整合。
在本章中,我们将指引读者学习下面这些核心内容,并构建起用于服务治理的基础设
施。
·构建服务注册中心
·服务注册与服务发现
。Eureka的基础架构
Eureka的服务治理机制
Eureka的配置
服务治理
服务治理可以说是微服务架构中最为核心和基础的模块,它主要用来实现各个微服务
实例的自动化注册与发现。为什么我们在微服务架构中那么需要服务治理模块呢?微服务
系统没有它会有什么不好的地方吗?
在最初开始构建微服务系统的时候可能服务并不多,我们可以通过做一些静态配置来
完成服务的调用。比如,有两个服务A和B,其中服务A需要调用服务B来完成一个业务
操作时,为了实现服务的高可用,不论采用服务端负载均衡还是客户端负载均衡,都需
要手工维护服务的具体实例清单。但是随着业务的发展,系统功能越来越复杂,相应一下的
微服务应用也不断增加,我们的静态配置就会变得越来越难以维护。并且面对不断发展的
业务,我们的集群规模、服务的位置、服务的命名等都有可能发生变化,如果还是通过手
工维护的方式,那么极易发生错误或是命名冲突等间题。同时,对于这类静态内容的维护
为了解决微服务架构中的服务实例维护问题,产生了大量的服务治理框架和产品。这
也必将消耗大量的人力。
些框架和产品的实现都围绕着服务注册与服务发现机制来完成对微服务应用实例的自动化
管理。
服务注册:在服务治理框架中,通常都会构建一个注册中心,每个服务单元向注册
中心登记自己提供的服务,将主机与端口号、版本号、通信协议等一些附加信息告
知注册中心,注册中心按服务名分类组织服务清单。比如,我们有两个提供服务A
的进程分别运行于192.168.0.100:8000和192.168.0.101:8000位置上,
另外还有三个提供服务B的进程分别运行于192.168.0.100:9000、
192.168.0.101:9000、192.168.0.102:9000位置上。当这些进程均启动,
并向注册中心注册自己的服务之后,注册中心就会维护类似下面的一个服务清单。
另外,服务注册中心还需要以心跳的方式去监测清单中的服务是否可用,若不可用
需要从服务清单中剔除,达到排除故障服务的效果。
服务名
位置
服务A
192.168.0.100:8000、192.168.0.101:8000
服务B
192.168.0.100:9000、192.168.0.101:9000、192.168.0.102:9000
服务发现:由于在服务治理框架下运作,服务间的调用不再通过指定具体的实例地
址来实现,而是通过向服务名发起请求调用实现。所以,服务调用方在调用服务提
供方接口的时候,并不知道具体的服务实例位置。因此,调用方需要向服务注册中
心咨询服务,并获取所有服务的实例清单,以实现对具体服务实例的访问。比如,
现有服务C希望调用服务A,服务C就需要向注册中心发起咨询服务请求,服务注
册中心就会将服务A的位置清单返回给服务C,如按上例服务A的情况,C便获得
了服务A的两个可用位置192.168.0.100:8000和192.168.0.101:8000。
当服务要发起调用的时候,便从该清单中以某种轮询策略取出一个位置来进行服
务调用,这就是后续我们将会介绍的客户端负载均衡。这里我们只是列举了一种简
单的服务治理逻辑,以方便理解服务治理框架的基本运行思路。实际的框架为了性
能等因素,不会采用每次都向服务注册中心获取服务的方式,并且不同的应用哦场景
在缓存和服务剔除等机制上也会有一些不同的实现策略。
㈧ Eureka工作原理
Eureka 作为 Spring Cloud 体系中最核心、默认的注册中心组件,研究它的运行机制,有助于我们在工作中更好地使用它。
回到上节的服务注册调用示意图,服务提供者和服务的消费者,本质上也是 Eureka Client 角色。整体上可以分为两个主体:Eureka Server 和 Eureka Client。
Eureka Server:注册中心服务端
注册中心服务端主要对外提供了三个功能:
服务注册 服务提供者启动时,会通过 Eureka Client 向 Eureka Server 注册信息,Eureka Server 会存储该服务的信息,Eureka Server 内部有二层缓存机制来维护整个注册表
提供注册表 服务消费者在调用服务时,如果 Eureka Client 没有缓存注册表的话,会从 Eureka Server 获取最新的注册表
同步状态 Eureka Client 通过注册、心跳机制和 Eureka Server 同步当前客户端的状态。
Eureka Client:注册中心客户端 Eureka Client 是一个 Java 客户端,用于简化与 Eureka Server 的交互。Eureka Client 会拉取、更新和缓存 Eureka Server 中的信息。因此当所有的 Eureka Server 节点都宕掉,服务消费者依然可以使用缓存中的信息找到服务提供者,但是当服务有更改的时候会出现信息不一致。
Register: 服务注册 服务的提供者,将自身注册到注册中心,服务提供者也是一个 Eureka Client。当 Eureka Client 向 Eureka Server 注册时,它提供自身的元数据,比如 IP 地址、端口,运行状况指示符 URL,主页等。
Renew: 服务续约 Eureka Client 会每隔 30 秒发送一次心跳来续约。 通过续约来告知 Eureka Server 该 Eureka Client 运行正常,没有出现问题。 默认情况下,如果 Eureka Server 在 90 秒内没有收到 Eureka Client 的续约,Server 端会将实例从其注册表中删除,此时间可配置,一般情况不建议更改。
服务续约的两个重要属性
Eviction 服务剔除 当 Eureka Client 和 Eureka Server 不再有心跳时,Eureka Server 会将该服务实例从服务注册列表中删除,即服务剔除。
Cancel: 服务下线 Eureka Client 在程序关闭时向 Eureka Server 发送取消请求。 发送请求后,该客户端实例信息将从 Eureka Server 的实例注册表中删除。该下线请求不会自动完成,它需要调用以下内容:
GetRegisty: 获取注册列表信息 Eureka Client 从服务器获取注册表信息,并将其缓存在本地。客户端会使用该信息查找其他服务,从而进行远程调用。该注册列表信息定期(每30秒钟)更新一次。每次返回注册列表信息可能与 Eureka Client 的缓存信息不同,Eureka Client 自动处理。
如果由于某种原因导致注册列表信息不能及时匹配,Eureka Client 则会重新获取整个注册表信息。 Eureka Server 缓存注册列表信息,整个注册表以及每个应用程序的信息进行了压缩,压缩内容和没有压缩的内容完全相同。Eureka Client 和 Eureka Server 可以使用 JSON/XML 格式进行通讯。在默认情况下 Eureka Client 使用压缩 JSON 格式来获取注册列表的信息。
获取服务是服务消费者的基础,所以必有两个重要参数需要注意:
Remote Call: 远程调用 当 Eureka Client 从注册中心获取到服务提供者信息后,就可以通过 Http 请求调用对应的服务;服务提供者有多个时,Eureka Client 客户端会通过 Ribbon 自动进行负载均衡。
默认情况下,如果 Eureka Server 在一定的 90s 内没有接收到某个微服务实例的心跳,会注销该实例。但是在微服务架构下服务之间通常都是跨进程调用,网络通信往往会面临着各种问题,比如微服务状态正常,网络分区故障,导致此实例被注销。
固定时间内大量实例被注销,可能会严重威胁整个微服务架构的可用性。为了解决这个问题,Eureka 开发了自我保护机制,那么什么是自我保护机制呢?
Eureka Server 在运行期间会去统计心跳失败比例在 15 分钟之内是否低于 85%,如果低于 85%,Eureka Server 即会进入自我保护机制。
Eureka Server 触发自我保护机制后,页面会出现提示:
Eureka Server 进入自我保护机制,会出现以下几种情况: (1 Eureka 不再从注册列表中移除因为长时间没收到心跳而应该过期的服务 (2 Eureka 仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用) (3 当网络稳定时,当前实例新的注册信息会被同步到其它节点中
Eureka 自我保护机制是为了防止误杀服务而提供的一个机制。当个别客户端出现心跳失联时,则认为是客户端的问题,剔除掉客户端;当 Eureka 捕获到大量的心跳失败时,则认为可能是网络问题,进入自我保护机制;当客户端心跳恢复时,Eureka 会自动退出自我保护机制。
如果在保护期内刚好这个服务提供者非正常下线了,此时服务消费者就会拿到一个无效的服务实例,即会调用失败。对于这个问题需要服务消费者端要有一些容错机制,如重试,断路器等。
通过在 Eureka Server 配置如下参数,开启或者关闭保护机制,生产环境建议打开:
再来看看 Eureka 集群的工作原理。我们假设有三台 Eureka Server 组成的集群,第一台 Eureka Server 在北京机房,另外两台 Eureka Server 在深圳和西安机房。这样三台 Eureka Server 就组建成了一个跨区域的高可用集群,只要三个地方的任意一个机房不出现问题,都不会影响整个架构的稳定性。
从图中可以看出 Eureka Server 集群相互之间通过 Replicate 来同步数据,相互之间不区分主节点和从节点,所有的节点都是平等的。在这种架构中,节点通过彼此互相注册来提高可用性,每个节点需要添加一个或多个有效的 serviceUrl 指向其他节点。
如果某台 Eureka Server 宕机,Eureka Client 的请求会自动切换到新的 Eureka Server 节点。当宕机的服务器重新恢复后,Eureka 会再次将其纳入到服务器集群管理之中。当节点开始接受客户端请求时,所有的操作都会进行节点间复制,将请求复制到其它 Eureka Server 当前所知的所有节点中。
另外 Eureka Server 的同步遵循着一个非常简单的原则:只要有一条边将节点连接,就可以进行信息传播与同步。所以,如果存在多个节点,只需要将节点之间两两连接起来形成通路,那么其它注册中心都可以共享信息。每个 Eureka Server 同时也是 Eureka Client,多个 Eureka Server 之间通过 P2P 的方式完成服务注册表的同步。
Eureka Server 集群之间的状态是采用异步方式同步的,所以不保证节点间的状态一定是一致的,不过基本能保证最终状态是一致的。
Eureka 分区 Eureka 提供了 Region 和 Zone 两个概念来进行分区,这两个概念均来自于亚马逊的 AWS: region :可以理解为地理上的不同区域,比如亚洲地区,中国区或者深圳等等。没有具体大小的限制。根据项目具体的情况,可以自行合理划分 region。 zone :可以简单理解为 region 内的具体机房,比如说 region 划分为深圳,然后深圳有两个机房,就可以在此 region 之下划分出 zone1、zone2 两个 zone。
上图中的 us-east-1c、us-east-1d、us-east-1e 就代表了不同的 Zone。Zone 内的 Eureka Client 优先和 Zone 内的 Eureka Server 进行心跳同步,同样调用端优先在 Zone 内的 Eureka Server 获取服务列表,当 Zone 内的 Eureka Server 挂掉之后,才会从别的 Zone 中获取信息。
Eurka 保证 AP
Eureka Server 各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而 Eureka Client 在向某个 Eureka 注册时,如果发现连接失败,则会自动切换至其它节点。只要有一台 Eureka Server 还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。
了解完 Eureka 核心概念,自我保护机制,以及集群内的工作原理后,我们来整体梳理一下 Eureka 的工作流程:
1、Eureka Server 启动成功,等待服务端注册。在启动过程中如果配置了集群,集群之间定时通过 Replicate 同步注册表,每个 Eureka Server 都存在独立完整的服务注册表信息
2、Eureka Client 启动时根据配置的 Eureka Server 地址去注册中心注册服务
3、Eureka Client 会每 30s 向 Eureka Server 发送一次心跳请求,证明客户端服务正常
4、当 Eureka Server 90s 内没有收到 Eureka Client 的心跳,注册中心则认为该节点失效,会注销该实例
5、单位时间内 Eureka Server 统计到有大量的 Eureka Client 没有上送心跳,则认为可能为网络异常,进入自我保护机制,不再剔除没有上送心跳的客户端
6、当 Eureka Client 心跳请求恢复正常之后,Eureka Server 自动退出自我保护模式
7、Eureka Client 定时全量或者增量从注册中心获取服务注册表,并且将获取到的信息缓存到本地
8、服务调用时,Eureka Client 会先从本地缓存找寻调取的服务。如果获取不到,先从注册中心刷新注册表,再同步到本地缓存
9、Eureka Client 获取到目标服务器信息,发起服务调用
10、Eureka Client 程序关闭时向 Eureka Server 发送取消请求,Eureka Server 将实例从注册表中删除
这就是Eurka基本工作流程
讲了 Eureka 核心概念、Eureka 自我保护机制和 Eureka 集群原理。通过分析 Eureka 工作原理,我可以明显地感觉到 Eureka 的设计之巧妙,通过一些列的机制,完美地解决了注册中心的稳定性和高可用性。
Eureka 为了保障注册中心的高可用性,容忍了数据的非强一致性,服务节点间的数据可能不一致, Client-Server 间的数据可能不一致。比较适合跨越多机房、对注册中心服务可用性要求较高的使用场景。