SpringCloud-Eureka服务注册与发现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/belovehejian/article/details/83039294

什么是Eureka

简单来说Eureka是一个Netflix公司开源的一款服务发现组件.这个组件提供的服务发现可以为负载均衡等提供支持.Eureka包括了Eureka Server 和 Eureka Client. Eureka Server 提供 REST 服务, Eureka Client 则是 JAVA 编写的客户端用于简化与 Eureka Server 的交互.Eureka Server 端采用的是 P2P 的复制模式. 不过它不能保证复制操作一定会成功.因此它提供的是一个最终一致性的服务实例视图.Client 端在 Server 端的注册信息有一个带期限的租约,并且Client 与 Server 通过心跳维持更新租约,一旦 Server 端在指定时间之内没有收到 Client 发送的心跳,那么 Server 端会认为 Client 已经已经出现故障, 这个时候 Server 端会将这个 Client 从注册表中删除.

示例

Eureka Server:

添加依赖

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

配置文件 application.yml

#设置服务端口
server:
  port: 8761

#设置服务实例hostname
eureka:
  instance:
    hostname: localhost
  client:
    #指示此客户端是否应从eureka服务器获取eureka注册表信息
    fetch-registry: false
    #指示此实例是否应将其信息注册到eureka服务器以供他人发现
    register-with-eureka: false
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
  server:
    #是否启用注册中心的自我保护模式
    #Eureka 会统计15分钟之内心跳失败的比例低于85%将会触发保护机制,不剔除服务提供者,如果关闭服务注册中心将不可用的实例正确剔除
    enable-self-preservation: false
    #在Eureka服务器获取不到集群里对等服务器上的实例时,需要等待的时间,单位为毫秒,默认为1000 * 60 * 5
    wait-time-in-ms-when-sync-empty: 0

主启动类

@SpringBootApplication
@EnableEurekaServer //添加注解,作为Eureka Server使用
public class Ch2EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(Ch2EurekaServerApplication.class, args);
    }
}

Eureka client 端

引入依赖

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

配置文件 application.yml

server:
  port: 8081
spring:
  application:
    name: eureka-client

#与Eureka server 通讯的地址,可以理解为注册中心地址
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

主启动类

@SpringBootApplication
@EnableDiscoveryClient  //注册为 Eureka Client 客户端
public class Ch2EurekaClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(Ch2EurekaClientApplication.class, args);
    }
}

然后依次启动 Eureka Server 服务端, Eureka Client 客户端, 然后访问 http://localhost:8761/eureka 可以看到如下页面表示服务端与客户端搭建成功.

Eureka Server提供了许多的 REST API, 允许非 JAVA 语言的其他应用服务通过 HTTP REST 的方式接入 Eureka 的服务发现当中.具体的 REST API 列表可以自行百度查看, 例如 ,启动 Eureka Server 服务端之后,可以通过访问  http://localhost:8761/eureka/apps 来获取所有实例信息

服务发现原理

Application Service: 这是一个 Eureka Client 可以看成是一个服务的提供者,提供一些服务, 它可以向 Eureka Server 注册,更新自己的信息,也可以从 Eureka Server 获取其他服务的信息.

Application Client : 是一个 Eureka Client . 是一个服务消费者的角色.可以注册到 Eureka Server上,并且获取其他的服务实例信息,这样就可以调用其他服务实例提供的服务.

Eureka Server: 注册中心.提供注册和发现服务实例的功能

Replicate: Eureka Server 之间进行同步复制.,以保证集群中所有 注册表中的服务实例信息一致.

服务的核心操作:

既然叫服务发现,那么肯定能有发现其他服务的功能.服务发现主要围绕以下的几个重要的功能(源码看的迷迷糊糊的)

  • 服务注册
    • 服务在启动的时候会调用 Eureka 的 REST API 的 register 方法,将服务注册到服务中心.在注册之前,会先去获取注册表中的其他服务实例,第一次获取的时候是全量获取,之后是增量获取.并且如果无法从任何的 Eureka Server 获取实例的时候,会从备用中心获取服务实例.获取完服务实例之后,会有一个预注册,然后才进行注册.注册信息是封装在 InstanceInfo 中的.之后会启用3个定时任务,一个用于定时发送心跳,一个用于定时拉去注册表信息,一个用于按需注册(按需注册就是:当服务实例注册到注册中心时,会同时注册一个监听器,监听自身服务实例的变化,当自身服务实例发生 变化的时候,会重新注册实例到 Eureka Server 注册中心)
  • 服务下线
    • 正常情况下,服务在关闭的时候会调用 Eureka Server 的 REST API,来删除自身服务实例的相关信息.如果维护的心跳不及时的话, Eureka Server 也会主动的剔除该服务实例
  • 服务租约
    • 服务租约主要是通过定时任务,维护客户端与服务端的心跳,然后更新租约进行的.
  • 服务剔除
    • 当服务端在指定的时间之内收不到客户端发送过来的心跳的时候,服务端就会在注册中心剔除这个服务实例.不过好像有保护机制,具体不是很清楚, 还在学习当中.

常见问题

  • 服务下线了,但是 Eureka Server接口返回的信息还在.

因为Eureka Server 并不是强一致的,因此 Registry 中会存留过期的实例信息.要么就是应用实例异常挂掉,没有通知服务端要下线该服务实例信息.可以适当的考虑调整 EvictionTask的调度频率.将默认时间 60秒调整为更低的值.

要么就是已经通知到服务端,但是 Eureka Server 的 REST API 有 Response cache,因此需要等到缓存过期才刷新.可以考虑关闭 ReadOnlyCacheMap,或者调整 ReadWriteCacheMap 的过期时间

或者是 Eureka Server 开启了 SELF PRESERVATION (自我保护)模式.导致 Registry 的信息不会因为过期而被剔除掉.直到退出 SELF PRESERVATION 模式.可以开了关闭该模式.不过关闭的话会在 Eureka 的 WEB显示页面出现错误信息.

  • 服务上线了,但是服务端获取不及时

可以提高 client 端拉取 Server 注册表信息的频率.将默认的 30 秒,降低到 5 秒,加大拉取频率.

SELF PRESERVATION(自我保护模式 )

由于网络等原因,经常会有服务实例(Eureka Client端)与 服务端(Eureka Server 端)的心跳未能如期保持,但是服务实例本身是健康的,这个时候如果按照租约机制,剔除该服务实例的话,会造成误判,如果这个误判的范围很大的话,有可能会导致注册表中的大部分注册信息被删除, 导致没有任何服务实例可用. 所以 Eureka 为了解决这个问题,引入了 SELF PRESERVATION (自我保护)模式.如果最近一分钟收到的心跳次数小于阀值的话,就会关闭租约失效机制, 禁止任何定时任务剔除失效的实例.从而保护注册表信息.在测试环境中可以考虑关闭这个模式.在生成环境当中可以适当地调整心跳发送频率,以及降低阀值.从而提高触发 SELF PRESERVATION 的门槛.

服务注册相关

  1. 服务提供者在启动的时候会通过发送 REST 请求的方式将自己注册到Eureka Server上,同时带上了自身服务的一些元数据信息.Eureka Server接收到这个REST请求之后,将元数据信息存储在一个双层结构Map中, 其中第 一层的key是服务名, 第二层的key是具体服务的实例名。
  2. 如果服务注册中心之间互相注册为服务, 当服务提供者发送注册请求到其中一个服务注册中心时, 它会将该请求转发给集群中相连的其他注册中心, 从而实现注册中心之间的服务同步 。 通过服务同步,服务提供者的服务信息就可以通过服务注册中心中的任意 一 台获取到。
  3. 在注册完服务之后,服务提供者会维护 一个心跳用来持续告诉EurekaSe1-er: "我还活着 ”, 以防止Eureka Server 的 “ 剔除任务 ” 将该服务实例从服务列表中排除出去, 我们称该操作为服务续约(Renew)。关千服务续约有两个重要属性,我们可以关注并根据需要来进行调整:
    eureka.instance.lease-renewal-interval-in-seconds=30
    eureka.instance.lease-expiration-duration-in-seconds=90
    eureka.instance.lease-renewal-interval-in-seconds 参数用于定义服务续约任务的调用间隔时间,默认为30秒.eureka.instance.lease-expiratonduration-in-seconds参数用于定义服务失效的时间,默认为90秒
  4. 在系统运行过程中必然会面临关闭或重启服务的某个实例的情况, 在服务关闭期间,我们自然不希望客户端会继续调用关闭了的实例。 所以在客户端程序中, 当服务实例进行正常的关闭操作时, 它会触发一个服务下线的REST请求给Eurke a Server, 告诉服务注册中心:“我要下线了 ”。 服务端在接收到请求 之后, 将该服务状态置为下线(DOW), 并把
    该下线事件传播出去。
  5. 有些时候, 我们的服务实例并不一定会正常下线, 可能由于内存溢出、 网络故障等原因使得服务不能正常工作, 而服务注册中心并未收到 “服务下线 ” 的请求。 为了从服务列表中将这些无法提供服务的实例剔除, Eureka Server在启动的时候会创建一个定时任务,默认每隔 一段时间(默认为60秒) 将当前清单中超时(默认为90秒)没有续约的服务剔除出去。
  6. 当我们在本地调试基于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.
    实际上, 该警告就是触发了EurekaServer的自我保护机制。 之前我们介绍过, 服务注册到EurekaServer之后,会维护一个心跳连接,告诉EurekaServer自己还活着。EurekaServer在运行期间,会统计心跳失败的比例在15分钟之内是否低于85%, 如果出现低于的情况(在单机调试的时候很容易满足, 实际在生产环境上通常是由于网络不稳定导致), Eureka
    Server会将当前的实例注册信息保护起来, 让这些实例不会过期, 尽可能保护这些注册信息。 但是, 在这段保护期间内实例若出现问题, 那么客户端很容易拿到实际已经不存在的服务实例, 会出现调用失败的清况, 所以客户端必须要有容错机制, 比如可以使用请求重试、 断路器等机制。

参考资料:<spring cloud微服务实战><spring cloud 微服务架构进阶> 两本书

猜你喜欢

转载自blog.csdn.net/belovehejian/article/details/83039294