zoukankan      html  css  js  c++  java
  • SpringCloudNetflix(Usage of Eureka)

    SpringCloud-Netflix(Usage of Eureka)

    前面聊了Ribbon的使用,因为使用Ribbon带出了两个痛点,所以我们来聊聊Eureka,当他和Ribbon结合后,会解决一定的问题。并且本篇会聊聊它的使用,关于SpringCloud-Netflix系列的源码我会在聊完对他们的使用后,然后再和大家进行剖析。

    Outline of Eureka

    前面说没有Eureka,Ribbon单独使用造成的痛点是【微服务目标地址的维护、监测微服务的健康状态】,那Eureka做的事情其实就是:

    • 服务地址的统一维护
    • 服务提供者的动态上下线感知

    要做到上面的两点,Eureka实际上做的事情是非常多的,因为

    • 我们服务调用者需要知道哪些微服务的地址是有用的,那就有两种方式解决
      • 【pull】:服务调用者主动去eureka上获取可用的微服务地址
      • 【push】:eureka主动推送微服务地址给服务调用方,那就需要和这些服务调用方建立心跳,及时的把最新的微服务地址传递给服务调用方
    • eureka需要知道哪些微服务是存活的,那就需要和这些微服务建立心跳

    如果Eureka做到了上面的这些,就可以解决Ribbon带来的痛点->Ribbon从Eureka上获取服务地址

    • 自己就不用手动维护地址,解决了目标地址的维护问题
    • Eureka对这些微服务的健康状态进行监听,解决了监测微服务的健康状态

    Usage of Eureka

    Eureka我们都知道它是一个注册中心,和其他的注册中心不同的是,他也是一个项目,所以我们需要创建一个项目,我们在创建项目的时候,把eureka相关的包勾选上即可。

     因为他默认的端口是8761,所在application中修改他的端口为8761,上面说了他是一个项目,所以我们要做还有把他自己注册到自己上面,否则会报错。

    spring.application.name=eureka-server
    server.port=8761
    #自己注册自己
    eureka.client.service-url.defaultZone=http://localhost:8761/eureka
    View Code

    并且在springBoot的启动类上加上@EnableEurekaServer,后面的源码,我会带大家聊这个。启动之后,我们发现,eureka已经把自己注册上去了。

    并且在想注册到eureka的微服务中加上eureka的client的pom

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

    同时每个微服务的application中指定一下默认eureka server

    eureka.client.service-url.defaultZone=http://localhost:8761/eureka
    View Code

    这样,我们的相关的微服务在启动的时候就注册到了eureka中

     另外我们需要加上actuator对微服务进行健康检查

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
    View Code

    这个时候,我们就可以删除在单独使用Ribbon的时候在application中维护的各个微服务地址,Ribbon会从Eureka上获取地址。

    Framework of Eureka

     Eureka满足了cap理论中的ap的特性,也就是可用性,和分区容错性,他的集群是一个去中心化的集群节点。因为如果有中心节点,那就会造成短时间内不可用的状态,就像之前的zk一样。引入集群后,他的流程如下:

    • 服务提供者启动的时候把自己注册到eureka上,然后建立心跳包。
    • 客户端通过定时的轮询去获取eureka上的服务地址。
    • 如果服务提供者的请求落到了某个eureka节点上的话,eureka就会把数据同步到其他的eureka节点上

    搭建集群】:实际上就是搭建多个相同的eureka项目,然后把彼此注册到对方中,比如我们现在有一个8761的节点,那就在application中维护8762的信息,反之亦然。eureka因为不像zk那样,所以只要保证高可用,无论部署几个节点。

    spring.application.name=eureka-server-replica
    server.port=8762
    eureka.client.service-url.defaultZone=http://localhost:8761/eureka
    View Code

    eureka的数据同步流程(基于http协议进行api接口之间的通信):

    服务提供者随机调用eureka的服务注册/下线api,在eureka底层提供了一个数据副本同步的机制,他会进行多个节点之间的同步
    • 当服务提供这随机调用一个eureka的api,比如说默认到eureka1上,eureka1会首先更新自己节点上的数据,
    • 然后它遍历所有的eureka实例,
    • 最后逐一发送数据同步的请求

    问题:那么既然eureka集群没有中心节点,它是如何避免死循环同步问题呢?(比如有一个服务提供者上线,并且发送消息到eureka1这个时候eureka1更新了它本地,并且发送一个他同步数据给了eureka2,这个时候eureka2收到了同步消息,更新了自己的本地,并且把这个数据也同步给了eureka1,这样就造成了死循环)

    解决:这个通过加时间戳解决就可以了,判断最新就行,这个和zk的zxid一样,后面源码我会和大家聊。

    relevant questions

    eureka心跳续约机制的流程

    • 服务提供者每隔30s会发送一次心跳请求给eureka-server,在eureka上维护了所有服务提供者的实例,当一次心跳请求过来的时候,他会更新发送心跳的服务的时间。在eureka上,它会每隔60s去检查所有的实例的过期时间,如果维护的某个服务提供者的上一次的心跳时间距离当前时间大于90s就认为服务提供者过期,并且会剔除它(但是eureka如果开启了自我保护机制是不会剔除

    eureka自我保护机制

    • 上面说到当某个服务提供者的心跳时间距离当前的时间大于90s那就被认为已经宕机,然而如果开启了自我保护机制那就不会剔除。这是因为有的时候因为网络的问题,eureka通过心跳判定某个服务提供者可能已经宕机,所以把一个健康的因为网络问题的服务提供者给剔除了。为了规避这种原因,eureka会默认开启这种机制【eureka.server.enable-self-preservation=true/false】.

    【什么时候会打开自我保护的开关】:

    • 如果超过85%的客户端节点都没有发起正常的心跳(renew),那么eureka就认为客户端和服务端出现了网络故障eureka就会进入自我保护状态。当然我们可以修改【eureka.server.renewal-percent-threshold = 0.85】。那具体表现为Renews (last min) < Renews threshold。这两个数值我们都可以在eureka的dashboard上看见。

    Renews threshold:Eureka Server 期望每分钟收到客户端实例续约的总数。这个数字15分钟更新一次。 (服务总数*每分钟的续约数量(60s/客户端续约间隔时间)* 0.85->现在我们的服务总数为为7个 那就等于【7*2*0.85=11.9(11)】

    Renews (last min)】:Eureka Server 最后 1 分钟收到客户端实例续约的总数。

    注:这两个参数我们可以在eureka的dashboard中看见。

    【模拟自我保护机制】

    通过配置,让它在5s之内,保证所有的服务都成功。这显然是不可能的,所以我们这样就可以模拟。

    eureka.server.wait-time-in-ms-when-sync-empty=5000
    eureka.server.renewal-percent-threshold=1
    View Code

    Eureka多级缓存机制

    他的缓存只是为了解决读写服务提供者信息的冲突问题,从而使用多个容器作为读写分离,他的服务提供者的信息是存储在ConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>>中的。下面为缓存流程:

    • 当服务注册或者服务下线,这些服务提供者的信息会更新到ConcurrentHashMap,然后同时更新到readWriteCacheHahMap中。
    • 当查询这些服务提供者信息的时候,
      • 他不会直接读取ConcurrentHashMap,而是从只读缓存中获取数据(readOnlyCacheHashMap)。
      • 这个只读缓存(readOnlyCacheHashMap)的信息是从一个readWriteCacheHahMap的容器中同步过来的。
      • readWriteCacheHahMap中的数据是,当ConcurrentHashMap中的信息变更后,就会马上同步到readWriteCacheHahMap
      • readOnlyCacheHashMap会每隔30s从readWriteCacheHahMap中获取数据,readWriteCacheHahMap中的数据每隔180s会过期,过期后会从ConcurrentHashMap中重新同步。

     

  • 相关阅读:
    【ZYNQ Ultrascale+ MPSOC FPGA教程】第八章FPGA片内FIFO读写测试实验
    【ZYNQ Ultrascale+ MPSOC FPGA教程】第七章 FPGA片内ROM测试实验
    【ZYNQ Ultrascale+ MPSOC FPGA教程】第六章 FPGA片内RAM读写测试实验
    【ZYNQ Ultrascale+ MPSOC FPGA教程】第五章 Vivado下PLL实验
    【ZYNQ Ultrascale+ MPSOC FPGA教程】第四章 PL的LED实验
    在Mac OS X中使用VIM开发STM32(3)
    在Mac OS X中使用VIM开发STM32(2)
    STM32F40xxx 与 STM32F41xxx Flash结构详解
    在Mac OS X中搭建STM32开发环境(3)
    在Mac OS X中搭建STM32开发环境(2)
  • 原文地址:https://www.cnblogs.com/UpGx/p/15741221.html
Copyright © 2011-2022 走看看