在微服务架构中,各微服务实例的一个重要能力就是可以快速上线或下线,进行水平扩展,并保证服务的可用性。如何保持服务消费者能够与不断上下线的服务进行正常通信,就需要依靠服务治理。
服务治理通过抽象将服务提供者与服务消费者进行隔离。消费者不需要知道具体服务提供者的真是地址,也不需要知道有多少个服务提供者可用;而服务提供者只需要将自己注册到服务治理服务器中即可;同时服务治理服务器能够发现并绕开有问题的服务实例,降低对应用的影响。Eureka提供相应的解决方案,主要包括三个概念:服务注册中心、服务提供者和服务消费者。
在实际调用过程中,一个服务消费者可能会调用多个服务提供者,同时也可能会作为服务提供者对外提供服务。
以下简单介绍如何搭建Eureka注册中心和服务注册,依赖Spring Boot 2.1.4.RELEASE和Spring Cloud Greenwich.SR1。
一、Eureka服务器
1.创建一个eureka_server的springboot项目
pom.xml文件如下:
4.0.0
com.kevin
eureka_server
0.0.1-SNAPSHOT
jar
eureka_server
http://maven.apache.org
UTF-8
org.springframework.boot
spring-boot-starter-parent
2.1.4.RELEASE
org.springframework.boot
spring-boot-starter-test
test
org.springframework.cloud
spring-cloud-starter-netflix-eureka-server
org.springframework.cloud
spring-cloud-dependencies
Greenwich.SR1
pom
import
2. application.properties
spring.application.name=eurekaServer
server.port=9101
eureka.instance.hostname=localhost
eureka.client.registerWithEureka=false
eureka.client.fetchRegistry=false
备注:registerWithEureka=false和fetchRegistry=false来表明自己是一个eureka server.
3. Application.java
package com.kevin.eureka_server;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class Application {
public static void main( String[] args ) {
new SpringApplicationBuilder(Application.class).web(WebApplicationType.SERVLET).run(args);
}
}
4. 启动访问http://127.0.0.1:9101/,可以看到Eureka Server管理后台
二、Eureka服务注册(eureka client)
1. 创建一个eureka_client的springboot项目,pom.xml如下:
4.0.0
com.kevin
eureka_client
0.0.1-SNAPSHOT
jar
eureka_client
http://maven.apache.org
UTF-8
org.springframework.boot
spring-boot-starter-parent
2.1.4.RELEASE
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.cloud
spring-cloud-dependencies
Greenwich.SR1
pom
import
2. application.properties
# 此处name一定不能有下划线,否则注册的服务不能被消费
spring.application.name=eurekaClient
server.port=9103
3. Application.java,@EnableDiscoveryClient能够让注册中心能够发现和扫描到该服务;也可使用@EnableEurekaClient,但其只支持Eureka不支持其他注册中心。
@SpringBootApplication
@EnableDiscoveryClient
public class Application {
public static void main( String[] args ) {
new SpringApplicationBuilder(Application.class).web(WebApplicationType.SERVLET).run(args);
}
}
4. 创建一个rest api, HelloController.java
@RestController
public class HelloController {
@RequestMapping("sayHello")
public String sayHello() {
System.out.println("收到请求");
return "Hello World";
}
}
6. 自我保护机制
1)Eureka服务器出现提示:EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY’RE NOT. RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.
原因:自我保护机制。
默认情况下,如果Eureka Server在一定时间内(默认90秒)没有接收到某个微服务实例的心跳,Eureka Server将会移除该实例。但是当网络分区故障发生时,微服务与Eureka Server之间无法正常通信,而微服务本身是正常运行的,此时不应该移除这个微服务,所以引入了自我保护机制。
自我保护机制的工作机制是如果在15分钟内超过85%的客户端节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,Eureka Server自动进入自我保护机制,此时会出现以下几种情况:
1、Eureka Server不再从注册列表中移除因为长时间没收到心跳而应该过期的服务。
2、Eureka Server仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上,保证当前节点依然可用。
3、当网络稳定时,当前Eureka Server新的注册信息会被同步到其它节点中。
因此Eureka Server可以很好的应对因网络故障导致部分节点失联的情况,而不会像ZK那样如果有一半不可用的情况会导致整个集群不可用而变成瘫痪。
解决方案:(适用于开发环境,生产环境不建议调整)
1、 EurekaServer注册中心关闭自我保护机制,修改检查失效服务的时间。
#关闭自我保护机制,保证不可用服务及时剔除
eureka.server.enable-self-preservation=false
#间隔3秒剔除
eureka.server.eviction-interval-timer-in-ms: 3000
2、EurekaClient修改减短服务心跳的时间。
#在收到最后一次心跳后等待的时间上限,超过则剔除,默认90秒
eureka.instance.lease-expiration-duration-in-seconds=10
#向注册中心发送心跳的时间间隔,默认30秒
eureka.instance.lease-renewal-interval-in-seconds=3
7. Eureka’s Health Checks健康检查
默认情况下,服务器端与客户端的心跳保持正常,应用程序就会始终保持“UP”状态,但是该机制并不能完全反应应用程序的状态。比如:微服务与Eureka Server的心跳正常,但是该微服务的数据源发生了问题(比如网络抖动,连不上数据源),根本无法正常工作。
可自定义实现更细粒度地控制健康检查。
1)开启健康检查
eureka.client.healthcheck.enabled=true
2)依赖springboot的actuator,pom.xml引入相关jar包
org.springframework.boot
spring-boot-starter-actuator
3)做完上面两步后重新注册服务,服务地址点击查看就不报异常了
4)实现springboot的healthcheck,HealthCheckIndicator .java根据需要自行检查并返回结果
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.boot.actuate.health.Status;
import org.springframework.stereotype.Component;
@Component
public class HealthCheckIndicator implements HealthIndicator{
@Override
public Health health() {
return new Health.Builder(Status.UP).build();
}
}
5)实现服务的健康检查,HealthCheckStatusHandler.java根据springboot的健康结果返回
package com.kevin.eureka_client.component.healthcheck;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.health.Status;
import org.springframework.stereotype.Component;
import com.netflix.appinfo.HealthCheckHandler;
import com.netflix.appinfo.InstanceInfo.InstanceStatus;
@Component
public class HealthCheckStatusHandler implements HealthCheckHandler{
@Autowired
private HealthCheckIndicator healthCheckIndicator;
@Override
public InstanceStatus getStatus(InstanceStatus instanceStatus) {
Status status=healthCheckIndicator.health().getStatus();
if(Status.UP.equals(status)) {
return InstanceStatus.UP;
}else {
return InstanceStatus.DOWN;
}
}
}
6)Eureka服务器会定时检查Eureka Client的健康状态,可以通过debug断点查看是否进入自定义的健康检查;通过/actuator/health可以查看服务状态
8. Spring Cloud Eureka 常用配置详解
Spring Cloud Eureka 主要分为下面三个模块的参数:
Eureka Server
Eureka Client
Eureka Instance
1) Eureka Server
Eureka Server 的配置参数格式:eureka.server.xxx。
enable-self-preservation 表示注册中心是否开启服务的自我保护能力。
renewal-percent-threshold 表示 Eureka Server 开启自我保护的系数,默认:0.85。
eviction-interval-timer-in-ms 表示 Eureka Server 清理无效节点的频率,默认 60000 毫秒。
更多 Eureka Server 参数配置可以看一下这个类:org.springframework.cloud.netflix.eureka.server.EurekaServerConfigBean
2)Eureka Client
Eureka Client 的配置参数格式:eureka.client.xxx。
register-with-eureka 表示此实例是否注册到 Eureka Server 以供其他实例发现。在某些情况下,如果你不想自己的实例被发现,而只想发现其他实例,配置为 false 即可。
fetch-registry 表示客户端是否从 Eureka Server 获取实例注册信息。
serviceUrl.defaultZone 表示客户端需要注册的 Eureka Server 的地址。
更多 Eureka Client 参数配置可以看一下这个类:
org.springframework.cloud.netflix.eureka.EurekaClientConfigBean
3)Eureka Instance
Eureka Instance 的配置参数格式:eureka.instance.xxx。
instance-id 表示实例在注册中心注册的唯一ID。
prefer-ip-address
true:实例以 IP 的形式注册
false:实例以机器 HOSTNAME 形式注册
lease-expiration-duration-in-seconds 表示 Eureka Server 在接收到上一个心跳之后等待下一个心跳的秒数(默认 90 秒),若不能在指定时间内收到心跳,则移除此实例,并禁止此实例的流量。
此值设置太长,即使实例不存在,流量也能路由到该实例
此值设置太小,由于网络故障,实例会被取消流量
需要设置为至少高于 lease-renewal-interval-in-seconds 的值,不然会被误移除了。
lease-renewal-interval-in-seconds 表示 Eureka Client 向 Eureka Server 发送心跳的频率(默认 30 秒),如果在 lease-expiration-duration-in-seconds 指定的时间内未收到心跳,则移除该实例。
更多 Eureka Instance 参数配置可以看一下这个类:
org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean
参考:
https://cloud.spring.io/spring-cloud-static/Greenwich.SR1/single/spring-cloud.html#spring-cloud-eureka-server