Eureka 入门使用
Eureka的使用场景
Eureka解决的是对服务如何去调用的问题
现在有A、B、C、D四个服务,它们之间会互相调用(而且IP地址很可能会发生变化),一旦某个服务的IP地址变了,那服务中的代码要跟着变,手动维护这些静态配置(IP)非常麻烦!
解决的方案
创建一个E服务,将A、B、C、D四个服务的信息都注册到E服务上,E服务维护这些已经注册进来的信息
A、B、C、D四个服务都可以拿到Eureka(服务E)那份注册清单。A、B、C、D四个服务互相调用不再通过具体的IP地址,而是通过服务名来调用!
Eureka组件细节
-
服务注册中心 Eureka Server
专门用于给其他服务注册
-
Eureka client 注册到注册中心的服务
- 服务提供者
- 服务消费者
- 允许一个服务既是提供者又是消费者
治理机制
Eureka client
服务提供者
- 服务注册
启动的时候会通过发送REST请求的方式将自己注册到Eureka Server上,同时带上了自身服务的一些元数据信息。
- 服务续约
在注册完服务之后,服务提供者会维护一个心跳(每30s定时向EurekaServer 分发起请求)用来持续告诉Eureka Server: "我还活着 ”
- 服务下线
当服务实例进行正常的关闭操作时,它会触发一个服务下线的REST请求给Eureka Server, 告诉服务注册中心:“我要下线了 ”。
服务消费者
- 获取服务
当我们启动服务消费者的时候,它会发送一个REST请求给服务注册中心,来获取上面注册的服务清单
-
服务调用
服务消费者在获取服务清单后,通过服务名可以获得具体提供服务的实例名和该实例的元数据信息。在进行服务调用的时候,优先访问同处一个Zone中的服务提供方。
Eureka Server
失效剔除
默认每隔一段时间(默认为60秒) 将当前清单中超时(默认为90秒)没有续约的服务剔除出去。
自我保护
EurekaServer 在运行期间,会统计心跳失败的比例在15分钟之内是否低于85%(通常由于网络不稳定导致)。 Eureka Server会将当前的实例注册信息保护起来, 让这些实例不会过期,尽可能保护这些注册信息。
Eureka自我保护机制,通俗的将就是好四不如赖活着。当Eureka通过心跳加测到服务可能出不正常状态(15分之内心跳失败的比例是否低于85%),可能是由于网络原因,服务本身是正常的,此时不应该注销服务,Eureka会保护服务注册表中的信息,不在删除也不会注销该服务,知道退出保护模式。
在springcloud 中可以使用eureka.server.enable-self-preservation=false 机制启动自动保护机制–不推荐
使用步骤
Eureka server
1.新建一个Modul用来当作Eureka Server
2.pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>SpringCloud</artifactId>
<groupId>com.wxw</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud-eureka-7001</artifactId>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-eureka -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
<!-- 热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
</project>
需要注意的是导包时候 用spring-cloud-starter-eureka-server,server 和client是不同的
3.配置yml
server:
port: 7001
#Eureka配置
eureka:
instance:
hostname: localhost #Eureka服务端的实例名字
client:
register-with-eureka: false #表示是否向eureka注册中心注册自己
fetch-registry: false #如果为false,则表示自己为注册中心
service-url: #监控页面
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
Eureka默认有自己的端口
public static final String PREFIX = "eureka.client";
public static final String DEFAULT_URL = "http://localhost:8761/eureka/";
public static final String DEFAULT_ZONE = "defaultZone";
4.在启动类上使用注解 @EnableEurekaServer 表示启用EurekaServer
package com.wxw.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServer_7001 {
public static void main(String[] args) {
SpringApplication.run(EurekaServer_7001.class,args);
}
}
Eureka provider
1.pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.6.RELEASE</version>
</dependency>
spring-cloud-starter-eureka
2.添加Eureka 配置到yml
#Eureka 配置,服务注册到哪里
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka/ #注册地址
instance-id: springcloud-provider-dept-8001 #修改eureka上的默认描述信息
3.启动类加入注解 @EnableEurekaClient
package com.wxw.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class DeptProvider_8001 {
public static void main(String[] args) {
SpringApplication.run(DeptProvider_8001.class,args);
}
}
监控
可以访问配置的架空页面去查看信息
http://localhost:7001/eureka/
描述服务状态的链接这个时候是404的,我们可以引入 spring-boot-starter-actuator 来配置想要显示的端口状态
1.引入包
<!-- 端口监控信息-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2.在yml配置限要显示的参数 自定义的参数
#info配置
info:
app.name: springcloud_Demo
zuozhe: wangxiaowa
Eureka Discovery
在团队开发中可能需要提供一个服务发现接口告知 调用者 当前的服务实例的相关信息。
1.在controller 添加接口
@GetMapping("/dept/discovery")
public Object discovery(){
List<String> services =client.getServices();
System.out.println("discovery=>services"+services);
//得到一个具体的微服务信息
List<ServiceInstance> instances=client.getInstances("SPRINGCLOUD-PROVIDER-DEPT");
for (ServiceInstance serviceInstance:instances) {
System.out.println(serviceInstance.getHost()+"\t"+
serviceInstance.getInstanceId()+"\t"+
serviceInstance.getScheme()+"\t"+
serviceInstance.getServiceId()+"\t"+
serviceInstance.getMetadata()+"\t"+
serviceInstance.getPort()+"\t"+
serviceInstance.getUri()+"\t"
);
}
return client;
}
2.在启动类上添加注解
@EnableDiscoveryClient
Eureka 的集群搭建
eureka可以搭建集群,主要的思路就是,在项目中创建多个eureka server的服务。
主要是在配置application.yml上有一些区别
server:
port: 7001
#Eureka配置
eureka:
instance:
hostname: eureka7001.com #Eureka服务端的实例名字
client:
register-with-eureka: false #表示是否向eureka注册中心注册自己
fetch-registry: false #如果为false,则表示自己为注册中心
service-url: #监控页面
# 单机配置
# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #注册地址
defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/ #注册地址
server:
port: 7002
#Eureka配置
eureka:
instance:
hostname: eureka7002.com #Eureka服务端的实例名字
client:
register-with-eureka: false #表示是否向eureka注册中心注册自己
fetch-registry: false #如果为false,则表示自己为注册中心
service-url: #监控页面
# 单机配置
# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #注册地址
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7003.com:7003/eureka/ #注册地址
server:
port: 7003
#Eureka配置
eureka:
instance:
hostname: eureka7003.com #Eureka服务端的实例名字
client:
register-with-eureka: false #表示是否向eureka注册中心注册自己
fetch-registry: false #如果为false,则表示自己为注册中心
service-url: #监控页面
# 单机配置
# defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #注册地址
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/ #注册地址
原理就是让每一个结点都引用其他两个结点,当其中一个结点故障还有其他的结点可以使用
在服务题供着的注册地址上配置三个节点的地址
#Eureka 配置,服务注册到哪里
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka70012.com:7002/eureka/,http://eureka7003.com:7003/eureka/
instance:
instance-id: springcloud-provider-dept-8001 #修改eureka上的默认描述信息
Eureka 与Zookeeper的区别
定位:都可以用作服务注册中心
著名的CAP理论指出,一个分布式系统不可能同时满足C(一致性)、A(可用性)和P(分区容错性)。由于分区容错性在是分布式系统中必须要保证的,因此我们只能在A和C之间进行权衡。在此Zookeeper保证的是CP, 而Eureka则是AP。
CAP理论:
C (Consistency)是指一致性,当一个process(过程)修改了某个值之后,其他的process读取的数据是,更新后的数据。一致性也分为弱一致性和强一致性。
弱一致性是可以允许process获得的数据是跟新之前的数据,或是等待一段时间后才修改的数据。DNS系统
强一致性是process获得数据必须是修改之后的数据。 银行账户信息
A (Availability) 是指可用性,“A”是指可用性。即系统总是能够为用户提供连续的服务能力。当用户发出请求是,系统能给出响应(成功或者失败),而且是立即给出响应,而不是等待其他事情完成才响应。如果需要等待某件事情完成才响应,那么“可用性”就不存在了。
P (Partition tolerance)是指容错性。任何一个分布式计算系统都是由多个节点组成的。在正常情况下,节点与节点之间的通信是正常的。但是在某些情况下,节点之间的通信会 断开,这种断开成为“Partition”。在分布式计算的实现中,Partition是很常见的,因为节点不可能永远不出故障,尤其是对于跨物理地区的 海量存储系统而言,而容错性则可以保证如果只是系统中的部分节点不可用,那么相关的操作仍旧能够正常完成。
Zookeeper是保证CP
当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的注册信息,但不能接受服务直接down掉不可用。也就是说,服务注册功能对可用性的要求要高于一致性。
但是zk会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。问题在于,选举leader的时间太长,30 ~ 120s, 且选举期间整个zk集群都是不可用的,这就导致在选举期间注册服务瘫痪。在云部署的环境下,因网络问题使得zk集群失去master节点是较大概率会发生的事,虽然服务能够最终恢复,但是漫长的选举时间导致的注册长期不可用是不能容忍的。
Eureka是保证AP
Eureka看明白了这一点,因此在设计时就优先保证可用性。Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册或时如果发现连接失败,则会自动切换至其它节点,只要有一台Eureka还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。除此之外,Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:
-
Eureka不再从注册列表中移除因为长时间没收到心跳而应该过期的服务
-
Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用)
-
当网络稳定时,当前实例新的注册信息会被同步到其它节点中
因此, Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使整个注册服务瘫痪。