由来
eureka是一个注册中心,注册中心出现的一个主要原因就是每当有一个服务有一个台新的机器上线的时候,都需要去改动调用方的代码;而使用了注册中心之后,只需要每次去访问注册中心就可以知道一个服务有多少台机器运行,这样也就避免了不停的修改调用方的代码
服务启动
- 需要在pom文件下导入eureka的依赖
- 在启动类上加入@EnableEurekaServer注解
- 在resources中加入一个application.yml的文件
- 启动对应的的类即可
依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
<version>3.0.4</version>
</dependency>
application.yml文件
server:
port: 8761 #指定该Eureka实例的端口
spring:
application:
name: eurekaServer
eureka:
instance:
hostname: localhost #设置当前实例的主机名称
client:
# 禁止注册自身
registerWithEureka: true
fetchRegistry: false #因为该服务没有注册到其他注册中心,所以关闭从注册中心拉取服务列表。
serviceUrl: #服务注册中心地址
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
服务注册
- 需要在pom文件下导入eureka的依赖
- 在启动类上加入@EnableEurekaClient注解
- 在resources中加入一个application.yml的文件
- 启动对应的的类即可
服务注册和服务启动的主要差别其实就是在于 启动类上的注解的差别
当然还有一个差别就是application.yml文件的差别
参数:
- registerWithEureka 注册到eureka
- fetchRegistry 是否要拉取注册中心注册表
注意:
- 注册中心的接口是不能够被feign调用的
依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
<version>3.0.4</version>
</dependency>
application.yml文件
server:
port: 8762 #指定该Eureka实例的端口
spring:
application:
name: eurekaA
eureka:
instance:
hostname: eurekaA #设置当前实例的主机名称
client:
serviceUrl:
defaultZone: http://127.0.0.1:8761/eureka/
成功截图
eurekaA就是向注册中心注册进入的机器,eurekaServer就是注册中心
集群
服务端
- 启动多台eureka服务
- 每个服务都要注册到自身,并且注册到其他服务上
客户端
每个机器都要注册到所有的eureka服务端的注册中心上
健康检查
默认情况下,你的所有的服务,比如服务A和服务B,都会自动给eureka注册中心同步心跳,续约,每隔一段时间发送心跳,如果说某个服务实例挂了,那么注册中心一段时间内没有感知到那个服务的心跳,就会把那个服务给他下线
如果你要自己来实现一个服务的健康检查的机制,自己来检查服务是否宕机,比如说,如果底层依赖的MQ、数据库挂了,你就宣布自己挂了,通知注册中心
在服务中加入以下依赖:
http://localhost:8080/health,可以看到服务的健康状态
正常情况下就这样就可以了,但是有一个问题,就是可能这个服务依赖的其他基础设施,比如redis、mysql、mq,都挂掉了,或者底层的基础服务挂掉了,此时这个服务已经不可用了,那么这个服务就可以认定自己是不可用了
所以可以自己实现一个健康检查器,就是自己检查自己依赖的基础设施,或者是基础服务,是否挂掉了,来决定自己是否还是健康的
@Component
public class ServiceAHealthIndicator implements HealthIndicator {
@Override
public Health health() {
// 这里可以通过返回UP或者DOWN来指示服务的状态
return new Health.Builder(Status.UP).build();
}
}
@Component
public class ServiceAHealthCheckHandler implements HealthCheckHandler {
@Autowired
private ServiceAHealthIndicator indicator;
public InstanceStatus getStatus(InstanceStatus currentStatus) {
Status status = indicator.health().getStatus();
// 根据这个status,可以决定这里返回什么
return InstanceStatus.UP;
}
}
eureka client里面会有一个定时器,不断调用那个HealthCheckHandler的getStatus()方法,然后检查当前这个服务实例的状态,如果状态变化了,就会通知eureka注册中心。如果服务实例挂掉了,那么eureka注册中心就会感知到,然后下线这个服务实例。
不过其实一般很少自己去实现这个健康检查,在大规模的部署中,每个服务都很复杂,不可能都这样去搞一堆健康检查的。大部分情况下,我们就是会对外暴露一个/health接口,然后专门外部来定时调用各个服务的/health接口来判断当前这个服务能够调通。
但是eureka默认是client通过心跳机制跟eureka注册中心保持心跳通信,如果心跳不及时或者没有心跳了,那么就说明那个服务挂了,然后eureka注册中心就会摘除这个服务实例。这个机制就足够了。
15239736183
心跳机制
eureka客户端,默认会每隔30秒发送一次心跳的eureka注册中心,下面的那个参数可以修改这个心跳间隔时间,如果在90秒内没收到一个eureka客户端的心跳,那么就摘除这个服务实例,别人就访问不到这个服务实例了,通过下面的参数可以修改这个90秒的值。但是一般这俩参数建议不要修改。
另外这个心跳检测的机制其实叫做renew机制,看下面的参数配置就知道了,也可以叫做服务续约
eureka.instance.leaseRenewallIntervalInSeconds
eureka.instance.leaseExpirationDurationInSeconds
如果一个服务被关闭了,那么会走cancel机制,就是类似是服务下线吧
如果90秒内没收到一个client的服务续约,也就是心跳吧,但是他这里叫做服务续约,那么就会走eviction,将服务实例从注册表里给摘除掉
注册表抓取
默认情况下,客户端每隔30秒去服务器抓取最新的注册表,然后缓存在本地,通过下面的参数可以修改。
eureka.client.registryFetchIntervalSeconds
自定义元数据
- eureka:
- instance:
- hostname: localhosto
- metadata-map:
- company-name: zhss
可以通过上面的metadata-map定义服务的元数据,反正就是你自己需要的一些东西,不过一般挺少使用的
自我保护模式
如果在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进入了自我保护模式,如果客户端的心跳失败了超过一定的比例,或者说在一定时间内(15分钟)接收到的服务续约低于85%,那么就会认为是自己网络故障了,导致人家client无法发送心跳。这个时候eureka注册中心会先给保护起来,不会立即把失效的服务实例摘除,在测试的时候一般都会关闭这个自我保护模式:
- eureka.server.enable-self-preservation: false
在生产环境里面,他怕自己因为自己有网络问题,导致别人没法给自己发心跳,就不想胡乱把别人给摘除,他就进入保护模式,不再摘除任何实例,等到自己网络环境恢复。