首页 > 技术文章 > 2--SpringCloud 和 Eureka 周阳老师

coderD 2021-01-30 19:10 原文

2021:2--SpringCloud 和 Eureka

https://www.cnblogs.com/coderD/p/14350076.html SpringCloud

https://www.cnblogs.com/coderD/p/14350073.html SpringCloud 和 Eureka

https://www.cnblogs.com/coderD/p/14350082.html SpringCloud 和 Zookeeper

https://www.cnblogs.com/coderD/p/14350086.html SpringCloud-Ribbon/OpenFeign

https://www.cnblogs.com/coderD/p/14350091.html SpringCloud:Hystrix 断路器

https://www.cnblogs.com/coderD/p/14350097.html SpringCloud:服务网关 gateway

https://www.cnblogs.com/coderD/p/14350099.html SpringCloud:Config/Bus

https://www.cnblogs.com/coderD/p/14350103.html SpringCloud:Stream/Sleuth

https://www.cnblogs.com/coderD/p/14350110.html SpringCloud Alibaba:Nacos

https://www.cnblogs.com/coderD/p/14350114.html SpringCloud Alibaba:Sentinel

https://www.cnblogs.com/coderD/p/14350119.html SpringCloud Alibaba:Seata

代码:https://gitee.com/xue--dong/spring-cloud

阳哥脑图:https://gitee.com/xue--dong/spring-cloud

主要内容

Eureka服务注册与发现
单机Eureka构建
集群Eureka构建
复制代码

1 Eureka 基础知识

    前面我们没有服务注册中心,也可以服务间调用,为什么还要服务注册?

    当服务很多时,单靠代码手动管理是很麻烦的,需要一个公共组件,统一管理多服务之间的相互调用。

    Eureka用于服务注册,目前官网已经停止更新。
复制代码

1.1 什么是服务治理

    SpringCloud 封装了 Netflix 公司开发的Eureka模块来实现服务治理
    
    在传统的rpc远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,所以需要使用服务治理,
    管理服务与服务之间依赖关系,可以实现服务调用,负载均衡,容错等,实现服务发现与注册。
    
    n个生产者和n个消费者之间相互调用。
复制代码

1.2 什么是服务注册与发现

    如果你的服务注册中心只有一台机器,那么只要它一宕机,就会产生单点故障。
    所以一般服务注册中心能配多个就配多个,主要就是为了避免单点故障。
复制代码

img

img

1.3 Eureka 的两个组件

    1.  Eureka Server:提供服务注册的服务。
    
        各个微服务节点通过配置启动后,会在EurekaServer中进行注册,这样EurekaServer中的服务注册
        表将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观看到。
    
    2.  Eureka Client:微服务通过其和Eureka Server保持通信。
    
        它是一个Java客户端,用于简化微服务和EurekaServer的交互。客户端同时也具备一个内置的,
        使用轮询(round-robin)负载算法的负载均衡器。
        在应用启动后,将会向EurekaServer发送心跳(默认周期30s)。如果EurekaServer在多个心跳
        周期内没有接收到某个节点的心跳,EurekaServer将会从服务注册表中把这个服务节点移除(默认90s)。
复制代码

2 单机 Eureka 构建步骤

img

2.1 建 module:cloud-eureka-server7001

img

2.2 改 pom

1.  1.x和2.x的Eureka依赖对比说明

    1.x:
复制代码
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
复制代码
    2.x
复制代码
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
复制代码
2.  添加依赖
复制代码
    <dependencies>
        <!--eureka server-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>

        <!--引入我们自定义的公共api jar包-->
        <dependency>
            <groupId>com.atguigu.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--图形监控-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <!--一般通用配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
复制代码

2.3. 写 yml

        Eureka服务器 请求地址:
        http://${eureka.instance.hostname}:${server.port}/eureka/
        http:/localhost:7001/eureka/
复制代码
    server:
      port: 7001
    
    eureka:
      instance:
        hostname: localhost
      client:
        # false表示不向注册中心注册自己(中介不用注册了)
        register-with-eureka: false
        # false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
        fetch-registry: false
    
        service-url: 
          # 设置Eureka Server交互的地址查询服务和注册服务都需要依赖这个地址
          defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
复制代码

2.4 主启动类

    注意开启注解:@EnableEurekaServer
    指明该模块作为Eureka注册中心的服务器。
复制代码
    @EnableEurekaServer
    @SpringBootApplication
    public class EurekaMain7001 {
        public static void main(String[] args) {
            SpringApplication.run(EurekaMain7001.class, args);
        }
    }
复制代码

2.5 service 类

  Eureka Server不需要写service类
复制代码

2.6 测试

    启动,发送http://localhost:7001/ 请求
复制代码

img

    测试成功

    只是目前还没有任何实例(微服务)注册尽进来。
复制代码

img

3. 微服务注册

3.1 生产者微服务 8001 注册 EurekaServer

1.  改POM
    
    添加一个Eureka-Client依赖:
复制代码
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
复制代码
2.  改yml:添加如下配置
复制代码
eureka:
  client:
    # 表示将自己注册进EurekaServer默认为true
    register-with-eureka: true
    # 表示可以从Eureka抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
    fetch-registry: true
    service-url: 
      defaultZone: http://localhost:7001/eureka
复制代码
3.  修改主启动类

    添加注解:@EnableEurekaClient。
    指明这是一个Eureka客户端,要注册进EurekaServer中。
复制代码
    @SpringBootApplication
    @EnableEurekaClient
    public class PaymentMain8001 {
        public static void main(String[] args) {
            SpringApplication.run(PaymentMain8001.class, args);
        }
    }
复制代码
4.  测试

    启动Payment8001模块:
复制代码

img

    发现我们的8001服务注册进来了。
    
    红色字体是Eureka的自我保护机制,后面再详细说。
    
    注意:注册进来的服务名,就是我们在该服务yml文件中配置的微服务名
复制代码

img

3.2 消费者微服务 80 注册进 EurekaServer

1.  改POM
    
    添加Eureka Client 依赖
复制代码
        <!--eureka client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
复制代码
2.  改yml
复制代码
    # 微服务名称
    spring:
      application:
        name: cloud-order-service
        
    eureka:
      client:
        # 表示将自己注册进EurekaServer默认为true
        register-with-eureka: true
        # 表示可以从Eureka抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
        fetch-registry: true
        service-url:
          defaultZone: http://localhost:7001/eureka 
复制代码
3.  修改主启动类

    添加:@EnableEurekaClient

4.  测试:
    启动消费者80微服务。
    
    刷新http://localhost:7001/页面:消费者80微服务也注册进来了。
复制代码

img

5.  测试微服务调用
复制代码

img

6.  不想将那个服务注册,就在yml中配置
复制代码
    eureka:
      client:
        register-with-eureka: false
复制代码
    重启服务再刷新EurekaServer主页
复制代码

img

小结:单机Eureka构建步骤到此就创建完成了。
复制代码

img

4 集群 Eureka 构建步骤

    单机版Eureka构建到这就结束了,但是企业中不可能有谁敢说它的服务注册中心是单机版。
    因为没有集群的高可用,就会带来一个严重的问题,单点故障。
    
    1.  Eureka集群原理说明
    2.  EurekaServer集群环境构建步骤
    3.  将支付服务8001微服务发布到上面2台Eureka集群配置中
    4.  将订单服务80微服务发布到上面2台Eureka集群配置中
    5.  测试01
    6.  支付服务提供者8001集群环境构建。
    7.  负载均衡
    8.  测试02
复制代码

4.1 Eureka 集群原理说明

    Eureka流程原理:
复制代码

img

    Eureka集群原理:互相注册,相互守望
复制代码

img

4.2 EurekaServer 集群环境构建步骤

4.2.1 新建一个 cloud-eureka-server7002 模块
    1.  新建一个cloud-eureka-server7002模块
复制代码
4.2.4 pom 依赖
    2.  pom依赖同cloud-eureka-server7001
复制代码
4.2.4 修改两个 EurekaServer 的 yml 配置
    4.  yml
        
        现在有多台Eureka服务器,所以没台Eureka服务器都要有自己的主机名。
        
        同时Eureka7001和Eureka7002要互相注册。
        
        我们先修改映射配置文件:第3步
        
        1.  Eureka7001的yml
复制代码
        server:
          port: 7001
        
        eureka:
          instance:
            hostname: eureka7001.com  #eureka服务端的实例名称
          client:
            # false表示不向注册中心注册自己(中介不用注册了)
            register-with-eureka: false
            # false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
            fetch-registry: false
        
            service-url:
              # 以7001作为服务提供者,向该指定的服务注册中心的位置注册7001服务
              defaultZone: http://eureka7002.com:7002/eureka/
复制代码
        2.  Eureka7002的yml
复制代码
            server:
              port: 7002
            
            eureka:
              instance:
                hostname: eureka7002.com  #eureka服务端的实例名称
              client:
                # false表示不向注册中心注册自己(中介不用注册了)
                register-with-eureka: false
                # false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
                fetch-registry: false
            
                service-url:
                  # 以7002作为服务提供者,向该指定的服务注册中心的位置注册7002服务
                  defaultZone: http://eureka7001.com:7001/eureka/
复制代码
4.2.3 修改域名映射配置文件
    3.  修改映射配置文件
    
        修改:C:\Windows\System32\drivers\etc 路径下的host文件
        
        受限于我们只有一台物理机器,我们用不同的端口号来映射同一个地址。
复制代码

img

        这样修改是是什么意思:
            由于我只有一台电脑,而且将这台电脑也作为服务器。每次我们发送localhost,就会被域名解析器
        解析成127.0.0.1,也就是我们本机的ip回送地址,访问我们本机。
            
            现在我们将eureka7001.com和eureka7002.com作为域名映射到127.0.0.1,那么我们就可以
        模拟请求不同的服务器名。实际上都会解析到我们本机。
        
        注意这个映射修改了不意味着localhost 127.0.0.1之间的映射关系没有,还有。
        即localhost/eureka7001.com/eureka7002.com 都会被域名解析器解析成127.0.0.1
            
        例子1:
            之前的单机的EurekaServer的yml配置:
            server.port=7001
            eureka.instance.hostname=localhost
            eureka.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
            
            那么我通过发送http://localhost:7001/eureka能访问到服务器在本地主机的EurekaServer。
            
        例子2:以两个集群为例
            现在集群的EurekaServer的yml配置
            server.port=7001
            eureka.instance.hostname=eureka7001.com
            eureka.service-url.defaultZone=http://eureka7002.com:7002/eureka/
            
            server.port=7002
            eureka.instance.hostname=eureka7002.com
            eureka.service-url.defaultZone=http://eureka7001.com:7001/eureka/ 
            
            那么这样配置后,我们就可以通过:
                http://eureka7001.com:7001和http://eureka7002.com:7002来
                分别访问这两个EurekaServer。
                同时这两个EurekaServer实现了互相注册。
复制代码
4.2.5 主配置类
        @SpringBootApplication
        @EnableEurekaServer
        public class EurekaMain7002 {
            public static void main(String[] args) {
                SpringApplication.run(EurekaMain7002.class, args);
            }
        }
复制代码
4.2.6 测试
    开启eureka7002 和 eureka7001 这两个服务
    
    测试:  http://localhost:7001/ 和 http://localhost:7002/ 
            
            都成功连接。        
复制代码

img

    测试:  http://eureka7002.com:7002/ 和 http://eureka7001.com:7001/
  
            都成功连接。
复制代码

img

    并且实现了两个Euraka服务器的相互注册:
复制代码

img

img

4.2.7 我又测试一个 eureka7003
server:
  port: 7003

eureka:
  instance:
    hostname: eureka7003.com  #eureka服务端的实例名称
  client:
    # false表示不向注册中心注册自己(中介不用注册了)
    register-with-eureka: false
    # false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
    fetch-registry: false

    service-url:
      # 以7001作为服务提供者,向该指定的服务注册中心的位置注册7001服务
      defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7001.com:7001/eureka/
复制代码
将其注册到eureka7002和eureka7001中。
复制代码

img

5 注册提供者微服务和消费者微服务

5.1 将提供者服务 8001 微服务发布到上面的 3 台 Eureka 集群配置中

    1.  修改yml
复制代码
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
    2.  其他不改
复制代码

5.2 将消费者服务 80 微服务发布到上面的 3 台 Eureka 集群配置中

    1.  修改yml
复制代码
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
    2.  其他不改
复制代码

5.3 测试

    1.  启动顺序
        先启动Eureka 7001/7002/7003
        在启动payment8001,order80
        
    2.  测试:http://eureka7003.com:7003/  成功
复制代码

img

    3.  测试:http://eureka7001.com:7001/和http://eureka7002.com:7002/
        
        略...
    
    4.  测试order80微服务
复制代码

img

img

6 生产者微服务集群构建

    一个提供者微服务不可能应付所有的消费者微服务。
复制代码

img

6.1 新建 cloud-provider-payment8002 微服务

1.  POM和cloud-provider-payment8001一致
    
    此处有差别:
复制代码

img

2.  写yml:

    和payment8001一致,只改一个端口。
复制代码
    # 微服务端口号
    server:
      port: 8002
复制代码
3.  主启动类
复制代码
    @SpringBootApplication
    @EnableEurekaClient
    public class PaymentMain8002 {
        public static void main(String[] args) {
            SpringApplication.run(PaymentMain8002.class, args);
        }
    }
复制代码
4.  其他业务类和payment8001一致一致。

    其他业务类controller/service/dao 直接复制。
    注意:报错的话,重新alt+enter导下包。
    
    mapper映射文件直接复制
    
    entities通过cloud-api-commons引入。
复制代码

6.2 修改 controller

1.  注意:两个生产者微服务在注册中心中的注册名是一样的
    
    这两个微服务对外暴露的都是同一个名字。
复制代码

img

2.  消费者微服务调用的是cloud-payment-service这个服务,但是在这个名字下面可能有多台机器。
    那么怎么确定消费者微服务调用哪台机器上的cloud-payment-service服务?
    
    看端口号!
    
3.  修改两个生产者微服务的controller方法

    两个生产者微服务的controller都改成这样。
复制代码
    public class PaymentController {
    
        @Resource
        private PaymentService paymentService;
    
        @Value("${server.port}") //Value绑定单一的属性值
        private String serverPort;
        
        //传给前端JSON
        @PostMapping(value = "/payment/create")    //写操作POST
        public CommonResult create(@RequestBody Payment payment){
    
            //由于在mapper.xml配置了useGeneratedKeys="true" keyProperty="id",会将自增的id封装到实体类中
            int result = paymentService.create(payment);
    
            log.info("*****插入结果:" + result);
    
            if(result > 0){
                //restful风格:对象以json串返回到页面
                return new CommonResult(200, "插入数据库成功,serverPort:"+serverPort, result);
            }else {
                return new CommonResult(444,"插入数据库失败", null);
            }
        }
        
        //传给前端JSON
        @GetMapping(value = "/payment/get/{id}")    //写操作POST
        public CommonResult getPaymentById(@PathVariable("id") Long id){
    
            Payment payment = paymentService.getPaymentById(id);
    
            log.info("*****查询结果:" + payment);
    
            if(payment != null){
                return new CommonResult(200, "查询数据库成功,serverPort:"+serverPort, payment);
            }else {
                return new CommonResult(444,"查询ID:"+id+"没有对应记录", null);
            }
        }
    }
复制代码
4.  启动测试:EurekaServer

    两个生产者微服务都注册进来了。
复制代码

img

5.  测试:生产者微服务
复制代码

img

img

6.  测试:消费者微服务
复制代码

img

    发现测试若干次不同请求,但是走的都是8001端口的生产者微服务。

7.  原因是我们在消费者微服务中将地址写死了
复制代码

img

    所以在访问消费者微服务后,消费者微服务再去调用生产者中的方法。
    调用发送的请求一直都是http://localhost:8001/...
    所以一直调用了8001端口的微服务。
    
    那么现在我们不指明具体的微服务端口,指定一个这两个生产者微服务共有的指向:
    即微服务名:CLOUD-PAYMENT-SERVICE
复制代码

img

    那么消费者再去调用生产者中的方法时,就没有指定具体的端口(具体的微服务)。那么哪一个微服务
    被调用有其他方式来决定。
    
    注意这个说法:
        这个程序的使用者会知道这些微服务的端口或者地址吗?
        消费者使用时,他们根本不想知道具体哪个微服务对应哪个端口或者具体的地址。他只关心微服务的名称。
        他们只想通过看到的微服务名,来使用这些微服务。
        也就是说,我们对外暴露的只能是微服务名,来供使用者
        
8.  再次测试:

    发现报错:
复制代码

img

    原因:
        这个微服务下面对应着多个微服务,这个微服务名下的多个微服务到底是哪个出来响应,没有办法识别。
复制代码

6.3 使用 @LoadBlanced 注解赋予 RestTemplate 负载均衡的能力

    1.  以前我们把生产者微服务写死,没关系,因为只有一个生产者微服务,只认一个。
    
    但是现在不能写死了,因为这个微服务名下对应有多个微服务,那么调用时,必须得说明
    哪一个被调用了。
    
    需要规定一种默认的负载均衡机制:@LoadBlanced
复制代码

img

    我们在这里通过@LoadBlanced赋予了RestTemplate负载均衡的能力
    
    2.  测试:
复制代码

img

        开启了默认的轮询的负载机制,8001和8002交替出现(循环交替)
        
        提前说一下这就是Ribbon的负载均衡功能默认就是轮询。
        
        即:Ribbon和Eureka整合后Consumer可以直接调用服务而不用再关心地址和端口号,
        且该服务还有负载功能了。
    
        消费者只关注生产者微服务名称,生产者微服务一定是一个集群,那就要有一个默认的
        负载均衡。
复制代码

7 actuator 微服务信息完善

7.1 主机名称:服务名称的规范和修改

img

    1.  按照规范的要求只暴露服务名,不带有主机名。
    
    2.  修改生产者微服务的yml
复制代码

img

    3.  测试:只暴露服务名
复制代码

img

    4.  actuator:监测检查
    
        1. 	显示应用的基本信息
复制代码

img

        2.  显示应用的健康状态(健康检查)
复制代码

img

7.2 访问信息有 IP 信息提示

img

    1.  我现在点击这个微服务的链接,没有ip信息提示。
    
        实际工作中,我们都会说这个微服务是部署在几号机器上面的几号端口。我们要让访问信息
        有ip信息提示。
        
    2.  在每个微服务的yml中添加如下
复制代码

img

    3.  实现
复制代码

img

8 服务发现 Discovery

    1. 我们现在已经实现了这6个微服务的调用。
复制代码

img

        不排除我们微服务自身,想对外提供功能。那么我们就要拿到在微服务中注册了的微服务的信息。
        比如:主机名称,端口号。
        
    2.  服务发现:
        
        对于注册进eureka里面的微服务,可以通过服务发现来获得这些微服务的信息。
    
    3.  修改cloud-provider-payment8001的controller:写好提供给外部的信息
复制代码

注意写在 80 和 8002 中也都可以获得所有的微服务信息,这里只是在 8001 上进行测试。

        @Resource  //发现自己的服务信息
        protected DiscoveryClient discoveryClient;
        
        //服务发现Discovery
        @GetMapping(value = "/payment/discovery")
        public Object discovery(){
            //得到服务清单列表
            List<String> services = discoveryClient.getServices();
            for (String service : services) {
                log.info("*********service: "+ service);
            }
    
            //根据微服务的具体服务名称:得到微服务实例
            List<ServiceInstance> instances = discoveryClient.getInstances("cloud-payment-service");
            for (ServiceInstance instance : instances) {
                log.info(instance.getServiceId()+"\t"+instance.getHost()+"\t"+instance.getPort()+"\t"+instance.getUri());
            }
    
            return this.discoveryClient;
        }
复制代码
        注入一个DiscoveryClient类,可以通过其中的两个方法得到我们注册了的服务的信息
            
        3.1 得到服务清单:    
            discoveryClient.getServices();
        
        3.2 根据微服务的具体服务名称:得到微服务实例
            discoveryClient.getInstances("cloud-payment-service");
            
    4.  在8001主启动类开启注解:@EnableDiscoveryClient
    
    5.  测试
        发型请求:http://localhost:8001/payment/discovery
        页面返回的是discoveryClient的json传:
复制代码

img

        控制台打印的信息:
复制代码

img

    6.  所以我们今后只要对外暴露这样的一个rest服务接口地址。
        
        调用者就可以访问这个地址获取微服务的信息。
复制代码

img

9 eureka 自我保护

9.1 自我保护

1.  概述:
    保护模式主要用于一组客户端和EurekaServer之间存在网络分区场景下的保护。一旦进入保护模式,
    EurekaServer将会尝试保护其服务注册表中的信息,不在删除服务注册表中的数据,也就是不会注销
    任何微服务。
    
    
    如果在EurekaServer的首页看到以下这段提示,则说明Eureka进入了保护模式:
复制代码

img

    一句话:某时刻某一个微服务不可用了,Eureka不会立刻清理,依旧会对该微服务的信息进行保存。
    
    属于CAP里面的AP分支。
    
    Eureka它的设计思想:
    分布式CAP里面的AP分支,某时刻某一个微服务不可用了,Eureka不会立刻清理,
    依旧会对该微服务的信息进行保存。
    
2.  为什么会产生Eureka自我保护机制

    因为可能存在这样的情况:
        EurekaClient可以正常运行,但是与EurekaServer网络不通。
    
    此时EurekaServer不会立刻将EurekaClient服务剔除。

3.  自我保护
复制代码

img

    如果一定时间内丢失大量该微服务的实例,这时Eureka就会开启自我保护机制,不会剔除该服务。
    因为这个现象可能是因为网络暂时不通,出现了Eureka的假死,拥堵,卡顿。
    稍等会客户端还能正常发送心跳。
    
    这就是CAP里面的AP分支思想。
    
4.  设计哲学

    宁可保留错误的服务注册信息,也不盲目注销任何可能健康的服务实例。
复制代码

9.2 怎么禁止自我保护

    默认是开启自我保护。
    
    禁止自我保护:只要掉线了,立马删掉该服务实例

    1.  注册中心:7001
    
        出厂默认,自我保护机制是开启的
        eureka.server.enable-self-preservation=true
        
        默认服务实例掉线9s后删掉
        eviction-interval-timer-in-ms: 9000
        
    2.  修改一下yml
    
        关闭自我保护,并且掉线2s就删除。
复制代码

img

    3.  启动7001
        
        自我保护已关闭。
复制代码

img

    4.  修改eurekaClient端8001
    
        它有两个默认的配置
        # Eureka客户端向服务端发送心跳的时间间隔默认30秒
        eureka.instance.lease-renewal-interval-in-seconds: 30       单位秒
        # Eureka服务端在收到最后一次心跳后,90s没有收到心跳,剔除服务
        eureka.instance.lease-expiration-duration-in-seconds: 90    单位秒
        
    5.  测试:
        
        8001能正常注册
复制代码

img

    6.  模拟发生故障:
            
        关闭8001
        
        如果是默认的话,由于Eureka自我保护机制,会在90s后剔除该服务。
        
        现在关闭了自我保护机制,并且在7001设置了掉线两秒就会剔除。
复制代码

img

        迅速刷新几下后:该服务被剔除了。
复制代码

img

推荐阅读