精华内容
下载资源
问答
  • eureka 踢出过时服务 几个月前,我与我的同事Lorenzo Dee进行了有关服务课程的对话。 “在许多情况下,您不需要它们……您只需将存储库直接注入Controller中即可。” 我很震惊! 这是什么异端! 这违反了关注分离!...

    eureka 踢出过时服务

    几个月前,我与我的同事Lorenzo Dee进行了有关服务课程的对话。 “在许多情况下,您不需要它们……您只需将存储库直接注入Controller中即可。” 我很震惊! 这是什么异端! 这违反了关注分离! 您的代码库将被僵化,紧密耦合的代码所困扰,这些代码将很难进行测试和更改! 我和他争辩了所有这些观点……以一种比我刚刚写的更有礼貌的方式。 我们俩都无法说服对方。

    洛伦佐(Lorenzo)在我们的辩论中拥有的一项优势是,他比我拥有更多的近期项目经验。 我上一次向生产中的企业系统提供任何代码是在2006年。一年前,我成立了Orange&Bronze Software Labs ,但是我很快就忙于运营公司,以至于我无法为实际项目贡献代码。以富有成效的方式 但是,直到那时,我还是按照表示,服务和集成(或持久性)这三个应用程序层来编写项目。

    为什么我们需要服务层?

    可测性

    我只使用普通的旧Servlet开始进行Web开发,当时我们只有这些。 然后Struts出现了。 即使使用Struts仍然存在的问题是为了测试您的应用程序,您必须将其部署到Servlet容器中。 这使得“测试驱动开发”非常缓慢且繁琐,甚至是诸如ServletUnit或Apache Cactus之类的专用工具。
    解决方案是将尽可能多的逻辑转移到不需要部署到容器的普通类中,因此可以使用普通的JUnit进行测试。 对我来说,这是服务最明显的好处之一。

    生存变化

    在Struts出现了框架的爆炸式增长之后,Wicket,Tapestry,Stripes,Stripe,WebWork(成为Struts 2)……框架的爆炸式增长也在持久性方面– Hibernate,JPO,Ibatis……还没有JPA标准。 想一想当今的Javascript框架正在发生什么,这就是2000年代初至中期的Java框架的情况。
    为了适应变化,系统的核心代码必须位于与明年可能要更改的任何特定框架无关的地方。 再次,这是服务层出现的地方。

    多视图

    即使在那时,您仍需要一种方法来支持多种客户端技术-HTML,桌面(Swing或Eclipse RCP),RMI,然后是更高版本的Web服务(SOAP,JSON)。 那时我们还没有视图解析器,所以我们不得不编写一个不同的Controller或编写大量的if块来处理多个视图。
    同样,将其余逻辑耦合到一个特定的视图将是一场灾难,因此您需要将逻辑推到独立的层,并且各种Controller都将位于该层的顶层。 这再次证明了服务层的合理性。

    发生了什么变化?

    最大的变化是标准– JPA等正式标准,以及诸如Spring Framework等事实上的标准。 由于标准化的原因,您现在可以在成千上万的大型企业应用程序中看到相同的技术堆栈(通常是Spring + JPA / Hibernate),通常需要十年甚至可以看到十年。 当那些技术看起来永远不会被蜜蜂取代时,与技术无关的层的经济理由就变得不那么重要了。
    这些技术带来了很多好处– AOP,视图分辨率,通过注释进行的声明式编程,基于约定的约定…如此之多,以至于今天我们发现服务层除了委托给其他类之外几乎无所要做– 惰性类 代码气味的定义!

    我的顿悟

    使我信服的是当我发现自己有一点空闲时间时。 有一个内部应用程序需要重写,但是没有开发人员有时间去做。 我决定试一试,因为我很清楚自己可能无法在再次忙之前完成。 这是我第一次使用Spring MVC ,并且在编写了我的第一个Controller之后,看到现在声明式处理了多少平常的工作,这真让我震惊!
    控制器现在非常薄 ,您可以将同一控制器用于多个视图 它们也可以用普通的JUnit进行测试 ,因为您不需要将它们部署到Container。
    由于Controller和Services几乎无所事事,我的面向对象培训要求我将两者合并!

    交易呢?

    但是对我来说,一个问题仍然是-交易。 如果您需要事务性操作,可以将@Transactional批注添加到Controller中吗?
    “是的,那是我唯一一次提供服务。” 洛伦佐说。 “当我发现一项操作需要进行事务处理时,这是我创建服务的唯一时间。”
    但是即使那样,我现在也提出质疑。 查看有关此主题的StackOverflow讨论的答案 制作Controllers @Transactional似乎没有技术障碍。 这是我需要用一些代码来验证的东西,但是当我这样做时,我将发布我的发现,如果一切顺利,我将把本文的标题更改为“服务层已过时!”…没有更多的问号!

    翻译自: https://www.javacodegeeks.com/2017/11/service-layer-obsolete.html

    eureka 踢出过时服务

    展开全文
  • eureka--踢出实例原理

    千次阅读 2018-05-06 11:03:03
    1. 为什么要踢出注册...但是:在网络世界踢出实例比现实世界有点复杂:原因是网络分区 网络分区:检测网络失败是很困难的,我们得到其他节点状态的信息就是通过网络来得到,延迟跟网络失败也无从区分。 2.eu...

    1. 为什么要踢出注册实例

    一个实例注册到eureka-server中。如果在规定的时间内没法发送心跳(续租)信息。服务器有权把它赶出。这类比于你租房,如果在规定的时间内你没有交房租,那么房东有权把你赶出。

    但是:在网络世界踢出实例比现实世界有点复杂:原因是网络分区

     网络分区:检测网络失败是很困难的,我们得到其他节点状态的信息就是通过网络来得到,延迟跟网络失败也无从区分。
    

    2.eureka 如何解决网络分区

    1. eukeka server默认开启了自我保护机制,当然可以关闭
    2. 如果开启自我保护机制。则eureka踢出实例时有一个最大的踢出个数(不能把所有的实例都踢出,剩下的要保护起来,不能在踢出了)。

      int expiredLeasesSize= 过期实例数;
      int registrySizeThreshold = (int) (registrySize * serverConfig.getRenewalPercentThreshold());//需要保护的最小实例数
      int toEvict = Math.min(expiredLeases.size(), evictionLimit);//server端决定本次踢出的实例数
      
    3. server端踢出时有一定的技巧,那就是随机的踢出toEvit大小的实例。如果不随机踢出,那么会造成整个应用下线。不可提供服务。这样影响应该均匀的分布到所有的应用中。

    3. eukeak 踢出源码实现

    3.1 eureka 通过一个Timer定时器来定时的踢出过期的实例

    private Timer evictionTimer = new Timer("Eureka-EvictionTimer", true);
    
     //定时任务的初始化方法
     protected void postInit() {
           //...其他代码
           evictionTaskRef.set(new EvictionTask());
           evictionTimer.schedule(evictionTaskRef.get(),
                   serverConfig.getEvictionIntervalTimerInMs(),
                   serverConfig.getEvictionIntervalTimerInMs());
       }

    一个定时器,必须有个任务。我们首先看下踢出过期实例的任务:EvictionTask

    2.1.1 EvictionTask源码分析

    重点看下。补偿时间的实现。
    为什么定时任务执行时需要注意补偿时间?
    假如一个定时任务在10:00开始,每隔1秒执行一次任务,但是由于full gc (Stop the word) 或者别的原因,造成下次任务实际执行的时间是:10:02。因此任务执行有延迟。整整延迟了1秒,这l秒就是上面提到的补偿时间。

    补偿时间计算算法实现:

    1. 一个变量存放上次定时任务执行的具体时间点,如:
      lastExecutionNanosRef

    2. 计算从上次任务执行以来到本地任务执行的时间差值:

       long elapsedMs = TimeUnit.NANOSECONDS.toMillis(currNanos - lastNanos);
      
    3. 计算补偿时间:两次任务的时间间隔差- 定时任务的时间间隔差

       long compensationTime = elapsedMs - serverConfig.getEvictionIntervalTimerInMs();
      
    4. compensationTime<=0 ? 0:compensationTime

      源码:

      /**
      * 长时间没有续租时,进行回收的定时任务
      *
      * eviction:回收
      */
      /* visible for testing */
      class EvictionTask extends TimerTask {
      
         private final AtomicLong lastExecutionNanosRef = new AtomicLong(0l);
      
         @Override
         public void run() {
             try {
                 long compensationTimeMs = getCompensationTimeMs();
                 logger.info("Running the evict task with compensationTime {}ms", compensationTimeMs);
                 evict(compensationTimeMs);
             } catch (Throwable e) {
                 logger.error("Could not run the evict task", e);
             }
         }
      
         /**
          * compute a compensation time defined as the actual time this task was executed since the prev iteration,
          * vs the configured amount of time for execution. This is useful for cases where changes in time (due to
          * clock skew or gc for example) causes the actual eviction task to execute later than the desired time
          * according to the configured cycle.
          *
          * 计算一个补偿时间作为下一个任务实际执行的时间。为什么这么做:是由于gc或者时钟便宜造成的时间改变。
          * 造成时间任务执行的时间比期望的时间晚点。
          *
          *
          *
          */
         long getCompensationTimeMs() {
             /**当前时间的纳秒*/
             long currNanos = getCurrentTimeNano();
      
             /**以原子方式设置新值。并返回旧值*/
             long lastNanos = lastExecutionNanosRef.getAndSet(currNanos);
             if (lastNanos == 0l) {
                 return 0l;
             }
      
             /**
              * elapsed 表示过去的时间
              * 自从上个定时任务执行以来。已经过了这么长时间
              */
             long elapsedMs = TimeUnit.NANOSECONDS.toMillis(currNanos - lastNanos);
      
             /**
              * 补偿时间 == 过去的时间 - 定时回收的时间间隔
              *
              * < 0 ;代表时间还没到
              * > = 0;表示时间已经过了。需要补偿这部分时间差值
              */
             long compensationTime = elapsedMs - serverConfig.getEvictionIntervalTimerInMs();
      
      
             return compensationTime <= 0l ? 0l : compensationTime;
         }
      
         long getCurrentTimeNano() {  // for testing
             return System.nanoTime();
         }
      
      }
    2.1.2 踢出源码分析
    1. 要解决的问题:网络分区
    2. 自我保护机制
    3. full gc等引起的补偿时间
    4. 洗牌算法 shuffle 参考:
      https://blog.csdn.net/ai_xiangjuan/article/details/80210899
    /**
        * 踢出过期实例
        * @param additionalLeaseMs
        */
       public void evict(long additionalLeaseMs) {
           logger.debug("Running the evict task");
    
           /**
            * 是否支持续租过期
            */
           if (!isLeaseExpirationEnabled()) {
               logger.debug("DS: lease expiration is currently disabled.");
               return;
           }
    
           // We collect first all expired items, to evict them in random order. For large eviction sets,
           // if we do not that, we might wipe out whole apps before self preservation kicks in. By randomizing it,
           // the impact should be evenly distributed across all applications.
    
           /**
            * 收集所有的过期项到一个集合中,然后随机的踢出它们。
            * 对于一个较大的踢出集合项,如果我们不这么做(随机的踢出),在进入自我保护之前,我们可能移除某个app的整个实例
            * 这样影响应该均匀的分布到所有的应用程序中
            */
           List<Lease<InstanceInfo>> expiredLeases = new ArrayList<>();
           for (Entry<String, Map<String, Lease<InstanceInfo>>> groupEntry : registry.entrySet()) {
               Map<String, Lease<InstanceInfo>> leaseMap = groupEntry.getValue();
               if (leaseMap != null) {
                   for (Entry<String, Lease<InstanceInfo>> leaseEntry : leaseMap.entrySet()) {
                       Lease<InstanceInfo> lease = leaseEntry.getValue();
                       /***
                        * 判断实例过期;用到了补偿时间
                        */
                       if (lease.isExpired(additionalLeaseMs) && lease.getHolder() != null) {
                           /**添加到过期实例的集合中*/
                           expiredLeases.add(lease);
                       }
                   }
               }
           }
    
           // To compensate for GC pauses or drifting local time, we need to use current registry size as a base for
           // triggering self-preservation. Without that we would wipe out full registry.
    
           /**本地注册表大小*/
           int registrySize = (int) getLocalRegistrySize();
    
           /**本地注册表的最大值。即阈值*/
           /**最小续订百分比。
            * 如果续租小于这个阀值。则过期会被禁用如果开启自我保护时。*/
           int registrySizeThreshold = (int) (registrySize * serverConfig.getRenewalPercentThreshold());
    
           /**
            * 踢出的最大限制
            */
           int evictionLimit = registrySize - registrySizeThreshold;
    
           /**
            * 决定踢出的实例数
            */
           int toEvict = Math.min(expiredLeases.size(), evictionLimit);
           if (toEvict > 0) {
               logger.info("Evicting {} items (expired={}, evictionLimit={})", toEvict, expiredLeases.size(), evictionLimit);
    
               /**
                * 创建一个随机数
                */
               Random random = new Random(System.currentTimeMillis());
               for (int i = 0; i < toEvict; i++) {
                   // Pick a random item (Knuth shuffle algorithm)
                   //Knuth shuffle algorithm 参考:https://blog.csdn.net/ai_xiangjuan/article/details/80210899
                   //随机的挑选一个
                   int next = i + random.nextInt(expiredLeases.size() - i);
    
                   //跟尾部的数组进行交换
                   Collections.swap(expiredLeases, i, next);
                   Lease<InstanceInfo> lease = expiredLeases.get(i);
    
                   String appName = lease.getHolder().getAppName();
                   String id = lease.getHolder().getId();
                   EXPIRED.increment();
                   logger.warn("DS: Registry: expired lease for {}/{}", appName, id);
                   internalCancel(appName, id, false);
               }
           }
       }
    展开全文
  • 一、如何在spring boot的注册中心中踢出某个服务 二、解读 http://192.168.100.135:8141/eureka/apps/HOLDER-SAAS-STORE-REPORT/192.168.102.240:8997/status?value=OUT_OF_SERVICE 1.采用put请求 2.第一个...

    一、如何在spring boot的注册中心中踢出某个服务

    二、解读

    http://192.168.100.135:8141/eureka/apps/HOLDER-SAAS-STORE-REPORT/192.168.102.240:8997/status?value=OUT_OF_SERVICE

    1.采用put请求

    2.第一个地址是服务中心的地址,即:192.168.100.135:8141

    3.服务名,即:HOLDER-SAAS-STORE-REPORT

    4.服务地址,即:192.168.102.240:8997

    5.状态,即:OUT_OF_SERVICE

    6.如果是注册,即:UP

     

    展开全文
  • Eureka深入理解

    2019-11-05 10:33:33
    一、Eureka Environment配置和Eureka ...四、如何解决Eureka Server不踢出已关停的节点的问题? 五、Eureka配置instanceId显示IP 一、Eureka Environment的配置 启动Eureka后,我们可以看到默认的环境和数据中...

    一、Eureka Environment配置和Eureka DataCenter的配置

    二、Eureka开启自我保护的提示

    三、Eureka注册服务慢的问题如何解决?

    四、如何解决Eureka Server不踢出已关停的节点的问题?

    五、Eureka配置instanceId显示IP

     

    一、Eureka Environment的配置

    启动Eureka后,我们可以看到默认的环境和数据中心

    我们配置一下eureka.environment和eureka.datacenter

    security:
      basic:
        enabled: true
      user:
        name: user
        password: password123
    server:
      port: 8761
    eureka:
      client:
        register-with-eureka: false
        fetch-registry: false
        service-url:
          defaultZone: http://user:password123@localhost:8761/eureka
      environment: local
      datacenter: cloud

    二、Eureka开启自我保护的提示

    Eureka server和client之间周期性心跳,每隔30秒会进行一次。
    下图中我们看到Renews threshold和Renews (last min)
    Renews threshold:server期望在每分钟中收到的心跳次数 
    Renews (last min):上一分钟内收到的心跳次数

    我关闭掉7900和7910后就出现了红色部分的提示

    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进入了自我保护机制,默认情况下,如果EurekaServer在一定时间内没有接收到某个微服务实例的心跳时,EurekaServer将会注销该实例(默认90s)。但是当网络发生故障时,微服务与EurekaServer之间无法通信,这样就会很危险了,因为微服务本身是很健康的,此时就不应该注销这个微服务,而Eureka通过自我保护机制来预防这种情况,当网络健康后,该EurekaServer节点就会自动退出自我保护模式。

    四、如何解决Eureka Server不踢出已关停的节点的问题?

    server端:
    eureka.server.enable-self-preservation            (设为false,关闭自我保护主要)
    eureka.server.eviction-interval-timer-in-ms     清理间隔(单位毫秒,默认是60*1000)client端:
    eureka.client.healthcheck.enabled = true                开启健康检查(需要spring-boot-starter-actuator依赖)
    eureka.instance.lease-renewal-interval-in-seconds =10        租期更新时间间隔(默认30秒)
    eureka.instance.lease-expiration-duration-in-seconds =30  租期到期时间(默认90秒)
    示例:
    服务器端配置:

    eureka:
        server:
            enableSelfPreservation: false
            evictionIntervalTimerInMs: 4000

    客户端配置:

    eureka:
        instance:
            leaseRenewalIntervalInSeconds: 5 ---每隔5s心跳一次,证明本服务还活着
            leaseExpirationDurationInSeconds: 10 ---本服务10s内没有心跳,就将该服务从服务端剔除

     

    THE SELF PRESERVATION MODE IS TURNED OFF.THIS MAY NOT PROTECT INSTANCE EXPIRY IN CASE OF NETWORK/OTHER PROBLEMS.

    在配置上,自我保护机制关闭了,但是一分钟内的续约数没有达到85% , 可能发生了网络分区,会有如下提示

     

    五、Eureka配置instanceId显示IP:${spring.cloud.client.ipAddress}

    eureka:
    
      instance:
        prefer-ip-address: true
        instance-id: ${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}

     

    展开全文
  • 问题:系统会根据业务被拆分成了很多的微服务,微服务的信息如何管理?...2. 微服务会实时上报自己的状态,注册中心统一管理这些微服务的状态,将存在问题的服务踢出服务列 表,客户端获取到可用的服务进行调...
  • Eureka自我保护机制

    2019-11-29 22:33:48
    概念: ...便会把该实例从注册服务列表中剔除(默认是90秒),但是在短时间内丢失大量的实例心跳,这时候EurekaServer会开启自我保护机制,Eureka不会踢出服务。 自我保护机制的目的: ...
  • 一个eureka会出现单点故障 这里整两个 eureka--1 application.yml: ...#唯一标示eureka注册中心 方便互相识别 ...eureka: ... hostname: eureka ...# 服务过了90秒没续约 默认你炸了 踢出 lease-expirat...
  • Eureka注册中心

    2020-12-30 02:23:30
    前言 现在的项目很多都是前后端...微服务会实时上报自己的状态,注册中心统一管理这些微服务的状态,将存在问题的服务踢出服务列表,客户端获取到可用的服务进行调用。 1、Eureka介绍 Spring Cloud Eureka 是对Netfl
  • Eureka的自我保护机制

    2018-12-06 12:12:50
    便会把该实例从注册服务列表中剔除(默认是90秒),但是在短时间内丢失大量的实例心跳,这时候EurekaServer会开启自我保护机制,Eureka不会踢出服务。 为了防止EurekaClient是可以正常访问,但是与EurekaSe...
  • SpringCloud的Eureka

    千次阅读 2019-03-17 14:24:02
    Eureka 类似zokeerper的功能.... 2、微服务会实时上报自己的状态,注册中心统一管理这些微服务的状态,将存在问题的服务踢出服务列表,客户 端获取到可用的服务进行调用。 Eureka提供服务端与客...
  • Eureka和Ribbon简介

    2021-05-30 12:36:45
    2、微服务会实时上报自己的状态,注册中心统一管理这些微服务的状态,将存在问题的服务踢出服务列表,客户端获取到可用的服务进行调用。 Eureka Server搭建 创建xc-govern-center工程。 需要引入相关依
  • 微服务会实时上报自己的状态,注册中心统一管理这些微服务的状态,将存在问题的服务踢出服务列表,客户端获取到可用的服务进行调用。 Eureka注册中心(转) Spring Cloud Eureka 是对Netflix公司的Eureka的二次...
  • 便会把该实例从注册服务列表中剔除(默认是90秒),但是在短时间内丢失大量的实例心跳,这时候EurekaServer会开启自我保护机制,Eureka不会踢出服务。 自我保护模式可以让集群更加健壮,但是我们在开...
  • 2、微服务会实时上报自己的状态,注册中心统一管理这些微服务的状态,将存在问题的服务踢出服务列表,客户端获取到可用的服务进行调用。 Eureka介绍 Spring Cloud Eureka 是对Netflix公司的Eureka的二次封装,它实现
  • 1.1 需求分析 ...2、微服务会实时上报自己的状态,注册中心统一管理这些微服务的状态,将存在问题的服务踢出服务列表,客户端获取到可用的服务进行调用。 1.3 Eureka注册中心 1.3.1 Eureka介绍 ​ Spring C
  • 1 Eureka注册中心1.1 需求分析在... 2、微服务会实时上报自己的状态,注册中心统一管理这些微服务的状态,将存在问题的服务踢出服务列表,客户 端获取到可用的服务进行调用。 1.3 Eureka注册中心 1.3.1 Eureka介绍 Sp
  • 学习Eureka注册中心

    2019-04-17 21:43:23
    需求分析 在前后端分离架构中,服务层被拆分成了很多的微服务,微服务的信息如何...2、微服务会实时上报自己的状态,注册中心统一管理这些微服务的状态,将存在问题的服务踢出服务列表,客户端获取到可用的服务进...
  • 2、微服务会实时上报自己的状态,注册中心统一管理这些微服务的状态,将存在问题的服务踢出服务列表,客户端获取到可用的服务进行调用。 Eureka服务工程单机环境搭建 1.创建Eureka工程(启动类) @EnableEurekaServer...
  • Eureka注册中心 ... 微服务的ip和端口管理 在前后台分离大型架构中,服务层被拆成了很多的微服务,前端要进行远程...微服务会实时上报自己的状态,注册中心统一管理这些微服务的状态,将存在问题的服务踢出服务列表,...
  • 服务名称 spring.application.name=eureka 服务端口 server.port= 设定access log 的目录. ...#关闭自我保护,防止因保护模式而不将挂掉的服务踢出eureka.server.enable-self-preservation=false #eurek...
  • 1 Eureka注册中心1.1需求分析在前后端分离架构中,服务层被拆分成了很多的微服务,微服务的信息如何管理?...2、微服务会实时上报自己的状态,注册中心统一管理这些微服务的状态,将存在问题的服务踢出服务...
  • ... 1、微服务数量众多,要进行远程调用就需要知道服务端的ip地址...2、微服务会实时上报自己的状态,注册中心统一管理这些微服务的状态,将存在问题的服务踢出服务列表,客户 端获取到可用的服务进行调用。 Spring Cl...
  • Spring Cloud Eureka 服务关闭但是未从注册中心剔除 ...# 测试时将值设置设置小些,保证服务关闭后注册中心能及时踢出服务 eureka.instance.lease-renewal-interval-in-seconds=2 #2秒发心跳 eureka.ins...
  • 目录: 1、Eureka 1.1、Eureka Environment的配置: 1.2、Eureka DataCenter的配置...1.5、如何解决Eureka Server不踢出已关停的节点的问题? 1.6、Eureka配置instanceId显示IP 1.7、Eureka配置最佳实践总结 2...
  • 便会把该实例从注册服务列表中剔除(默认是90秒),但是在短时间内丢失大量的实例心跳,这时候EurekaServer会开启自我保护机制,Eureka不会踢出服务。 自我保护模式可以让集群更加健壮,但是我们在开发测试阶段,...
  • SpringCloud 组件

    2021-02-26 17:51:48
    服务续约:向eureka报告服务健康状况 是否需要踢出列表 通过心跳机制 ribbon 1.负载均衡策略 轮询 随机 权重 地区。。。。 2.修改默认轮询策略 在配置类中加上一个IRule的Bean 3.优化 连接超时配置 重置...
  • springcloud配置

    2021-04-17 20:56:02
    #告诉服务端,如果我10s之内没有给你发心跳,就代表我故障了,将我踢出 eureka.instance.lease-expiration-duration-in-seconds=10 #告诉服务端,服务实例以IP作为链接,而不是取机器名 eureka.instance.prefer-ip-...

空空如也

空空如也

1 2
收藏数 32
精华内容 12
关键字:

eureka踢出服务