Eureka 客户端的服务注册
Eureka 客户端在运行时会向 Eureka 服务端发送周期性的心跳,Eureka 服务端利用客户端周期性的心跳续约请求来保证注册表的实时性。其中客户端会向服务端提供一个如果多久没有向服务端发送心跳请求,就不再维护这个客户端的时间阈值。
Eureka 客户端的服务拉取
在通常情况下服务提供者可能为多个实例,服务调用者在调用服务时通过一些特定的负载均衡算法来把请求转发到该服务调用者的实例上。Eureka 客户端也会定时向服务端获取最新的服务列表,如果想保证实时性更高的话需要修改其配置来实现。
Eureka 服务端的注册列表维护
当客户端心跳续约请求超过与服务端约定好的时间阈值之后,Eureka 服务端会将该客户端实例加入到待清理的一个列表中之后由定时器来清理。如果我们想让服务端的注册列表实时性更高一些除了需要修改客户端的配置也需要修改服务端清理定时器的配置。
Eureka 的自我保护机制
以下来自Netflix官方解释 原文链接
Eureka 客户尝试与同一区域的Eureka服务器通话。如果在与服务器交谈时出现问题,或者服务器不在同一区域中,则客户端将故障转移到其他区域中的服务器。 一旦服务器开始接收流量,服务器上执行的所有操作都会复制到服务器知道的所有对等节点。如果某个操作由于某种原因而失败,则该信息将与下一个在服务器之间复制的心跳同步。 当Eureka服务器启动时,它会尝试从邻居节点获取所有实例注册表信息。如果从节点获取信息时出现问题,则服务器在放弃之前先尝试所有对等节点。如果服务器能够成功获取所有实例,则会根据该信息设置它应该接收的更新阈值。如果任何时候,续订低于为该值配置的百分比(在15分钟内低于85%),则服务器将停止到期实例以保护当前实例注册表信息。 在Netflix中,上述安全措施称为自我保护模式 ,主要用于在一组客户端与Eureka服务器之间存在网络分区的情况下的保护。在这些情况下,服务器会尝试保护已有的信息。在发生大量停机的情况下,可能会出现这种情况,这可能会导致客户获取不再存在的实例。客户端必须确保它们对于返回不存在或不响应的实例的尤里卡服务器具有弹性。在这些情况下最好的保护是快速超时并尝试其他服务器。 Eureka的自我保护机制,通过配置 eureka.server.enable-self-preservation(true/false)来打开或者禁用自我保护机制,默认打开状态。在自我保护开启的时候,如果心跳的失败率超过一定比例,服务端会将这些实例保护起来,并不会马上将其从注册表中剔除。此时对于调用的客户端来说有可能会拿到一些无法使用的实例,这种情况可能会导致灾难的恶化。对于这种情况我们可以用 netflix 提供的容错框架hystrix 来触发fallback或者熔断来解决,使微服务集群更加健壮。对于开发环境我们可以关闭自我保护,这样在出现网络问题或者其他问题时,服务端将不会保护过期实例。
模拟
Eureka 服务提供者
更改上一篇文章中的服务提供者的启动方法为控制台输入端口启动
@EnableEurekaClient
@SpringBootApplication
public class EkProviderApplication {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
new SpringApplicationBuilder(EkProviderApplication.class).properties("server.port=" + scanner.nextLine()).run(args);
}
}
在这里我们启动8080和8081两个端口实例。
Eureka 服务调用者
增加上一篇文章中的服务调用者的REST服务
@Autowired
EurekaClient eurekaClient;
@RequestMapping("/getServices")
public void getServices() {
Applications applications = eurekaClient.getApplications();
List<Application> registereds = applications.getRegisteredApplications();
for (Application registered : registereds) {
System.out.println("服务: " + registered.getName());
System.out.print(" 实例:");
for (InstanceInfo info : registered.getInstances()) {
System.out.print(" ");
System.out.print(info.getHomePageUrl());
}
System.out.println("");
}
启动之后可以在 Eureka 控制台看到如下实例列表
通过访问http://localhost:9000/getServices 看到客户端获取的注册列表为
之后我们停掉8081的服务提供者可以在Eureka控制台看到Eureka 告警提示,通过再次访问getService接口知道不会立马剔除这个服务实例。(如果未出现如下情况可以尝试几次访问invoke使其达到开启自我保护的条件)
Eureka 服务
增加上一篇文章中的Eureka 服务的application.yml的配置,使其关闭自我保护模式
server:
port: 8761
eureka:
server:
enable-self-preservation: false
client:
registerWithEureka: false
fetchRegistry: false
启动之后可以在 Eureka控制台看到已关闭自我保护的文字,之后当客户端达到剔除规则之后就会被清理掉。