一、Eureka简介本文所有代码都会上传到git中,欢迎浏览项目git地址:https://github.com/839022478/Spring-Cloud中传统的应用程序,组件模块之间的调用是通过标准化和约束的接口来实现的,从而实现不同模块之间的良好协作。但是拆分成微服务后,每个微服务实例的网络地址可能会动态变化,数量也可能发生变化,使得原来硬编码的地址变得无用。服务注册和管理需要一个集中的组件。为了解决以上问题,出现了服务治理,就是对所有的服务信息和状态进行管理,也就是我们所说的注册中心1.1。比如我们做火车或者汽车,需要买票才能乘坐。我们只需要看看有没有车票(有没有服务),有的话就买车票(拿到登记表),然后搭车(打电话)。你不需要关心有多少辆车在运行这个过程。图:使用注册中心,我们不需要关心有多少provider,直接调用即可,那么注册中心有哪些呢?注册中心:Eureka、Nacos、Consul、Zookeeper本文讲解SpringCloud微服务下的Eureka,Eureka是Netflix开发的服务发现框架。它是一个RESTful服务,是服务发现和注册的基本组件。它是构建SpringCloud微服务的先决条件之一。它屏蔽了Server和client的交互细节,让开发者可以专注于业务。服务注册和发现主要包括服务端(EurekaServer)和客户端(EurekaClient)两部分服务端(EurekaServer):一个公共服务,为Client提供服务注册和发现的功能,维护向自己注册的Client的相关信息Information,同时为Client提供接口获取注册中心中其他服务的信息,使得动态变化的Client可以在服务之间相互调用。Client(EurekaClient):Client将自己的服务信息以一定的方式注册到Server,并在正常范围内保持自己的信息一致性,以便于其他服务发现自己,同时可以获取其他通过ServerInformation了解其所依赖的服务,完成服务调用,内置负载均衡器进行基本的负载均衡EurekaGIt官网:https://github.com/Netflix/Eureka1.2服务注册与发现服务注册与发现发现关系图:1.3clientFunctions和serverfunctions1.3.1Clientfunction注册:每个微服务在启动时,都会向注册中心注册自己的网络地址等信息,注册中心会存储(内存)这些信息。获取服务注册中心:服务消费者从注册中心查询服务提供者的网络地址,并使用该地址调用服务提供者。为了避免每次都要检查注册表信息,客户端会定时去服务端拉取注册表信息缓存在客户端本地。心跳:每个微服务通过一定的机制(心跳)与注册中心进行通信。如果注册中心长时间不与服务通信,该实例将被注销。Invocation:实际的服务调用,通过注册中心解析服务名与具体地址的对应关系,找到具体服务的地址,进行实际的调用。1.3.2服务器注册中心功能服务注册中心:记录每个微服务的信息,如服务名称、ip、端口等。注册中心提供查询API(查询可用的微服务实例)和管理API(用于服务注册和注销)。服务注册与发现:注册:向注册中心注册微服务信息。发现:查询可用微服务列表及其网络地址。服务检查:定期检查已注册的服务,如果发现某个实例长时间无法访问,则将其从注册中心中移除。2、Eureka单节点搭建2.1pom.xml在一些教程中,会引入spring-boot-starter-web。这个依赖其实是不需要的,因为spring-cloud-starter-netflix-eureka-server的依赖已经包含了。在pom依赖中可以org.springframework.cloudspring-cloud-starter-netflix-eureka-server2.2application.ymlserver:port:8500eureka:client:#是否向EurekaServer注册自己,默认为true,因为当前是服务器,所以设置为false,表示服务不会向eureka注册自己的信息register-with-eureka:false#是否从eurekaserver获取注册信息。因为是单节点,所以不需要同步其他节点的数据。使用falsefetch-registry:false#设置服务注册中心的URL,用于客户端和服务端通信service-url:defaultZone:http://localhost:8080/eureka/2.3服务端启动类在启动类中添加这个注解来标识服务作为配置中心@EnableEurekaServerimportorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.cloud.netflix.eureka.server。EnableEurekaServer;@EnableEurekaServer@SpringBootApplicationpublicclassEurekaServerApplication{publicstaticvoidmain(String[]args){SpringApplication.run(EurekaServerApplication.class,args);}}2.4启动我们启动EurekaDemoApplication,然后在浏览器中输入地址http://localhost:8500/来启动我们的Eureka,我们看看效果吧,看到这个之后画面,说明我们启动成功了~,但是此时我们的服务中还没有客户端注册。3、服务注册注意:我们需要在客户端pom中添加spring-boot-starter-web,否则服务无法正常启动3.1pom.xmlorg.springframework.bootspring-boot-starter-weborg.springframework.cloudspring-cloud-starter-netflix-eureka-client/复制代码dependency>3.2application.yml#注册中心eureka:client:#设置服务注册中心的URLservice-url:defaultZone:http://localhost:8500/eureka/#服务名称instance:appname:mxn3.3客户端启动类在客户端启动类中,我们需要添加@EnableDiscoveryClientimportorg.springframework.boot.SpringApplication;importorg.springframework。boot.autoconfigure.SpringBootApplication;importorg.springframework.cloud.client.discovery.EnableDiscoveryClient;@EnableDiscoveryClient@SpringBootApplicationpublicclassEurekaClientApplication{publicstaticvoidmain(String[]args){SpringApplication.run(EurekaClientApplication.class,args);}}3.4查看效果项目启动后,刷新http://localhost:8500/页面,我们可以发现服务注册成功并且在idea日志打印中可以看到DiscoveryClient_MXN/DESKTOP-5BQ3UK8-registrationstatus:204,说明注册成功。EurekaServer和EurekaClient之间的连接主要是通过心跳(Heartbeat)实现的,即EurekaClient定期向EurekaServer发送服务实例当前状态的报告,并在注册中心维护服务实例租约的有效性。EurekaClient会定时从EurekaServer拉取registry中的信息,并将信息缓存在本地,用于服务发现4.Eurekaendpoint官网地址:https://github.com/Netflix/eureka/wiki/Eureka-REST-operationsEurekaserver还提供了一个端点(eureka/apps/{applicaitonName})来查看注册服务的详细信息。applicaitonName是微服务的名称。比如这里我们访问http://localhost:8500/eureka/apps/mxn5.Eureka原理5.1本质上就是存放了各个client的注册信息。EurekaClient从EurekaServer同步获取服务注册列表。通过一定的规则选择一个服务来调用5.2Eureka架构图服务提供者:是一个eureka客户端,向EurekaServer注册和更新自己的信息,并可以从EurekaServer注册中心获取其他服务信息。ServiceRegistry:提供服务注册和发现的功能。每个EurekaClient向EurekaServer注册自己的信息,也可以通过EurekaServer获取其他服务的信息,以发现和调用其他服务。服务消费者:是一个eureka客户端,通过EurekaServer获取注册在其上的其他服务的信息,从而根据这些信息找到需要的服务,并发起远程调用。同步复制:EurekaServer之间注册中心信息的同步复制,使EurekaServer集群中不同注册中心的服务实例信息保持一致。远程调用:服务客户端之间的远程调用。注册:客户端向服务器注册自己的元数据以进行服务发现。Renewal:通过向Server发送心跳来维护和更新注册中心中服务实例元数据的有效性。当服务端在一定时间内没有收到来自客户端的心跳信息时,会将默认服务下线,并从注册中心中删除该服务实例的信息。离线:客户端关闭时,主动从服务端注销服务实例元数据。此时,客户端的服务实例数据将从服务器的注册表中删除。获取注册中心:Client向Server请求注册信息用于服务发现,从而发起服务间的远程调用。5.3Eureka自我保护有时候我们会看到这样的提示信息:EMERGENCY!EUREKAMAYBEINCRECTLYCLAIMINGINSTANCESAREUPWHENTHERE'RENOT.RENEWALSARELESSERTHANTHRESHOLDANDHENCETHEINSTANCESARENOTEPERIEDJUSTISSAFE.这是因为默认情况下,EurekaServer会发送Microservicelogout(90S)。但是当网络出现故障时,微服务与服务器的正常通信就无法进行了。上面的行为是非常危险的,因为微服务是正常的,不应该被注销。它的指导思想是保持健康和不健康而不是盲目注销我们也可以通过命令关闭自我保护功能:eureka:server:enable-self-preservation:false那么自我保护是如何触发的呢?自我保护机制的触发条件是:当每分钟心跳数(renewsLastMin)小于numberOfRenewsPerMinThreshold时,且自动保护模式开关(eureka.server.enable-self-preservation=true)被打开时上,自我保护机制将被触发,租约将不再自动到期。以上所有租约都小于numberOfRenewsPerMinThreshold。它是如何计算的?我们在eureka源码中可以得知:numberOfRenewsPerMinThreshold=expectedNumberOfRenewsPerMin*renewalpercentage(defaultis0.85)expectedNumberOfRenewsPerMin=numberofcurrentlyregisteredapplicationinstancesx2当前注册的应用实例数x2是因为,默认情况下,注册的应用实例每半分钟一次续约,每分钟心跳两次,所以x2例如:我们有10个服务,每分钟期望续约次数:10*2=20,期望阈值:20*0.85=17,当小于17时,会触发自我保护机制5.4健康检查由于服务端和客户端通过心跳来维护服务状态,只有状态为UP的服务才能被访问。查看eureka界面中的状态。比如心跳一直正常,服务一直up,但是服务DB(数据库)无法连接,无法正常提供服务。此时,我们需要将微服务的健康状态同步到服务端。只需启动eureka的健康检查。这样微服务就会把自己的健康状态同步到eureka。配置如下。客户端配置:将自己的健康状态传播给服务端。eureka:client:healthcheck:enabled:true5.5Eureka监听事件springframework.stereotype.Component;importjava.time.LocalDateTime;@ComponentpublicclassCustomEvent{@EventListenerpublicvoidlisten(EurekaInstanceCanceledEventevent){System.out.println(LocalDateTime.now()+"服务下线事件:"+event.getAppName()+"---"+event.getServerId());//hairpin}@EventListenerpublicvoidlisten(EurekaInstanceRegisteredEventevent){InstanceInfoinstanceInfo=event.getInstanceInfo();System.out.println(LocalDateTime.now()+"服务上线事件:"+instanceInfo.getAppName()+"---"+instanceInfo.getInstanceId());}@EventListenerpublicvoidlisten(EurekaInstanceRenewedEventevent){System.out.println(LocalDateTime.now()+"服务更新/心跳上报事件:"+event.getAppName()+"---"+event.getServerId());}@EventListenerpublicvoidlisten(EurekaRegistryAvailableEventevent){System.out.println(LocalDateTime.now()+"注册中心可用事件");}@EventListenerpublicvoidlisten(EurekaServerStartedEventevent){System.out.println(LocalDateTime.now()+"注册中心启动event");}}5.6Renew:服务续约EurekaClient每30秒发送一次心跳来续约。通过续约通知EurekaServer,EurekaClient运行正常,没有问题。默认情况下,如果EurekaServer在90秒内没有收到来自EurekaClient的更新,服务器将从其注册表中删除该实例。这个时间是可以配置的,一般不建议改。5.6服务下架如果EurekaClient注册后既没有续费也没有下线(服务崩溃或网络异常等原因),则该服务的状态为未知状态,不保证可以从服务端获取到服务实例。反馈,所以需要下架服务,定期清理这些不稳定的服务。该方法会批量移除注册表中所有过期的租约。清除是一个定时任务,默认每60秒执行一次。60秒延时、60秒间隔消除限制:1、自我保护时不清除。2.分批清除。6.Eureka缺陷由于集群间的同步复制是通过HTTP进行的,基于网络的不可靠性,集群内EurekaServer之间的注册信息难免会出现不同步的时间节点,不符合C在CAP(dataConsistency)7.总结中,我们讲解了eureka的节点搭建和原理。对于目前火热的微服务,我们非常有必要去了解Eureka。