Netflix在设计Eureka时遵守的就是AP原则。
Eureka是Netflix的一个子模块,也是核心模块之一,Eureka是一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移。服务注册与发现对于微服务来说是非常重要的,有了服务与注册,只需要使用服务的标识符,就可以访问到服务,而不需要修改服务调用的配置文件。功能类似于dubbo的注册中心,比如:Zookeeper。
2、原理?
Spring Cloud封装了Netfilx公司开发的Eureka模块来实现服务注册和发现(请对比Zookeeper)
Eureka采用了C-S的设计架构。Eureka作为服务注册功能的服务器,它是服务注册中心。
而系统中其他服务器,通过Eureka的客户端连接到Eureka Server并维持心跳连接。这样系统的维护人员就可以通过Eureka server来监控系统中各个微服务是否正常运行。SpringCloud的其他模块(比如Zuul)就可以通过Eureka Server来发现系统中的其他微服务,并执行相关逻辑。
架构图:(与dubbo对比)
Eureka架构图
dubbo架构图
Eureka包含两个组件:Eureka Server和Eureka Client
1)、Eureka Server提供服务注册服务
各个节点启动后,会在EurekaServer中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在页面上直观的看到。
2)、EurekaClient第一个Java客户端,用户简化Eureka Server的交互,客户端同时也具备一个内置的、使用轮询负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳(默认周期是30秒),如果Eureka Server在多个心跳周期内没有连接到某个节点的心跳,EurekaServer将会从服务注册表中把这个服务节点移除(默认90秒)
3、三大角色?
1)、Eureka Server提供服务注册和发现
2)、Service Provide服务提供方将自身服务注册到Eureka,从而使服务消费方能够获取到。
3)、Service Consumer服务消费方从Eureka获取注册服务列表,从而能够消费服务。
4、构建步骤:
【1】、 microservicecloud-eureka-7001:eureka服务注册中心Module(服务端)
1)、 引入Eureka的方法一:POM.xml文件中添加:
<!--eureka-server服务端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
2)、配置yml文件:
server:
port: 7001
eureka:
instance:
hostname: eureka7001.com #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
#设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址(单机)。
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
3)、在主启动类上面,标注新组件的相关注解
@SpringBootApplication
@EnableEurekaServer // EurekaServer服务器端启动类,接受其它微服务注册进来
public class EurekaServer7001_App
{
public static void main(String[] args)
{
SpringApplication.run(EurekaServer7001_App.class, args);
}
}
【2】、服务提供者microservicecloud-provider-dept-8001相关配置修改(客户端)
1)、POM.xml修改(新增)
<!-- 将微服务provider侧注册进eureka -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
2)、*.yml文件修改
eureka:
client: #客户端注册进eureka服务列表内
service-url:
defaultZone: http://localhost:7001/eureka #对应server中提供的对外地址
3)、主启动类@EnableEurekaClient
@SpringBootApplication
@EnableEurekaClient //本服务启动后会自动注册进eureka服务中
public class DeptProvider8001_App
{
public static void main(String[] args)
{
SpringApplication.run(DeptProvider8001_App.class, args);
}
}
4)、测试server中是否包含该客户端
【3】、主机名:服务名称修改
在注册Eureka客户端的时候,进行实例化instance,并为其自命名id即可。同时添加访问IP地址显示:prefer-ip-address
eureka:
client: #客户端注册进eureka服务列表内
service-url:
defaultZone: http://localhost:7001/eureka
instance:
instance-id: microservicecloud-dept8001
prefer-ip-address: true #访问路径可以显示IP地址
【4】、微服务info内容详细信息
1)、在microservicecloud-provider-dept-8001的POM.xml中添加监控
<!-- actuator监控信息完善 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2)、在总项目POM.xml中添加
<build>
<finalName>microservicecloud</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<delimiters>
<delimit>$</delimit>
</delimiters>
</configuration>
</plugin>
</plugins>
</build>
3)、在microservicecloud-provider-dept-8001项目的application.yml配置文件中配置info
info:
app.name: atguigu-microservicecloud
company.name: www.atguigu.com
build.artifactId: $project.artifactId$
build.version: $project.version$
4)、效果图展示:
【5】、自我保护
1)、case
默认情况下,如果EurekaServer在一定时间内没有接收到每个微服务实例的心跳,Eureka将会注销该实例(默认90秒)。但是当网络分区故障发生时,微服务与EurekaServer无法正常通信,以上行为可能变得非常危险了——因为微服务本身是健康的,此时不应该注销这个微服务。Eureka通过“自我保护模式”来解决这个问题——当Eureka节点短时间内丢失过多客户端时(可能发生网络分区故障),那么这个节点就会进入自我保护模式。一旦进入该模式,Eureka就是保护服务注册表中的信息,不再删除服务注册表中的信息 (也就是不会注销任何微服务)。当网络故障恢复后,该Eureka Server自动退出自我保护模式。
设计思想:宁可保留错误的服务注册信息,也不盲目注销任何可能健康的服务实例。
综上,自我保护模式是一种应对网络异常的安全保护措施。从而让Eureka集群更加健壮、稳定。
在spring cloud中也可以使用eureka.server.enable-self-preservation=false禁用自我保护模式。(不推荐)
【6】、服务发现
1)、对于注册进eureka里面的服务,可以通过服务发现来获得该服务信息。
2)、修改microservicecloud-provider-dept-8001工程的DeptController
@Autowired
private DiscoveryClient client;
@RequestMapping(value = "/dept/discovery", method = RequestMethod.GET)
public Object discovery()
{
List<String> list = client.getServices();
System.out.println("**********" + list);
List<ServiceInstance> srvList = client.getInstances("MICROSERVICECLOUD-DEPT");
for (ServiceInstance element : srvList) {
System.out.println(element.getServiceId() + "\t" + element.getHost() + "\t" + element.getPort() + "\t"
+ element.getUri());
}
return this.client;
}
3)、DeptProvider8001_App主启动类,添加服务发现。
@EnableDiscoveryClient //服务发现
public class DeptProvider8001_App
4)、自测
【7】、集群发现
1)、创建注册中心:microservicecloud-eureka-7002,microservicecloud-eureka-7003
2)、修改pom.xml文件,为7002,7003添加热部署
<dependencies>
<!--eureka-server服务端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<!-- 修改后立即生效,热部署 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
3)、根据7001配置其他主配置类(复制即可)
4)、修改映射配置
(1)、找到hosts文件
(2)、修改hosts文件,添加如下内容
127.0.0.1 eureka7001.com
127.0.0.1 eureka7002.com
127.0.0.1 eureka7003.com
5)、3台Eureka服务器的yml配置
(1)、修改7001配置文件(红色部分为修改部分):
server:
port: 7001
eureka:
instance:
hostname: eureka7001.com #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
#单机 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址(单机)。
defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
(2)、添加7002配置文件
server:
port: 7002
eureka:
instance:
hostname: eureka7002.com #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
#defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址。
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7003.com:7003/eureka/
(3)、添加7003配置文件
server:
port: 7003
eureka:
instance:
hostname: eureka7003.com #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
#defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址。
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
6)、microservicecloud-provider-dept-8001微服务发布到上面3台eureka集群配置中,defultZone修改为三个服务列表。
eureka:
client: #客户端注册进eureka服务列表内
service-url:
#defaultZone: http://localhost:7001/eureka
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
instance:
instance-id: microservicecloud-dept8001
prefer-ip-address: true #访问路径可以显示IP地址
7)、效果图
【8】、Eureka与Zookeeper的区别
1)、Zookeeper保证了CP(C:一致性,P:分区容错性),Eureka保证了AP(A:高可用)
(1)、当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的信息,但不能容忍直接down掉不可用。也就是说,服务注册功能对高可用性要求比较高,但zk会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新选leader。问题在于,选取leader时间过长,30 ~ 120s,且选取期间zk集群都不可用,这样就会导致选取期间注册服务瘫痪。在云部署的环境下,因网络问题使得zk集群失去master节点是较大概率会发生的事,虽然服务能够恢复,但是漫长的选取时间导致的注册长期不可用是不能容忍的。
(2)、Eureka保证了可用性,Eureka各个节点是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点仍然可以提供注册和查询服务。而Eureka的客户端向某个Eureka注册或发现是发生连接失败,则会自动切换到其他节点,只要有一台Eureka还在,就能保证注册服务可用,只是查到的信息可能不是最新的。除此之外,Eureka还有自我保护机制,如果在15分钟内超过85%的节点没有正常的心跳,那么Eureka就认为客户端与注册中心发生了网络故障,此时会出现以下几种情况:
No1、Eureka不在从注册列表中移除因为长时间没有收到心跳而应该过期的服务。
No2、Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其他节点上(即保证当前节点仍然可用)
No3、当网络稳定时,当前实例新的注册信息会被同步到其他节点。
因此,Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像Zookeeper那样使整个微服务瘫痪。