目前主流的服务注册&发现的组件是 Nacos,但是 Eureka 作为老牌经典的服务注册&发现技术还是有必要学习一下,原因:
(1)一些早期的分布式微服务项目使用的是 Eureka,在工作中完全有可能遇到这种情况。
(2)后期的服务注册&发现组件/技术,都参考了 Eureka 设计和理念,学习了 Eureka 后, 我们上手 Nacos 容易很多,而且可以理解得更深刻。
在企业级项目中,服务消费访问请求会存在高并发现象。如果只有一个会员中心-提供服务,可用性很差——如果该模块宕机,那么整个分布式应用就不能使用了。所以,会员中心提供服务往往是一个集群,有多个会员中心-提供服务模块。
这时又会出现两个问题:
使用Eureka就可以解决上述问题。
图示是分布式架构,每个模块都在不同的主机上
服务治理即服务管理:当项目中有多个服务的时候,怎么去管理这些服务。
Eureka 实现服务治理:
在传统的 rpc (remote procedure call)远程调用框架中,每个服务与服务之间的依赖关系比较复杂,管理也比较困难,所以需要管理服务之间的依赖关系。服务治理实现服务调用、负载均衡、容错等功能,实现服务发现与注册。
二说分布式开发
演示创建单机版的Eureka Server,集群版的后面再使用。
(1)创建 e-commerce-eureka-server-9001 微服务模块 [作为注册中心]
选中父项目并右键--New--Module--Maven--直接点击next--根据下图配置--Finish
(2)修改本模块的pom.xml,加入依赖
<!--引入相关依赖,版本都使用父项目声明的版本--> <dependencies> <!--引入Eureka Server场景启动器,使用版本仲裁--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> <!--web-starter--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--actuator-starter 是 springboot程序的监控系统,可以实现系统的健康监测 可以通过http://localhost:9001/actuator看到相关的连接和信息--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!--test-starter--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <!--通用模块的jar包-e_commerce_center_common-api--> <dependency> <groupId>com.li.springcloud</groupId> <artifactId>e_commerce_center_common-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>
(3)创建application.yml,配置服务端口
server: port: 9001 #配置Eureka-server eureka: instance: hostname: localhost #服务实例名 client: #如果Eureka是一个集群,那么相互两个Eureka之间也可以当做对方为客户端 #配置是否向注册中心注册自己 register-with-eureka: false #表示自己就是注册中心,作用是维护注册的服务实例,不需要去检索服务 fetch-registry: false service-url: #设置于 Eureka server 的交互模块,查询服务和注册服务都需要依赖这个地址 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
(4)创建主启动类 EurekaApplication.java
package com.li.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; /** * @author 李 * @version 1.0 */ @EnableEurekaServer //表示该程序作为EurekaServer @SpringBootApplication public class EurekaApplication { public static void main(String[] args) { SpringApplication.run(EurekaApplication.class,args); } }
启动主程序,在浏览器访问设置的ip+端口,已经能够看到Eureka的监控页面:
将member-service-provider-10000作为EurekaClient,注册到注册中心(e-commerce-eureka-server-9001),成为服务提供者
(1)在本模块的pom.xml中引入EurekaClient依赖
<!--引入EurekaClient场景启动器starter--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
(2)修改本模块的application.yml,添加如下配置:
#配置Eureka-Client eureka: client: register-with-eureka: true #将自己注册到EurekaServer #表示从EurekaServer抓取注册信息 fetch-registry: true service-url: #表示将自己注册到哪个EurekaServer defaultZone: http://localhost:9001/eureka instance: # 消费端地址 ip-address: localhost #以IP地址的方式向eureka进行注册,域名变ip prefer-ip-address: true
(3)在本模块的主启动类添加注解@EnableEurekaClient,将该程序标识为EurekaClient
(4)完成测试:
先启动EurekaServer(e-commerce-eureka-server-9001),再启动EurekaServer(member-service-provider-10000),然后在浏览器中访问EurekaServer的监控页面,可以看到注册中心已经检测到一个Eureka实例:
将member-service-consumer-80也作为EurekaClient注册到注册中心(e-commerce-eureka-server-9001),并且可以拉取注册中心提供的服务信息。
步骤、代码和2.3.1一致:
(1)修改本模块的pom.xml,添加EurekaClient的依赖
(2)在本模块的application.yml中进行EurekaClient的配置
(3)在本模块的主启动类添加注解@EnableEurekaClient,将该程序标识为EurekaClient
(4)先启动EurekaServer,再启动本模块,然后在浏览器中访问EurekaServer的监控页面,可以看到注册中心已经检测到本模块的EurekaClient实例:
如果上面的Status显示的是电脑名、localhost而不是ip地址,解决方案:
配置Eureka时Status显示的是电脑名而不是localhost及ipAddr显示为本机ip的问题
在默认情况下,Eureka会启动自我保护模式(如图红字)
Eureka自我保护机制
默认情况下,Eureka Client定时向Eureka Server端发送心跳包。如果Eureka Server在一定时间内没有收到某个微服务实例的心跳,Eureka Server将会注销该实例(默认90s)
但是当网络分区故障发生(延时、卡顿、拥挤)时,微服务与Eureka Server之间无法正常通信,以上的注销行为可能变得非常危险了——因为微服务本身其实是健康的,此时本不应该注销这个微服务的。
Eureka 通过“自我保护模式”来解决这个问题——当EurekaServer节点在短时间内丢失过多客户端时,Eureka Server 就会进入自我保护模式。开启自我保护模式之后,不会剔除微服务。因为客户端还能发送心跳,可能只是网络延迟问题。
综上,自我保护是一种应对网络异常的安全保护措施。它的架构哲学是宁可同时保留所有微服务(健康的、不健康的微服务都会保留),也不盲目注销任何健康的微服务。
一句话:开启自我保护模式后,如果某时刻某一个微服务不可用了,Eureka不会立刻清理,依旧会对该服务的信息进行保存。
CAP原则:分布式系统中,C:一致性;A:可用性;P:分区容错性。CAP理论详解
验证下 Eureka 的自我保护机制:
启动 member-service-provider-10000 和 e-commerce-eureka-server-9001
让 member-service-provider-10000 正确的注册
然后关闭 member-service-provider-10000,观察注册的 member-service-provider-10000 服务是否还在
注意不能通过idea直接关闭,详见:自我保护机制开启了但是服务还是"被删掉了"
在生产环境中一般不禁用自我保护模式
在Eureka Server端的配置文件中:
#配置Eureka-server eureka: server: enable-self-preservation: false #禁用自我保护模式