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

本文带你掌握SpringCloud高可用服务注册Eureka

时间:2023-03-17 15:36:43 科技观察

什么是服务注册?服务注册:将服务的主机、端口、版本号、通信协议等信息注册到注册中心;什么是服务发现?服务发现:服务消费者向注册中心请求注册的服务列表,进而获取某个服务的主机、端口、版本号、通信协议等信息,从而实现对特定服务的调用;尤里卡是什么?Eureka是NetflixFirst的子模块之一,也是一个核心模块。Eureka采用C-S(client/server)设计架构,即Eureka由两个组件组成:Eurekaserver和Eurekaclient。EurekaServer(一个独立的项目)用于注册服务和实现服务的负载均衡和故障转移。它是服务的注册表。EurekaClient(我们的微服务)用于与EurekaServer交互并在其上获取注册。服务让交互变得非常简单,只需要通过服务标识就可以获取到服务。与spring-cloud的关系:Eureka是由Netflix(一家提供版权视频和云服务的公司)开发的。SpringCloud封装了Netflix开发的Eureka模块,实现服务注册和发现。二次封装;角色关系图:构建配置Eureka服务注册中心SpringCloud使用Eureka服务注册中心非常简单方便。SpringCloud中的Eureka服务注册中心其实就是一个SpringBoot项目。我们只需要引入相关的依赖和注解配置就可以让使用SpringBoot构建的微服务应用轻松的与Eureka集成。具体步骤如下:1、创建一个SpringBoot项目,添加SpringBoot相关依赖;34-springGCloud-service-eureka2.添加eureka依赖:org.springframework.cloudspring-cloud-starter-netflix-eureka-server3.在SpringBoot的入口类中添加@EnableEurekaServer注解,开启Eureka注册中心服务器4.在application.properties文件中配置Eureka服务注册中心信息:#Embeddedtimingtomcatportserver.port=8761#设置服务注册中心的hostnameeureka.instance.hostname=localhost#因为我们当前创建的应用是服务注册中心,不是普通应用。默认情况下,此应用程序将自己注册到注册表(也是它自己)。设置为false表示禁止这种自注册eureka的默认行为。client.register-with-eureka=false#表示不从服务端获取其他服务信息,因为是服务端本身,服务注册中心自己负责维护服务实例,不需要获取其他服务eureka.client.fetch-registry=false#指定服务注册中心的位置eureka.client.service-url.defaultZone=http://localhost:8761/eureka启动并测试Eureka服务注册中心1.完成以上工程构建后,我们可以启动它的SpringBoot程序,main方法运行;2、启动成功后,在浏览器地址栏访问我们的注册中心;向Eureka服务注册中心注册服务。我们前面搭建了服务提供者项目,然后我们就可以提供服务注册到Eureke注册中心,步骤如下:1.在服务提供者中添加eureka依赖,因为服务提供者向注册中心注册服务时需要连接eureka,所以需要eureka客户端的支持;org.springframework.cloudspring-cloud-starter-netflix-eureka-client2.在Eureka功能中激活EnableEurekaClient:在SpringBoot的入口函数处,添加@EnableEurekaClient注解,表示是eureka客户端,这样我的服务提供者就可以连接eureka注册中心了;3.配置服务名和注册中心地址#每隔2s,给服务器发一次心跳,证明我还“活着”把我踢出去eureka.instance.lease-expiration-duration-in-seconds=10#告诉服务实例使用IP作为链接的服务器,而不是取机器名eureka.instance.prefer-ip-address=true#TellServer,服务实例名eureka.instance.instance-id=34-springGCloud-service-goods#eureka注册中心连接地址eureka.client.service-url.defaultZone=http://localhost:8761/eureka4、启动服务提供者SpringBoot程序运行的main方法;5、启动运行后,在浏览器地址栏访问我们之前搭建的eureka注册中心,可以看到一个服务已经注册成功;从Eureka服务注册中心找到并消费服务我们搭建了一个服务注册中心,用这个服务注册中心注册服务。接下来,我们可以发现和消费服务。服务的发现由eureka客户端实现,服务的消费由Ribbon实现。也就是说,服务的调用需要eurekaclient和Ribbon,只有两者配合才能实现;Eureka客户端是Java客户端,用于连接Eureka服务器,与服务器交互,负载均衡,服务故障转移等;Ribbon是基于HTTP和TCP的客户端负载均衡器。使用Ribbon访问服务时,会扩展Eureka客户端的服务发现功能,实现从Eureka注册中心获取服务器列表,并通过Eureka客户端在Eureka客户端服务发现的基础上,实现对服务实例的选择策略,所以从而实现服务的负载均衡消费。接下来让服务消费者来消费服务:我们前面构建了服务消费者项目,然后我们就可以使用服务消费者通过注册中心来调用服务提供者了。步骤如下:1、在consumer项目中添加eureka的依赖,因为服务消费者从注册中心获取服务,需要连接eureka,所以需要eurekaclient的支持;org.springframework.cloudspring-cloud-starter-netflix-eureka-client2.激活Eureka中的EnableEurekaClient功能:在SpringBoot的入口函数处,通过添加@EnableEurekaClient注解,表明你是eureka客户端,这样我的服务消费者就可以使用eureka注册中心了;3.配置服务的名称和注册中心的地址:spring.application.name=34-springGCloud-service-portaleureka.client.service-url.defaultZone=http://localhost:8761/eureka4.我引入前面说了服务发现是由eureka客户端实现的,而真正的服务调用是由ribbon实现的,所以我们需要调用服务提供者使用ribbon来调用:@LoadBalanced//使用Ribbon实现负载均衡调用@BeanpublicRestTemplaterestTemplate(){returnnewRestTemplate();}增加了ribbon支持,那么调用的时候可以使用服务名来访问:restTemplate.getForEntity("http://34-SPRINGCLOUD-SERVICE-GOODS/service/goods",String.class).getBody();5.完成以上经过这些步骤,我们就可以启动消费者的SpringBoot程序,main方法运行;6、启动成功后,在浏览器地址栏访问我们的consumer,看能否正常调用远程服务提供者提供的服务;Eureka和Zookeeper著名的CAP理论指出分布式系统不能同时满足C(一致性)、A(可用性)和P(分区容错);因为在分布式系统中必须保证分区容错,所以我们只能在A和C之间做一个取舍。这里Zookeeper保证CP,而Eureka是APp的全称:Partitiontolerance(分区容错)主要是指网络问题,如:A、B、C三台机器不能互相ping通或者网络不通。这种情况在分布式系统中是允许的,而且很可能发生。我们不得不容忍这种情况的发生。当出现这种情况时,我们根据应用场景选择“ConsistencyC”或“AvailabilityA”。Zookeeper保证CP在ZooKeeper中。当master节点由于网络故障与其他节点失去联系时,剩余节点会重新选举leader,但问题是选举leader需要一定的时间,期间整个ZooKeeper集群不可用选举。这导致选举期间登记服务中断。在云部署环境中,由于网络问题导致ZooKeeper集群的主节点丢失是大概率事件。虽然最终可以恢复服务,但是在选举期间导致服务注册长时间不可用是不能容忍的。Eureka保证APEureka首先保证可用性,Eureka的每个节点都是平等的。部分节点挂掉,不影响正常节点的工作,其余节点仍可提供注册和查询服务。但是如果Eureka的客户端向某个Eureka注册或者发现连接失败,会自动切换到其他节点。只要一个Eureka还在,就可以保证注册服务可用(guaranteedavailability),但是查到的信息可能不是最新的(不保证强一致性)。因此,当Eureka由于网络故障而与部分节点失去联系时,只要有一个节点可用,就可以正常使用注册和查询服务,而不是像zookeeper一样瘫痪整个注册服务。Eureka首先保证可用性;Eureka注册中心高可用集群在这个微服务架构的分布式系统中,我们要充分考虑各个微服务组件的高可用,不能有单点故障。由于注册中心eureka本身也是一个服务,如果它只有一个节点,那么它可能会失败,以至于我们无法注册和查询服务,所以我们需要一个高可用的服务注册中心,这需要通过注册中心集群来解决。eureka服务注册中心本身也是一个服务。也可以看作是提供者和消费者。我们之前配置了:eureka.client.register-with-eureka=false,这样注册中心不注册自己,但是我们可以自己注册到其他注册中心;EurekaServer的高可用其实就是把自己注册成一个服务到其他的服务注册中心,这样就会形成一组相互注册的服务注册中心,进而实现服务列表。相互同步,在注册中心A上注册的服务可以复制并同步到注册中心B,这样注册的服务就可以从任意一个注册中心查询到,从而达到高可用。Eureka注册中心高可用集群搭建我们知道Eureka注册中心高可用集群是各个注册中心互相注册,所以:在8761配置文件中,让它的service-url指向8762和8763,在8762的配置文件让它的service-url指向8761和8763,在8763的配置文件中它的service-url指向8761和8762;由于两者相互指向,所以我们实际上搭建了一个三节点的服务注册集群eureka.client.service-url.defaultZone=http://eureka8762:8762/eureka/,http://eureka8763:8763/eureka/eureka.client.service-url.defaultZone=http://eureka8761:8761/eureka/,http://eureka8763:8763/eureka/eureka.client.service-url.defaultZone=http://eureka8761:8761/eureka/,http://eureka8762:8762/eureka/然后在本地的hosts文件中配置:C:\Windows\System32\drivers\etc\hosts127.0.0.1eureka8761127.0.0.1eureka8762127.0.0.1eureka8763运行时,配置在运行配置项目程序参数:--spring.profiles.active=eureka8761--spring.profiles.active=eureka8762--spring.profiles.active=eureka8763分别启动三个注册中心,访问三个注册中心页面,观察是否注册中心页面正常;在要注册的服务中配置Eureka注册中心高可用集群测试:#eureka注册中心连接地址eureka.client.service-url.defaultZone=http://eureka8761:8761/eureka,http://eureka8762:8762/尤里卡,http://eureka8763:8763/eureka启动serviceprovider服务,然后观察注册中心页面,可以看到服务会在三个注册中心注册成功;集群的注册中心是在真实项目中打包发布的,需要将Eureka发布到具体的服务器上面执行,打包部署其实和springboot中一样,对于properties文件,不同的环境会有不同配置文件;运行:java-jarsprinGCloud-eureka-server.jar--spring.profiles.active=eureka8762;java-jarsprinGCloud-eureka-server.jar--spring.profiles.active=eureka8762;java-jarsprinGCloud-eureka-server.jar--spring.profiles.active=eureka8763可以写一个shell脚本启动三个注册中心:#!/bin/shnohupjava-jar34-springGCloud-service-eureka-1.0.0.jar--spring.profiles.active=eureka8761>./logs/eureka8761.log&nohupjava-jar34-springGCloud-service-eureka-1.0.0.jar--spring.profiles.active=eureka8762>./logs/eureka8762.log&nohupjava-jar34-springGCloud-service-eureka-1.0.0.jar--spring.profiles.active=eureka8763>./logs/eureka8763.log&修改linuxhosts文件:vim/etc/hosts192.168.10.128eureka8761192.168.10.128eureka8762192.168.10.128eureka8763Eureka服务注册中心自我保护机制自我保护机制是Eureka注册中心的一个重要特性,当Eureka注册中心进入自我保护模式时,在Eureka服务器主页会输出如下警告信息:EMERGENCY!尤里卡可能错误地声称实例已启动,而实际上它们并未启动。续订少于阈值,因此为了安全起见,实例不会过期。小写是:紧急!尤里卡可能错误地声明了实例。续订次数少于阈值,因此为了安全起见,实例不会过期。在没有Eureka自我保护的情况下,如果EurekaServer在一定时间内没有收到微服务实例的心跳,EurekaServer会注销该Instance,但是当出现网络分区故障时,微服务和EurekaServer会无法正常通信,而上述行为可能会变得非常危险,因为微服务本身其实是正常的,此时不应该注销微服务。如果没有自我保护机制,那么EurekaServer会注销这个服务。Eureka通过“自我保护模式”解决了这个问题——当EurekaServer节点在短时间内丢失过多客户端时(可能会出现网络分区故障),那么这个微服务节点就会受到保护。一旦进入自我保护模式,EurekaServer将保护服务注册表中的信息,不会删除服务注册表中的数据(即不会注销任何微服务)。当网络故障恢复后,EurekaServer节点会自动退出自我保护模式。因此,自我保护模式是一种应对网络异常的安全保护措施。它的架构理念是同时保留所有微服务(健康和不健康的微服务都会被保留),而不是盲目地注销任何健康的微服务,使用自我保护模式可以让Eureka集群更加健壮和稳定。当然你也可以通过配置项:eureka.server.enable-self-preservation=false来关闭自我保护模式。关闭自我保护模式后,会出现红色:THESELFPRESERVATIONMODEISTURNEDOFF。如果出现网络/其他问题,这可能无法保护实例过期。但是EurekaServer的自我保护模式也会给我们带来一些麻烦,如果在保护期间服务提供者异常下线,服务消费者会得到一个无效的服务实例,调用就会失败。对于这个问题,服务消费者需要有一些容错机制,比如重试,断路器等,Eureka的自我保护模式是有意义的。激活该模式后,不会因为长时间未收到心跳而将过期的服务从注册列表中移除。而是等待修复,直到心跳恢复正常,才会自动退出。自我保护模式。该模式旨在避免网络分区故障导致服务不可用的问题。例如,两个微服务客户端实例A和B之间存在调用关系,A是消费者,B是提供者,但是由于网络故障,B未能及时向Eureka发送心跳更新,此时Eureka不能简单的将B从注册中心中移除,因为如果移除了,A将无法从Eureka服务器上获取到B注册的服务,但是此时B的服务是可用的;所以Eureka的自我保护模式最好开启。自我保护常用的几种配置如下:服务端配置:#测试时关闭自我保护机制,保证不可用的服务被及时踢出发送心跳,证明你还活着Outeureka.instance.lease-expiration-duration-in-seconds=10