一. Eureka 是什么?
Eureka是Netflix的一个子模块,也是核心模块之一。Eureka是一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故障转移。服务注册与发现对微服务架构来说是非常重要的,有了服务发现与注册,只需要使用服务的标识符,就可以访问服务,而不需要修改服务调用的配置文件了。功能类似于Dubbo的注册中心,比如Zookeeper。
二、Eureka的两大组件
Eureka Server
各个微服务节点启动后,会在Eureka Server 中进行注册,这样Eureka Server中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在页面中直观的看到。
Eureka Client
Eureka Client是一个Java客户端,用于简化Eureka的交互,客户端同时也具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,会向Eureka Server 发送心跳(默认周期30秒)。如果Eureka Server 在多个心跳周期内没有接收到某个节点的心跳,Eureka Server将会从服务注册表中把这个服务节点移除(90秒)。
三、如何构建
pom.xml文件引入
<!--eureka-server服务端 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency>
修改application.yml
server:
port: 7001
eureka:
instance:
hostname: localhost #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #设置与Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址。
主启动类
@SpringBootApplication @EnableEurekaServer//EurekaServer服务器端启动类,接受其它微服务注册进来 public class EurekaServer7001_App { public static void main(String[] args) { SpringApplication.run(EurekaServer7001_App.class, args); } }
访问 http://localhost:7001
搭建成功
四、将已有微服务注册进Eureka服务注册中心
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>
application.yml
eureka:
client: #客户端注册进eureka服务列表内
service-url:
defaultZone: http://localhost:7001/eureka
DeptProvider8001_App主启动类
@SpringBootApplication @EnableEurekaClient //本服务启动后会自动注册进eureka服务中 public class DeptProvider8001_App { public static void main(String[] args) { SpringApplication.run(DeptProvider8001_App.class, args); } }
先要启动EurekaServer,再访问http://localhost:7001/
五、actuator与注册微服务信息完善
1. 服务名称修改
eureka: client: #客户端注册进eureka服务列表内 service-url: defaultZone: http://localhost:7001/eureka instance: instance-id: microservicecloud-dept8001
2. 访问信息有IP信息提示
eureka: client: #客户端注册进eureka服务列表内 service-url: defaultZone: http://localhost:7001/eureka instance: instance-id: microservicecloud-dept8001 #自定义服务名称信息 prefer-ip-address: true #访问路径可以显示IP地址
3. 微服务info内容详细信息(点击超链接)
微服务工程添加
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency>
父工程添加
<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>
微服务application.yml 添加
info:
app.name: atguigu-microservicecloud
company.name: www.atguigu.com
build.artifactId: $project.artifactId$
build.version: $project.version$
效果,点击链接出现页面
六、eureka自我保护机制
某一时刻某一个微服务不可用了,eureka不会立刻清理, 依旧会对该微服务的信息进行保存
可以通过 eureka.server.enable-self-preservation=false 禁用自我保护机制
七、eureka 服务发现功能
对于注册进eureka里面的微服务,可以通过服务发现来获得该服务的信息
服务提供者的Controller, 开发一个用于服务发现的接口
@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; }
八、eureka集群配置
现有7001,7002,7003三台eureka机器
server:
port: 7001
eureka:
instance:
hostname: eureka7001.com #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
server:
port: 7002
eureka:
instance:
hostname: eureka7002.com #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7003.com:7003/eureka/
server:
port: 7003
eureka:
instance:
hostname: eureka7003.com #eureka服务端的实例名称
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
服务提供者, 配置三台eureka地址
eureka:
client: #客户端注册进eureka服务列表内
service-url:
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地址
服务消费者,配置三台eureka地址
server:
port: 80
eureka:
client:
register-with-eureka: false
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
九、作为服务注册中心,Eureka比Zookeeper好在哪里
CAP理论指出,一个分布式系统不可能同时满足C(一致性)、A(可用性)、P(分区容错性)。由于分区容错性P是在分布式系统中必须要保证的,因此我们之能在A和C之间进行权衡。
Zookeeper保证的是CP, 当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的注册信息,但不能接受服务直接down掉不可用。也就是说,服务注册的功能对可用性的要求要高于一致性。但是zk会出现这样一种情况,当Master节点因为网络故障与其它节点失去联系时,剩余节点会重新进行leader选举,问题在于,选举leader的时间过长,30~120s,且选举期间整个zk集群是不可用的,这就导致选举期间注册服务瘫痪,在云部署的环境下,因网络延迟使得zk集群失去Master节点是较大概率会发生的事,虽然服务最终能够恢复,但是漫长的选举时间导致的注册长期不可用是不能容忍的。
Eureka保证的是AP,在设计时优先保证可用性,Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点仍然可以提供服务注册和查询。而Eureka的客户端在连接时如果发现连接失败,会自动切换至其它节点,只要有一台Eureka还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保强一致性)。
除此之外,Eureka还有一种自我保护机制,默认如果在15分钟内超过85%的节点都没有正常心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:
- Eureka不再从注册列表移除因为长时间没收到心跳而应该过期的服务
- Eureka仍然能够接受新服务的注册和查询请求,但是不会同步到其它节点上
- 当网络稳定时,当前实例新的注册信息会被同步到其它节点上
因此,Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像Zookeeper那样使整个注册服务瘫痪。