Spring Cloud Eureka是Spring Cloud Netflix 微服务套件中的一部分,它基于Netflix Eureka做了二次封装,主要负责完成微服务架构中的服务治理功能。Spring Cloud 通过为Eureka增加了Spring Boot风格的自动化配置,我们只需通过引入依赖和注解配置就能让Spring Boot构建的微服务应用轻松的与Eureka服务治理体系进行整合。
服务治理
服务治理可以说是微服务架构中最为核心和基础的模块,主要用来实现各个微服务实例的自动化注册与发现。
使用服务治理的原因:在服务引用并不算多的时候,可以通过静态配置来完成服务的调用,但随着业务的发展,系统功能越来越复杂,相应的微服务也不断增加,此时静态配置会变得越来越难以维护。并且面对不断发展的业务,集群规模,服务的位置、服务的命名等都有可能发生变化,如果还是通过手工维护的方式,极易发生错误或是命名冲突等问题。同时,也将消耗大量的人力来维护静态配置的内容。为了解决微服务架构中的服务实例维护问题,就产生了大量的服务治理框架和产品。这些框架和产品的实现都围绕着服务注册与服务发现机制来完成对微服务应用实例的自动化管理。
服务注册
在服务治理框架中,通常都会构建一个注册中心
,每个服务单元向注册中心登记自己提供的服务,将主机与端口号、版本号、通信协议等一些附加信息告知注册中心,注册中心按服务名分类组织服务清单。比如:有两个提供服务A的进程分别运行于192.168.0.100:8000 和192.168.0.101:8000 位置上,还有三个提供服务B的进程分别运行于192.168.0.100:9000、192.168.0.101:9000、192.168.0.102:9000位置上。当这些进程都启动,并向注册中心注册自己的服务之后,注册中心就会维护类似下面的一个服务清单。另外,注册中心还需要以心跳的方式
去监测清单中的服务是否可用,若不可用需要从服务清单中剔除,达到排除故障服务的效果。
服务发现:
在服务治理框架的运作下,服务间的调用不再通过指定具体的实例地址来实现,而是通过向服务名发起请求调用实现。所以,服务调用方在调用服务提供方接口时,并不知道具体的服务实例位置。因此,调用方需要向注册中心咨询服务,并获取所有服务的实例清单,以实现对具体服务实例的访问。比如:以上述服务为例,有服务C希望调用服务A,服务C就向注册中心发起咨询请求,服务注册中心就会将服务A的位置清单返回给服务C,当服务C要发起调用时,便从该清单中以某种轮询策略取出一个位置来进行服务调用(客户端负载均衡
)。
服务注册中心:eureka-server
新建一个springboot 项目,其pom.xml如下:
4.0.0
org.springframework.boot
spring-boot-starter-parent
1.5.19.RELEASE
com.travis
springboot-demo
0.0.1-SNAPSHOT
springboot-demo
Demo project for Spring Boot
1.8
org.springframework.boot
spring-boot-starter-test
test
org.springframework.cloud
spring-cloud-starter-eureka-server
org.springframework.cloud
spring-cloud-dependencies
Dalston.RELEASE
pom
import
org.springframework.boot
spring-boot-maven-plugin
想要实现一个服务注册中心的功能非常简单,只需要在项目的启动类Application上使用@EnableEurekaServer注解即可
@EnableEurekaServer
@SpringBootApplication
public class SpringbootDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootDemoApplication.class, args);
}
}
默认情况下,该服务注册中心也会将自己作为客户端来尝试注册它自己,所以我们需要禁用它的客户端注册行为,只需要在application.properties配置文件中增加如下信息:
spring.application.name=eureka-server
server.port=8080
eureka.instance.hostname=localhost
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
启动application,访问 http://localhost:8080/
服务提供方
每一个实例注册之后需要向注册中心发送心跳,当client向server注册时,它会提供一些元数据,例如主机和端口,URL,主页等。Eureka server 从每个client实例接收心跳消息。 如果心跳超时,则通常将该实例从注册server中删除。
新建一个springboot项目,其pom.xml配置如下:
4.0.0
org.springframework.boot
spring-boot-starter-parent
1.5.19.RELEASE
com.travis.java
springboot-java
0.0.1-SNAPSHOT
springboot-java
Demo project for Spring Boot
1.8
Edgware.SR5
org.springframework.boot
spring-boot-starter-web
org.springframework.cloud
spring-cloud-starter
org.springframework.cloud
spring-cloud-starter-eureka
org.springframework.boot
spring-boot-starter-test
test
org.springframework.cloud
spring-cloud-dependencies
${spring-cloud.version}
pom
import
org.springframework.boot
spring-boot-maven-plugin
想要实现一个服务提供方也很简单,只要在项目的启动类Application上使用@EnableEurekaClient注解即可
@SpringBootApplication
@EnableEurekaClient
public class SpringbootJavaApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootJavaApplication.class, args);
}
}
在application.properties中进行如下配置
spring.application.name=eureka-client
server.port=9002
eureka.client.serviceUrl.defaultZone=http://localhost:8080/eureka/
通过spring.application.name属性,我们可以指定微服务的名称后续在调用的时候只需要使用该名称就可以进行服务的访问。
eureka.client.serviceUrl.defaultZone属性对应服务注册中心的配置内容,指定服务注册中心的位置。
使用server.port属性设置不同的端口。
启动注册中心和服务两个项目:
Eureka与Zookeep的区别
著名的CAP理论指出,一个分布式系统不可能同时满足C(一致性)、A(可用性)和P(分区容错性)。由于分区容错性P在是分布式系统中必须要保证的,因此我们只能在A和C之间进行权衡。
因此
Zookeeper保证的是CP。
Eureka则是AP。
1.Zookeeper保证CP
当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的注册信息,但不能接受服务直接down掉不可用。也就是说,服务注册功能对可用性的要求要高于一致性。但是zk会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。问题在于,选举leader的时间太长,30 ~ 120s, 且选举期间整个zk集群都是不可用的,这就导致在选举期间注册服务瘫痪。在云部署的环境下,因网络问题使得zk集群失去master节点是较大概率会发生的事,虽然服务能够最终恢复,但是漫长的选举时间导致的注册长期不可用是不能容忍的。
2.Eureka保证AP
Eureka看明白了这一点,因此在设计时就优先保证可用性。Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册或时如果发现连接失败,则会自动切换至其它节点,只要有一台Eureka还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。除此之外,Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:
Eureka不再从注册列表中移除因为长时间没收到心跳而应该过期的服务
Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用)
当网络稳定时,当前实例新的注册信息会被同步到其它节点中
因此, Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使整个注册服务瘫痪。