您当前的位置: 首页 >  eureka

一一哥Sun

暂无认证

  • 3浏览

    0关注

    622博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Day17_05_SpringCloud教程之Eureka实战

一一哥Sun 发布时间:2019-07-10 22:23:19 ,浏览量:3

SpringCloud之Eureka实战 一. 版本说明

本案例采用的Spring Boot版本为2.0.3.RELEASE,Spring Cloud版本为Finchley.RELEASE.

二. 创建主工程 1. 项目结构

主工程目录结构如下图所示.

我们可以先创建一个Maven项目-->MySpringCloudDemos,然后在该项目下创建一个model-->eureka01,以后还可以创建其他模块.

再然后我们在eureka01模块下再创建eureka_server01和eureka_client01两个子模块.

2. MySpringCloudDemos项目的pom.xml文件



    4.0.0
    com.syc.cloud
    MySpringCloudDemos
    pom
    1.0-SNAPSHOT

    
        eureka01
    

    
org.springframework.boot
        spring-boot-starter-parent
        
        2.0.3.RELEASE
        
    

    
        
        UTF-8
        UTF-8
        UTF-8
        1.8
        1.8
        1.8
        1.16.20

        
        Finchley.RELEASE
    

    
        
            
                org.springframework.cloud
                spring-cloud-dependencies
                ${spring-cloud.version}
                
                pom
                import
            
        
    

    
        
        
            org.springframework.boot
            spring-boot-starter-web
        

        
        
            org.projectlombok
            lombok
            ${lombok.version}
        

        
            org.springframework.boot
            spring-boot-starter-test
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    


3. eureka01的pom.xml文件



    
        MySpringCloudDemos
        com.syc.cloud
        1.0-SNAPSHOT
    

    4.0.0
    eureka01
    pom

    
        eureka_server01
        eureka_client01
    


三. 创建eureka_server01模块 1. eureka_server01的pom.xml文件

该模块的pom.xml文件继承了父pom文件,并引入spring-cloud-starter-netflix-eureka-server的依赖.



    
        eureka01
        com.syc.cloud
        1.0-SNAPSHOT
    

    4.0.0
    eureka_server01

    
        
        
            org.springframework.cloud
            spring-cloud-starter-netflix-eureka-server
        
    


2. 创建application.yml文件
server:
  port: 8761
spring:
  application:
    name: eurka-server
eureka:
  instance:
    hostname: localhost
  client:
    registerWithEureka: false
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/

Eureka是一个高可用的服务组件,每一个实例注册之后需要向注册中心发送心跳,在默认情况下erureka server也是一个eureka client,所以需要通过eureka.client.registerWithEureka: false和fetchRegistry: false来表明自己是一个Eureka Server,而不需要从Eureka Server中拉取注册的服务信息.

Eureka的默认端口就是8761,其中“defaultZone”是一个魔术字符串后备值,为任何不表示首选项的客户端提供服务URL(即defaultZone是有用的默认值).

3. 创建入口类

需要在入口类上添加一个注解@EnableEurekaServer,这个注解需要在Springboot工程的启动application类上加.

package com.syc.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

/**
 * 跟一一哥学SpringCloud微服务
 */
@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {

    public static void main(String[] args){
        SpringApplication.run(EurekaApplication.class,args);
    }
}
4. 启动Eureka Server

Eureka Server是有界面的,启动工程,打开浏览器访问:http://localhost:8761,界面如下:

四. 创建eureka-client01模块 1. 创建pom.xml文件



    
        eureka01
        com.syc.cloud
        1.0-SNAPSHOT
    
    
    4.0.0
    eureka_client01

    
        
        
            org.springframework.cloud
            spring-cloud-starter-netflix-eureka-client
        
    


2. 创建application.yml文件

在配置文件中通过serviceUrl指明自己的服务注册中心的地址.

server:
  port: 8762
spring:
  application:
    name: service-client
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

需要指明spring.application.name,这个很重要,这在以后的服务与服务之间相互调用一般都是根据这个name.

3. 创建入口类

通过注解@EnableEurekaClient表明自己是一个eureka client.

package com.syc.cloud;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * 跟一一哥学SpringCloud微服务
 */
@SpringBootApplication
@EnableEurekaClient
@RestController
public class ClientApplication {

    public static void main(String[] args) {
        SpringApplication.run(ClientApplication.class, args);
    }

    @Value("${server.port}")
    String port;

    @RequestMapping("/show")
    public String showPort(@RequestParam(value = "msg", defaultValue = "yyg") String msg) {
        return "Eureka--->" + msg + " ,This port:" + port;
    }

}
4. 启动该模块

启动eureka client服务后,该服务作为eureka server的一个实例,会向eureka server注册,注册时它会提供一些元数据,例如主机和端口,URL,主页等. Eureka Server 从每个client实例接收心跳消息,如果心跳超时,则通常将该实例从注册server中删除.

5. 访问自己定义的接口

这样就可以看到两个服务实现了正常的通信,eureka-client注册到了eureka-server中.

五. Eureka的自我保护机制 1. 现象描述

在启动我们的eureka client后,我们看到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.

其实,这个是eureka的自我保护的心跳机制导致的.

2. 自我保护机制

当Eureka Server开启了自我保护模式(默认已开启)后,Eureka Server就会统计运行期间所有客户端发来的心跳比例.如果在15分钟内超过85%的客户端节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时Eureka Server自动进入自我保护机制,会将这些实例保护起来,让这些实例不会过期. 但是在保护期内如果刚好这个服务提供者非正常下线了,此时服务消费者就会拿到一个无效的服务实例,从而导致调用失败,对于这个问题需要服务消费者端要有一些容错机制,如重试,断路器等.

默认情况下,如果Eureka Server在一定时间内(默认90秒)没有接收到某个微服务实例的心跳,Eureka Server将会移除该实例.但是当网络分区故障发生时,微服务与Eureka Server之间无法正常通信,而微服务本身是正常运行的,此时不应该移除这个微服务,所以引入了自我保护机制.

当Eureka Server自动进入自我保护机制后,此时会出现以下几种情况:

  • 1️⃣. Eureka Server不再从注册列表中移除因为长时间没收到心跳而应该过期的服务;

  • 2️⃣. Eureka Server仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上,保证当前节点依然可用;

  • 3️⃣. 当网络稳定时,当前Eureka Server新的注册信息会被同步到其它节点中.

3. 自我保护机制的重要参数

eureka默认心跳周期30s,即一分钟两次.

Renews threshold: Eureka Server 期望每分钟收到的客户端续约的总数.

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

RenewalPercentThreshold: 保护机制的触发阈值,默认0.85.

如果Renews(last min) < Renews threshold * RenewalPercentThreshold,则触发保护机制,此时就不再会剔除服务,控制台会报出红色提示错误.因为我们的实例中 2 < 0.85*3,因此报错.

4. 自我保护分析

在本案例中,我们部署了 3 个 Eureka Server(自注册模式),另外又部署 7 个客户端服务,注册到 Eureka Server 集群,参数值分别为:

  • Renews threshold: 17

  • Renews (last min): 20

下面说下Renews threshold和Renews threshold具体计算方式.

Renews threshold 计算代码:

this.expectedNumberOfRenewsPerMin = count * 2;

this.numberOfRenewsPerMinThreshold = (int) (this.expectedNumberOfRenewsPerMin * serverConfig.getRenewalPercentThreshold());

count表示服务的数量,如果 Eureka Server 开启自注册模式,也算一个服务,比如我们上面的示例,count的值就是 10 (3个自注册服务 + 7 个独立服务),serverConfig.getRenewalPercentThreshold()默认是 0.85 (可以通过eureka.server.renewal-percent-threshold配置).

所以,根据上面的分析,我们可以计算出Renews threshold的值: (int)(10 * 2 * 0.85) = (int)17 = 17.

Renews (last min)计算方式: count * 2, 数值 2 表示每 30 秒 1 个心跳,每分钟 2 个心跳的固定频率因子,所以具体值为: 10 * 2 = 20.

如果在 1 分钟后,Renews(last min) < Renews threshold,默认需等待 5 分钟(可以通过eureka.server.wait-time-in-ms-when-sync-empty配置),即 5 分钟后你会看到下面的提示信息:

5. 解决办法 5.1 解决方式有三种
  • 关闭自我保护模式:(eureka.server.enable-self-preservation设为false),不推荐;

  • 降低renewalPercentThreshold的比例:(eureka.server.renewal-percent-threshold设置为0.5以下,比如0.49),不推荐;

  • 部署多个 Eureka Server 并开启其客户端行为:(eureka.client.register-with-eureka不要设为false,默认为true),推荐.

5.2 具体实现

1️⃣. 测试环境直接关闭自我保护机制

eureka:
  server:
    enable-self-preservation: false

2️⃣. 修改配置,使触发条件不成立

比如修改心跳时间加入以下配置:

eureka:
  instance:
    lease-renewal-interval-in-seconds: 1
    lease-expiration-duration-in-seconds: 2

leaseRenewalIntervalInSeconds: Eureka客户端向服务端发送心跳的时间间隔,单位为秒,默认是30秒.

leaseExpirationDurationInSeconds: Eureka服务端在收到最后一次心跳之后等待的时间上限,单位为秒.超过该时间之后服务端会将该服务实例从服务清单中剔除,从而禁止服务调用请求被发送到该实例上,默认是90秒.

threshold=1 + 60 * 1 =61
60 > 61 * 0.85 所以不会触发自我保护机制.

或者把RenewalPercentThreshold的值调低,比如0.49

6. 注意

Eureka 的自我保护模式是有意义的,该模式被激活后,它不会从注册列表中剔除因长时间没收到心跳而导致租期过期的服务,而是等待修复,直到心跳恢复正常之后,它会自动退出自我保护模式.这种模式旨在避免因网络分区故障导致服务不可用的问题. 例如,两个客户端实例 C1 和 C2 的连通性是良好的,但是由于网络故障,C2 未能及时向 Eureka 发送心跳续约,这时候 Eureka 不能简单的将 C2 从注册表中剔除,因为如果剔除了,C1 就无法从 Eureka 服务器中获取 C2 注册的服务,但是这时候 C2 服务是可用的.

所以Eureka 的自我保护模式最好还是开启它.

 

关注
打赏
1665624836
查看更多评论
立即登录/注册

微信扫码登录

0.0409s