精华内容
下载资源
问答
  • Eureka集群原理 服务启动后向Eureka注册,Eureka Server会将注册信息向其他Eureka Server进行同步,当服务消费者要调用服务提供者,则向服务注册中心获取服务提供者地址,然后会将服务提供者地址缓存在本地,下次...

    Eureka集群的原理

    服务启动后向Eureka注册,Eureka Server会将注册信息向其他Eureka Server进行同步,当服务消费者要调用服务提供者,则向服务注册中心获取服务提供者地址,然后会将服务提供者地址缓存在本地,下次再调用时,则直接从本地缓存中取,完成一次调用。

    Eureka集群配置

    我在本地开了三个Eureka Server模拟集群环境:
    在这里插入图片描述
    现在怎么说明集群的环境呢?看下图:
    在这里插入图片描述
    看具体的配置:

    server:
      port: 3000
    eureka:
      server:
        enable-self-preservation: true  #自我保护机制
        eviction-interval-timer-in-ms: 4000   #设置清理间隔(单位毫秒  默认是60*1000)
      instance:
        hostname: localhost
    
      client:
        registerWithEureka: false  #不把自己作为一个客户端注册到自己身上
        fetchRegistry: false   #不需要从服务端获取注册的信息(因为在这里自己就是服务端)
        serviceUrl:
          defaultZone: http://localhost:3001/eureka,http://localhost:3002/eureka
    

    这里我就在本机进行了测试,如果看着不方便可以去修改一下hosts文件,自定义一下服务名称,这样看起来效果更好。集群的配置与单体配置不同的点在于,原来是把服务注册到自己身上,而现在是注册到其他服务的身上。

    为什么不注册自己了呢?

    因为eureka的server会把自己的注册信息与其他的server同步,所以这里我们不需要注册到自己的身上,因为另外两台服务器会配置本台服务器。所以其他两台的配置和这个一样,只要把自己注册到其他的服务上面就好了。

    三台都配置好以后看效果:

    在这里插入图片描述
    这个就是每一台机器的效果,每个服务都会注册上去。

    下面配置客户端,话不多说,直接上代码:

    eureka:
      client:
        serviceUrl:
          defaultZone: http://localhost:3000/eureka/,http://localhost:3001/eureka/,http://localhost:3002/eureka/
    

    Zookeeper也可以做服务的注册与发现,他们的区别在哪里呢?

    大多数分布式系统都分布在多个子哦网络。每一个网络就叫做一个区。分区容错的意思就是,区间通信可能失败。比如,一台服务器放在本地,另一台放在外地或者外国,这就是两个区,他们之间可能无法通信。
    一般来说,分区容错是无法避免的,所以认为CAP中的P总是成立的,剩下的CA无法同时做到。

    Eureka对比zookeeper

    zookeeper在设计的时候遵循CP原则,也就是要保证一致性,牺牲可用性;而Eureka在设计的时候遵循的是AP原则,也就是要保证可用性,牺牲一致性。Eureka还有自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么eureka就会认为注册中心出现了故障,这时候会出现以下情况:
    1、Eureka不再从注册表里移除因为长时间没有收到心跳而过期的服务;
    2、Eureka仍然能够接收新服务器的注册和查询请求,但是不会被同步到其他节点上,保证当前节点的可用;
    3、当网络稳定之后,当前实例新的注册信息会被同步到其他的节点中。

    展开全文
  • Eureka Server 集群相互之间通过 Replicate 来同步数据,相互之间不区分主节点和从节点,所有的节点都是平等的。在这种架构中,节点通过彼此互相注册来提高可用性,每个节点需要添加一个或多个有效的 serviceUrl ...

          我们假设有三台 Eureka Server 组成的集群,这样三台 Eureka Server 就组建成了一个跨区域的高可用集群,只要三个地方的任意一个机房不出现问题,都不会影响整个架构的稳定性。
        

        Eureka Server 集群相互之间通过 Replicate 来同步数据,相互之间不区分主节点和从节点,所有的节点都是平等的。在这种架构中,节点通过彼此互相注册来提高可用性,每个节点需要添加一个或多个有效的 serviceUrl 指向其他节点。

        如果某台 Eureka Server 宕机,Eureka Client 的请求会自动切换到新的 Eureka Server 节点。当宕机的服务器重新恢复后,Eureka 会再次将其纳入到服务器集群管理之中。当节点开始接受客户端请求时,所有的操作都会进行节点间复制,将请求复制到其它 Eureka Server 当前所知的所有节点中。

        另外 Eureka Server 的同步遵循着一个非常简单的原则:只要有一条边将节点连接,就可以进行信息传播与同步。所以,如果存在多个节点,只需要将节点之间两两连接起来形成通路,那么其它注册中心都可以共享信息。每个 Eureka Server 同时也是 Eureka Client,多个 Eureka Server 之间通过 P2P 的方式完成服务注册表的同步。

        Eureka Server 集群之间的状态是采用异步方式同步的,所以不保证节点间的状态一定是一致的,不过基本能保证最终状态是一致的

    Eureka 分区,  Eureka 提供了 Region 和 Zone 两个概念来进行分区,这两个概念均来自于亚马逊的 AWS:

    1. region:可以理解为地理上的不同区域,比如亚洲地区,中国区或者深圳等等。没有具体大小的限制。根据项目具体的情况,可以自行合理划分 region。
    2. zone:可以简单理解为 region 内的具体机房,比如说 region 划分为深圳,然后深圳有两个机房,就可以在此 region 之下划分出 zone1、zone2 两个 zone。

           上图中的 us-east-1c、us-east-1d、us-east-1e 就代表了不同的 Zone。Zone 内的 Eureka Client 优先和 Zone 内的 Eureka Server 进行心跳同步,同样调用端优先在 Zone 内的 Eureka Server 获取服务列表,当 Zone 内的 Eureka Server 挂掉之后,才会从别的 Zone 中获取信息。

    Eurka 保证 AP( 可用性(Availability)、分区容错性(Partition tolerance) ) , 而不保证 C ( 一致性(Consistency)) 

              Eureka Server 各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而 Eureka Client 在向某个 Eureka 注册时,如果发现连接失败,则会自动切换至其它节点。只要有一台 Eureka Server 还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。

    展开全文
  • 实际上就是启动多个 eureka 实例,实例之间相互注册、同步数据、共同组成一个 Eureka 集群 配置 hosts 文件 地址: C:\Windows\System32\drivers\etc\hosts 最后一行添加 127.0.0.1 eurekaA eurekaB 新增配置...

    5.2 Eureka 服务端集群

    • 使用了注册中心,所有服务都有通过注册中心获取服务信息地址,这时稳定性就变得重要了,一旦坏了,一项整个系统的稳定性,所有实际开发中,一般都是集群

    5.2.1 集群的搭建

    • 原理
      实际上就是启动多个 eureka 实例,实例之间相互注册、同步数据、共同组成一个 Eureka 集群
    • 配置 hosts 文件
      地址:
      C:\Windows\System32\drivers\etc\hosts
      最后一行添加
    127.0.0.1 eurekaA eurekaB
    

    在这里插入图片描述

    • 新增配置文件
      在笔记【Spring Cloud 学习笔记——Eureka 服务端介绍和基本搭建】的基础上,新增两个配置文件:application-a.properties 和 application-b.properties
      application-a.properties
    # 此微服务名称
    spring.application.name=eureka
    # 此微服务端口
    server.port=1111
    # 相当于给服务起个别名,注册到注册中心,与 hosts 文件中配置相对应
    eureka.instance.hostname=eurekaA
    # 默认本身也是一个微服务,当它是注册中心时,有两个身份,一个是服务注册中心,一个是普通项目,它会自己把注册到自己上面,默认是true
    # 集群,当前项目要注册到服务注册中心,设为true
    eureka.client.register-with-eureka=true
    # 集群,获取注册信息表
    eureka.client.fetch-registry=true
    # B 服务要注册到 A 服务上去
    eureka.client.service-url.defaultZone=http://eurekaB:1112/eureka
    

    application-b.properties

    # 此微服务名称
    spring.application.name=eureka
    # 此微服务端口
    server.port=1112
    # 相当于给服务起个别名,注册到注册中心,与 hosts 文件中配置相对应
    eureka.instance.hostname=eurekaB
    # 默认本身也是一个微服务,当它是注册中心时,有两个身份,一个是服务注册中心,一个是普通项目,它会自己把注册到自己上面,默认是true
    # 集群,当前项目要注册到服务注册中心,设为true
    eureka.client.register-with-eureka=true
    # 集群,获取注册信息表
    eureka.client.fetch-registry=true
    # A 服务要注册到 B 服务上去
    eureka.client.service-url.defaultZone=http://eurekaA:1111/eureka
    
    • 配置完成后,对象名打包,双击 package
      在这里插入图片描述
      在这里插入图片描述
    • 打开到两个 target 目录,分别输入
    java -jar eureka-0.0.1-SNAPSHOT.jar --spring.profiles.active=a
    java -jar eureka-0.0.1-SNAPSHOT.jar --spring.profiles.active=b
    

    启动两个 Eureka 服务端,启动后报错可能是代码问题,也可能是另一个 Eureka 没启动完成,过一段时间都不报错了,Eureka 集群就搭建好了

    • 访问 http://localhost:1111/
      在这里插入图片描述
    • 访问http://localhost:1112/
      在这里插入图片描述
    • 至此说明 Eureka 集群搭建成功

    5.3 Eureka 工作细节

    • Eureka 本身分为两个部分, Eureka Server 和 Eureka Client

    5.3.1 Eureka Server

    • Eureka Server 主要提供3个功能
      ① 服务注册,所有服务都注册到 Eureka Server 上来
      ② 提供注册表,注册表就是所有注册上来服务的一个列表,Eureka Client 在调用服务时,需要获取这个注册表,一般来说,这个注册表会缓存下来,如果缓存失效,则直接获取最新的注册表
      ③ 同步状态, Eureka Client 通过注册、心跳机制,和 Eureka Server 同步当前客户端的状态

    5.3.1.1 自我保护机制

    • 网络波动,如果三次没有收到 Eureka Client 的请求后,就删除该 Eureka Client 信息,可能造成误杀,为此出现了自我保护机制,开发环境不用开启,生产建议开启
      eureka.server.enable-self-preservation=true
    • 统计 15 分钟内是否低于 85% ,如果低于 85%,进入保护机制
      ① 不在移除因长时间没有收到心跳而过期的微服务
      ② 依然会接收新的注册、查询请求,但是不会同步
      ③ 不会同步到其他节点(自己不知道注册信息有没有失效),当恢复后同步到其他节点,退出保护机制

    5.3.2 Eureka Client

    • Eureka Client 主要是用来简化每个服务和 Eureka Server 之间的交互,Eureka Client 会自动拉取、更新、以及缓存 Eureka Server 中的信息,这样 Eureka Server 所有节点宕机,Eureka Client 依然能够获取到想要调用服务的地址(这是理想状态,有时候地址可能不准确,比如有个服务重启 IP 变了,还拿老地址调用服务,就不行了)

    5.3.2.1 服务注册

    • 服务提供者(本质也是一个 Eureka Client)将自己注册到服务中心(Eureka Server)。当 Eureka Client 向 Eureka Server 注册时,它需要提供自身的一些元数据,例如: IP 地址、端口、名称、运行状态等等

    5.3.2.2 服务续约

    • Eureka Client 注册到 Eureka Server 上之后,事情没有结束,只是刚刚开始,注册成功后,默认情况下,Eureka Client 每隔 30 秒就要向 Eureka Server 发送一条消息,来告诉 Eureka Server 我还在运行。如果 Eureka Server 连续 90 秒没有收到 Eureka Client 的续约消息(连续三次没发送),它会认为 Eureka Client 已经掉线,会将掉线的 Eureka Client 从当前的列表中删除。

    • 服务续约,有两个相关属性(一般不建议修改)

    eureka.instance.lease-renewal-interval-in-seconds=30
    eureka.instance.lease-expiration-duration-in seconds=90
    

    eureka.instance.lease-renewal-interval-in-seconds=30表示服务续约时间,默认是30秒
    eureka.instance.lease-expiration-duration-in seconds=90服务失效时间,默认是90秒

    5.3.2.3 服务下线

    • 当 Eureka Client 下线时,它会主动发送一条消息,告诉 Eureka Server,我下线啦。

    5.3.2.4 获取注册表信息

    • Eureka Client 从 Eureka Server 上获取服务的注册信息,并将其缓存在本地。本地客户端,在需要调用远程服务时,会从该信息中查找远程服务所对应的 IP 地址、端口等信息。 Eureka Client 上缓存的服务注册信息会定期更新,如果 Eureka Server 返回的注册表信息与本地缓存的注册表信息不同的话,Eureka Client 会自动处理
    • 这里也涉及两个属性,一个是是否允许获取注册表信息
      eureka.client.fetch-registry=true
      Eureka Client 上缓存的服务注册信息,定期更新的时间间隔,默认 30 秒
      eureka.client.register-fetch-interval-seconds=30

    5.4 Eureka 集群原理

    在这里插入图片描述

    • 在集群中,Eureka Server 通过 Replicate 同步数据,不同 Eureka Server 之间不分主从,是平等的;节点之间,通过指定 serviceUrl 来互相注册,形成一个集群,进而提高节点的可用性,如果有一个 Eureka Server 宕机,Eureka Client 会自动切换到新的 Eureka Server 上,每个 Eureka Server 节点上,都会相互同步数据
    • Eureka Server 的注册方式可以是单线的,也可以是多线的
      单线:A --> B --> C ,此方法 A 、C 也会同步,但如果 B 宕机了,A 、C 之间就不同步了
      多线:A --> B , C; B --> A , C;C --> A,B;如果一个节点宕机,另外两个节点依然可以同步数据

    5.4.1 Eureka 分区

    • Region:地理位置上的不同区域,比如华北、东北
    • Zone:具体机房
      同一个 Zone 的分区里的 Eureka Server 、Eureka Client 优先进行心跳、同步,没有找到再去其他分区找
    展开全文
  • Eureka Server集群同步

    2021-08-25 14:58:50
    本文来说下Eureka Server集群同步 文章目录概述 概述

    本文来说下Eureka Server集群同步


    集群启动同步

    集群启动同步

    protected void initEurekaServerContext() throws Exception {
     
         // ....省略N多代码
         // 同步信息
        int registryCount = this.registry.syncUp();
        // ....省略N多代码
     }
    

    网上很多文章说是调用syncUp这个方法去其他Eureka Server节点复制注册信息,这个说法不是很准确, 在这个地方,SyncUp()这个方法并不会去其他Eureka Server节点复制信息,而是从本地内存里面获取注册信息, 看源码就知道了。

    public int syncUp() {
    
          // Copy entire entry from neighboring DS node
          // 获取到的注册节点数量
          int count = 0;
          // 如果count==0 , 那么默认重试5次(前提是开启了register-with-eureka = true,否则为0)
          for (int i = 0; ((i < serverConfig.getRegistrySyncRetries()) && (count == 0)); i++) {
              if (i > 0) {
                  try {
                      // 从第二次开始,每次默认沉睡30秒
                     Thread.sleep(serverConfig.getRegistrySyncRetryWaitMs());
                 } catch (InterruptedException e) {
                      logger.warn("Interrupted during registry transfer..");
                      break;
                 }
             }
              // 从本地内存里面获取注册实例信息
              Applications apps = eurekaClient.getApplications();
              for (Application app : apps.getRegisteredApplications()) {
                 for (InstanceInfo instance : app.getInstances()) {
                     try {
                          // 判断是否可以注册
                          if (isRegisterable(instance)) {
                             // 注册到当前Eureka Server里面
                              register(instance, instance.getLeaseInfo().getDurationInSecs(), true);
                              count++;
                          }
                     } catch (Throwable t) {
                          logger.error("During DS init copy", t);
                     }
                 }
             }
         }
         return count;
    }
    

    参数说明:

    regirstrySyncRetries : 当eureka服务器启动时尝试去获取集群里其他服务器上的注册信息的次数,默认为5,

    只有当 eureka.client.register-with-eureka = true 的时候才会是5,如果是false ,则为0

    registrySyncRetryWaitMs : 当eureka服务器启动时获取其他服务器的注册信息失败时,会再次尝试获取,期间需要等待的时间,默认为30 * 1000毫秒

    count : 获取到的注册实例数量,如果为0 则根据重试次数进行重试,每次重试前沉默30秒

    PS: 在之前的文章中Eureka获取注册信息 ,讲过Eureka Client启动的时候默认会自动从Eureka Server获取注册信息, 要想Eureka Server在启动的时候可以同步其他集群节点的注册信息,那么必须开启客户端配置

    eureka.client.register-with-eureka = true    ## 是否作为一个Eureka Client 注册到Eureka Server上去
    2eureka.client.fetch-registry = true              ## 是否需要从Eureka Server上拉取注册信息到本地。
    

    只有开启了上面两个配置,那么集群节点在启动的时候,会初始化Eureka Client端的配置 ,会从其他Eureka Server拉取注册信息到本地,同时在初始化Eureka Server的时候,会从本地内存里面读取 注册信息,自动注册到本身的服务上。


    集群同步类型

    集群同步类型

    public enum Action {
    
          Heartbeat, Register, Cancel, StatusUpdate, DeleteStatusOverride;
     
          private com.netflix.servo.monitor.Timer timer = Monitors.newTimer(this.name());
     
          public com.netflix.servo.monitor.Timer getTimer() {
              return this.timer;
          }
      }
    
    
    //Heartbeat : 心跳续约
    
    //Register : 注册
    
    //Cancel : 下线
    
    //StatusUpdate : 添加覆盖状态
    
    //DeleteStatusOverride : 删除覆盖状态
    

    发起同步

    这里以注册的代码为例

      @Override
      public void register(final InstanceInfo info, final boolean isReplication) {
      
          int leaseDuration = Lease.DEFAULT_DURATION_IN_SECS;
          if (info.getLeaseInfo() != null && info.getLeaseInfo().getDurationInSecs() > 0) {
              leaseDuration = info.getLeaseInfo().getDurationInSecs();
          }
          // 发起注册
          super.register(info, leaseDuration, isReplication);
          // 注册完成后,在这里发起同步,同步类型为Register
         replicateToPeers(Action.Register, info.getAppName(), info.getId(), info, null, isReplication);
     }
     
     private void replicateToPeers(Action action, String appName, String id,
                                    InstanceInfo info /* optional */,
                                    InstanceStatus newStatus /* optional */, boolean isReplication) {
          Stopwatch tracer = action.getTimer().start();
          try {
              // 判断是否是集群同步请求,如果是,则记录最后一分钟的同步次数
              if (isReplication) {
                  numberOfReplicationsLastMin.increment();
              }
              // If it is a replication already, do not replicate again as this will create a poison replication
              // 集群节点为空,或者这是一个Eureka Server 同步请求,直接return
              if (peerEurekaNodes == Collections.EMPTY_LIST || isReplication) {
                  return;
              }
              // 循环相邻的Eureka Server Node, 分别发起请求同步
              for (final PeerEurekaNode node : peerEurekaNodes.getPeerEurekaNodes()) {
                  // 判断是否是自身的URL,过滤掉
                  if (peerEurekaNodes.isThisMyUrl(node.getServiceUrl())) {
                     continue;
                  }
                  // 发起同步请求
                 replicateInstanceActionsToPeers(action, appName, id, info, newStatus, node);
              }
         } finally {
             tracer.stop();
         }
    }
    

    步骤说明:

    • 判断集群节点是否为空,为空则返回
    • isReplication 代表是否是一个复制请求, isReplication = true 表示是其他Eureka Server发过来的同步请求。这个时候是不需要继续往下同步的。否则会陷入同步死循环
    • 循环集群节点,过滤掉自身的节点
    • 发起同步请求 ,调用replicateInstanceActionsToPeers

    PS: 这里提到了PeerEurekaNode , 对于PeerEurekaNodes的集群节点更新及数据读取,可以看这个深入Eureka Server启动源码分析,在服务启动的时候,对PeerEurekaNodes集群开启了线程更新集群节点信息。每15分钟一次

    private void replicateInstanceActionsToPeers(Action action, String appName,
                                                   String id, InstanceInfo info, InstanceStatus newStatus,
                                                   PeerEurekaNode node) {
          try {
              InstanceInfo infoFromRegistry = null;
              CurrentRequestVersion.set(Version.V2);
              switch (action) {
                  case Cancel: // 下线
                      node.cancel(appName, id);
                      break;
                 case Heartbeat:
                      // 心跳
                      InstanceStatus overriddenStatus = overriddenInstanceStatusMap.get(id);
                      // 获取本地最新的实例信息
                      infoFromRegistry = getInstanceByAppAndId(appName, id, false);
                      node.heartbeat(appName, id, infoFromRegistry, overriddenStatus, false);
                      break;
                 case Register: // 注册
                      node.register(info);
                      break;
                 case StatusUpdate:  // 设置覆盖状态
                      infoFromRegistry = getInstanceByAppAndId(appName, id, false);
                      node.statusUpdate(appName, id, newStatus, infoFromRegistry);
                      break;
                 case DeleteStatusOverride: //删除覆盖状态
                      infoFromRegistry = getInstanceByAppAndId(appName, id, false);
                      node.deleteStatusOverride(appName, id, infoFromRegistry);
                      break;
             }
         } catch (Throwable t) {
             logger.error("Cannot replicate information to {} for action {}", node.getServiceUrl(), action.name(), t);
         }
    }
    

    这里直接看注册,其他的原理上是一致的。PeerEurekaNode的register方法如下。

    public void register(final InstanceInfo info) throws Exception {
    
          long expiryTime = System.currentTimeMillis() + getLeaseRenewalOf(info);
          // 默认采用的是批处理
          batchingDispatcher.process(
                  taskId("register", info),
                  new InstanceReplicationTask(targetHost, Action.Register, info, null, true) {
                      public EurekaHttpResponse<Void> execute() {
                          return replicationClient.register(info);
                      }
                  },
                  expiryTime
         );
    }
    

    默认采用的是批量任务处理器,就是将task放入任务队列中,然后通过线程获取任务队列里面的任务,模仿ThreadExecutorPool的方式,生成线程,从队列里面抓取任务处理,统一批量执行,Eureka Server 那边也是统一接收,这样提高了同步效率。批量处理的任务执行器是com.netflix.eureka.cluster.ReplicationTaskProcessor

      @Override
      public ProcessingResult process(List<ReplicationTask> tasks) {
          // 构建ReplicationInstance放入ReplicationList 
          ReplicationList list = createReplicationListOf(tasks);
          try {
              // 发起批量处理请求
              EurekaHttpResponse<ReplicationListResponse> response = replicationClient.submitBatchUpdates(list);
              int statusCode = response.getStatusCode();
              if (!isSuccess(statusCode)) {
                 if (statusCode == 503) {
                     logger.warn("Server busy (503) HTTP status code received from the peer {}; rescheduling tasks after delay", peerId);
                     return ProcessingResult.Congestion;
                 } else {
                      // Unexpected error returned from the server. This should ideally never happen.
                      logger.error("Batch update failure with HTTP status code {}; discarding {} replication tasks", statusCode, tasks.size());
                      return ProcessingResult.PermanentError;
                 }
             } else {
                  // 处理执行结果 ,成功则调用handleSuccess ,失败则调用handleFailure。
                  handleBatchResponse(tasks, response.getEntity().getResponseList());
             }
         } catch (Throwable e) {
              if (isNetworkConnectException(e)) {
                  logNetworkErrorSample(null, e);
                  return ProcessingResult.TransientError;
             } else {
                  logger.error("Not re-trying this exception because it does not seem to be a network exception", e);
                  return ProcessingResult.PermanentError;
              }
          }
          return ProcessingResult.Success;
    }
    

    请求批量处理的接口地址 : peerreplication/batch/handleBatchResponse(tasks, response.getEntity().getResponseList()) , 循环调用处理结果,成功则调用handleSuccess. , 失败则调用handleFailure , 比如hearbeat的时候,调用返回码为404的时候,会重新发起注册。

    ReplicationTask replicationTask = new InstanceReplicationTask(targetHost, Action.Heartbeat, info, overriddenStatus, false) {
    
          @Override
          public EurekaHttpResponse<InstanceInfo> execute() throws Throwable {
              return replicationClient.sendHeartBeat(appName, id, info, overriddenStatus);
          }
      
          @Override
          public void handleFailure(int statusCode, Object responseEntity) throws Throwable {
              super.handleFailure(statusCode, responseEntity);
              if (statusCode == 404) {
                      // 重新发起注册。
                      register(info);
                 }
              } else if (config.shouldSyncWhenTimestampDiffers()) {
                  InstanceInfo peerInstanceInfo = (InstanceInfo) responseEntity;
                  if (peerInstanceInfo != null) {
                      syncInstancesIfTimestampDiffers(appName, id, info, peerInstanceInfo);
                 }
             }
         }
    };
    

    Eureka Server接收同步

    程序入口 : com.netflix.eureka.resources.PeerReplicationResource

      @Path("batch")
      @POST
      public Response batchReplication(ReplicationList replicationList) {
          try {
              ReplicationListResponse batchResponse = new ReplicationListResponse();
              // 循环请求的任务
              for (ReplicationInstance instanceInfo : replicationList.getReplicationList()) {
                  try {
                      // 分发任务,同时将处理结果收集起来,等会统一返回
                      batchResponse.addResponse(dispatch(instanceInfo));
                  } catch (Exception e) {
                      batchResponse.addResponse(new ReplicationInstanceResponse(Status.INTERNAL_SERVER_ERROR.getStatusCode(), null));
                      logger.error(instanceInfo.getAction() + " request processing failed for batch item "
                              + instanceInfo.getAppName() + '/' + instanceInfo.getId(), e);
                 }
             }
              return Response.ok(batchResponse).build();
         } catch (Throwable e) {
              logger.error("Cannot execute batch Request", e);
              return Response.status(Status.INTERNAL_SERVER_ERROR).build();
         }
     }
    
    
    private ReplicationInstanceResponse dispatch(ReplicationInstance instanceInfo) {
          //  创建实例
          ApplicationResource applicationResource = createApplicationResource(instanceInfo);
          // 创建实例
          InstanceResource resource = createInstanceResource(instanceInfo, applicationResource);
          //获取客户端instance的lastDirtyTimestamp  ,有点类似于版本号的概念。
          String lastDirtyTimestamp = toString(instanceInfo.getLastDirtyTimestamp());
          // 获取覆盖状态
          String overriddenStatus = toString(instanceInfo.getOverriddenStatus());
          // 获取instance的状态
          String instanceStatus = toString(instanceInfo.getStatus());
     
          Builder singleResponseBuilder = new Builder();
          switch (instanceInfo.getAction()) {
              case Register: // 注册
                  singleResponseBuilder = handleRegister(instanceInfo, applicationResource);
                  break;
             case Heartbeat: // 心跳续约
                  singleResponseBuilder = handleHeartbeat(resource, lastDirtyTimestamp, overriddenStatus, instanceStatus);
                  break;
              case Cancel:   // 下线
                  singleResponseBuilder = handleCancel(resource);
                  break;
             case StatusUpdate:  // 修改覆盖状态
                  singleResponseBuilder = handleStatusUpdate(instanceInfo, resource);
                  break;
             case DeleteStatusOverride: // 删除覆盖状态
                  singleResponseBuilder = handleDeleteStatusOverride(instanceInfo, resource);
                  break;
          }
          return singleResponseBuilder.build();
    }
    

    以上五个场景,这里就不一一说了,就说一下注册吧,

    private static Builder handleRegister(ReplicationInstance instanceInfo, ApplicationResource applicationResource) {
    
          // 调用Application控制层的接口,添加实例
          applicationResource.addInstance(instanceInfo.getInstanceInfo(), REPLICATION);
          return new Builder().setStatusCode(Status.OK.getStatusCode());
      }
      
      
      @POST
      @Consumes({"application/json", "application/xml"})
      public Response addInstance(InstanceInfo info,@HeaderParam(PeerEurekaNode.HEADER_REPLICATION) String isReplication) {
      
          // 省略代码1000行
          return Response.status(204).build();  // 204 to be backwards compatible
     }
    

    REPLICATION = “true” ,此次请求为true,表示是一个服务端的复制请求。

    由上面可以知道,集群同步走的和客户端注册的后续流程是一样的,只不过isReplication=true , 表明这是一个集群同步的请求


    本文小结

    本文详细介绍了Eureka Server集群同步相关的知识与核心源码。

    展开全文
  • 一张图告诉你Eureka集群原理

    千次阅读 2020-03-11 15:07:23
    问题: 微服务RPC远程服务调用最核心的是什么?...Eureka集群原理:互相注册,相互守望。 一个Eureka集群包含7001和7002等许多服务,在这个集群中,7001指向其他所有服务,7002也指向其他所有...
  • 1、前面我们分析了eureka服务端实现原理、客户端实现原理,今天我们来分析一下eureka集群同步原理,如何搭建以及使用eureka集群我们在前面以及演示过了,此处不在过多累赘。 2、eureka服务端也是客户端: 前面...
  • Eureka工作原理

    万次阅读 多人点赞 2019-07-03 10:46:48
    Eureka 工作原理 上节内容为大家介绍了,注册中心 Eureka 产品的使用,以及如何利用 Eureka 搭建单台和集群的注册中心。这节课我们来继续学习 Eureka,了解它的相关概念、工作流程机制等。 Eureka 作为 Spring Cloud...
  • 深入理解Eureka Server集群同步(十)

    千次阅读 2018-07-05 10:03:23
    集群启动同步 protected void initEurekaServerContext() throws Exception { // ....省略N多代码 // 同步信息 int registryCount = this.registry.syncUp(); // ....省略N多代码 } void ...
  • Eureka 集群

    2019-06-11 18:09:00
    Eureka 集群 集群搭建是在单节点基础上做的 单节点注册中心搭建-->https://www.cnblogs.com/chenglc/p/9561295.html 在单节点的基础上修改配置文件bootstrap.yml spring.application.name: ...
  • Redis集群搭建 Eureka集群搭建 Linux下rabbitMQ集群搭建 redis容错机制 springboot连接redis集群 Redis的持久化 Redis哨兵模式 redis缓存击穿 Redis缓存雪崩 安装erlang RabbitMQ集群搭建 保证相同的erlang cookie ...
  • Eureka-Server 集群原理

    千次阅读 2019-09-26 17:55:26
    Eureka 集群的工作原理。我们假设有三台 Eureka Server 组成的集群,第一台 Eureka Server 在北京机房,另外两台 Eureka Server 在深圳和西安机房。这样三台 Eureka Server 就组建成了一个跨区域的高可用集群,只要...
  • 首先搞清楚一个问题:Eureka Server集群数据同步Eureka Server集群数据备份,是同一个概念吗? 很显然,不是一个概念。 Eureka Server集群数据同步处理的是Eureka Client发起的数据同步请求。 Eureka Server集群...
  • Spring-Cloud-Netflix-Eureka集群搭建eureka集群原理搭建流程 eureka集群原理 服务启动后向Eureka注册,Eureka Server会将注册信息向其他Eureka Server进行同步, 当服务消费者要调用服务提供者,则向服务注册中心...
  • Eureka集群实现

    2020-03-23 11:06:47
    这里在本地机器搭建一个伪集群环境,通过两个节点实现相互注册,并通过主备数据同步实现高可用,实际生产环境可能有多个节点,原理一样。简单步骤如下: 【step1】:eureka配置文件如下 spring: application: name:...
  • 基于dns搭建eureka集群

    2018-04-09 18:29:00
    文/属衣 eureka集群方案: ...2.可能会有初学者和我一样,一开始的时候没有完全理解eureka集群原理,直接把每个eureka节点的url写进配置文件,期望所有的eureka节点进行相互注册。实际上,节...
  • Eureka 集群环境

    2020-08-16 17:16:51
    集群环境配置 新建工程springcloud-eureka-7002、springcloud-eureka-7003 按照7001为模板粘贴POM 修改7002和7003的主启动类 修改映射配置 , windows域名映射 集群配置分析 修改3个EurekaServer的yaml...
  • Eureka集群配置

    千次阅读 2019-07-02 20:30:17
    文章目录集群配置CAPCAP的3进2作为服务注册中心,Eureka比Zookeeper好在哪里Zookeeper保证CPEureka保证AP 集群配置 新建microservicecloud-eureka-7002/microservicecloud-eureka-7003 按照7001为模板粘贴POM 修改...
  • Eureka集群配置及使用

    千次阅读 2018-07-01 22:48:14
    eureka集群官方图 原理 上图是来自eureka的官方架构图,这是基于集群配置的eureka; - 处于不同节点的eureka通过Replicate进行数据同步 - Application Service为服务提供者 - Application Client为服务消费者...
  • 上一篇文章讲解了如何搭建单个节点的eureka,这篇讲解如何搭建eureka集群,这里的集群还是本地不同的端口执行三个eureka,因为条件不要允许,没有三台电脑,所以大家将就一下吧,eureka集群的目的就是防止一个点故障...
  • Eureka集群搭建

    2019-09-25 17:59:58
    服务注册、发现是微服务架构的关键原理之一,由于微服务架构是由一系列职责单一的细粒度服务构成的网状结构,服务之间通过轻量机制进行通信,这就必然引入一个服务注册发现的问题,也就是说服务提供方要注册报告服务...
  • SpringCloud服务注册中心双节点集群(Eureka集群)

    万次阅读 多人点赞 2018-08-09 11:34:37
    因此,在本例中使用springCloudEurekaCluster一个项目通过不同的启动参数来启动占用不同端口的两个Server服务,来模拟Eureka集群。则使用下面三个*.properties配置文件: application.properties application-...
  • 上一篇文章中我已经讲述了如何搭建一个简单的eureka注册中心和eureka客户端,但是在生产环境中我们如果只搭建一个eureka注册中心的话,那一但...eureka集群原理 服务启动后向Eureka注册,Eureka Server会将注册信...
  • 8.Eureka集群实战

    2019-11-20 15:20:36
    上图是来自eureka的官方架构图,这是基于集群配置的eureka; 处于不同节点的eureka通过Replicate进行数据同步 Application Service为服务提供者 Application Client为服务消费者 Make Remote Call完成一次服务调用 ...
  • Eureka服务注册原理及高可用集群配置  基本原理 上图是来自eureka的...- 处于不同节点的eureka通过Replicate进行数据同步  - Application Service为服务提供者  - Application Client为服务消费者  - Mak...
  • 【SpringCloud&Eureka】二、Eureka集群搭建

    千次阅读 多人点赞 2018-05-23 17:10:51
    上图是来自eureka的官方架构图,这是基于集群配置的eureka; 处于不同节点的eureka通过Replicate进行数据同步 Application Service为服务提供者 Application Client为服务消费者 Make Remote Call完成一次服务调用...
  • Eureka集群

    2021-06-25 15:05:43
    Eureka集群概述 如上图,是Eureka集群配置图。不同节点的Eureka Server通过Replicate(复制)进行数据同步: Application Service为服务提供者 Application Client为服务消费者 Make Remote Call完成一次服务...
  • 1. Eureka高可用原理在微服务中,注册中心非常核心,可以实现服务治理,如果一旦注册出现故障的时候,可能会导致整个微服务无法访问,在这时候就需要对注册中心实现高可用集群模式。默认情况下Eureka是让服务注册...
  • 点击上方“芋道源码”,选择“置顶公众号”技术文章第一时间送达!源码精品专栏 精尽 Dubbo 原理与源码专栏( 已经完成 69+ 篇,预计总共 75+ 篇 )中文详细注释...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,141
精华内容 2,456
关键字:

eureka集群同步原理