SpringCloud之Eureka原理分析与实战(注册与发现)

Posted 老王随聊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringCloud之Eureka原理分析与实战(注册与发现)相关的知识,希望对你有一定的参考价值。

目录

1、从本质理解服务治理思想

2、为什么选择Spring Cloud服务治理组件

3、Spring Cloud Eureka服务发现

3.1 Eureka的优势

3.2 Eureka架构组成

3.3 搭建Eureka Server 实战

3.3.1 添加依赖

3.3.2 开启服务注册

3.3.3 添加YML配置

3.3.4 访问服务

3.4 搭建Eureka Client实战

3.4.1 添加依赖

3.4.2 开启服务注册

3.4.3 添加YML配置

3.4.4 访问服务

4、什么是自我保护模式

4.1 自我保护原理

4.2 自我保护触发条件

4.2.1 触发条件

4.2.2 Renews threshold

4.2.3 Renews

4.2.4 如何解决


1、从本质理解服务治理思想

我们经常听到的一个词就是“服务治理”。很多文章似乎竭力用技术层面的架构在解释什么是服务治理。很少有人能用通俗易懂的语言来阐述。今天老王试着从通俗易懂角度给大家解释一下。

那怎么理解“服务治理”呢?

首先,要理解什么是“服务”。服务源于应用,而又高于应用。什么意思呢?

从字面意思理解,服务就是一个一个应用。但与“治理”建立联系后,那就上升到了服务与服务之间的通讯,交互,监控等管理。所以,服务治理,更多的是从服务和服务之间的可能存在什么问题,而服务治理就是需要去解决这个问题。如果是以前传统单体应用,也就不存这个问题。而当下分布式系统盛行,所以,我们需要各种组件来保障分布式系统之间能保持高稳定、高可用性等。

基于这样的目的,也就有了像Eureka、Consul和Zookeeper这类中间件的出现。

2、为什么选择Spring Cloud服务治理组件

在理解了什么是“服务治理”后,接下来,我们进入今天要讲解的主角:Eureka。

首先,我们要知道为什么选择Spring Cloud的服务治理框架。

前面我们提到,当下基本90%的业务系统属于分布式部署,而分布式系统之间大多都采用RPC(Remote Procedure Call,远程过程调用)的方式通信,那在PRC调用过程中,如何解决多样化的服务注册中,来监控服务是否可用,不可用情况下该怎么办?中断业务还是通过其他方式快速恢复业务等等。 那这些问题就需要通过“服务注册与发现”组件来解决。

那在服务注册组件中,我们之所以选择Spring Cloud,主要是由于Spring Cloud为服务治理做了一层抽象接口,所以在Spring Cloud应用,中可以支持多种不同的服务治理框架。

比如:Netflix Eureka、Consul、Zookeeper。在Spring Cloud服务治理抽象层的作用下,我们可以无缝地切换服务治理实现,并且不影响任何其他的服务注册、服务发现、服务调用等逻辑。

3、Spring Cloud Eureka服务发现

Spring Cloud Eureka是Spring Cloud Netflix项目下的服务治理模块。而Spring Cloud Netflix项目是Spring Cloud的子项目之一,主要内容是对Netflix公司一系列开源产品的包装,它为Spring Boot应用提供了自配置的Netflix OSS整合。通过一些简单的注解,开发者就可以快速的在应用中配置一下常用模块并构建庞大的分布式系统。它主要提供的模块包括:服务发现(Eureka),断路器(Hystrix),智能路由(Zuul),客户端负载均衡(Ribbon)等。

那在众多服务发现组件中,我们为什么选择Eureka呢?

3.1 Eureka的优势

1)提供完整的服务注册和服务发现实现机制

首先,Eureka提供了完整的服务注册和服务发现的实现机制,并且也经受住了Netflix自己的生产环境考验,稳定性方面相对使用起来会比较放心。

2)与SpirngCloud无缝集成

我们的项目本身就使用了Spring Cloud和Spring Boot,同时Spring Cloud还有一套非常完善的开源代码来整合Eureka,所以使用起来非常方便。另外,Eureka还支持在我们应用自身的容器中启动,也就是说我们的应用启动完之后,既充当了Eureka的角色,同时也是服务的提供者。这样就极大的提高了服务的可用性。

3)CAP采用AP而非CP

这个是经典的CAP理论。

我们知道,CAP原则指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance),但是CAP 原则指示3个要素最多只能同时实现两点,不可能三者兼顾,由于网络硬件肯定会出现延迟丢包等问题,但是在分布式系统中,我们必须保证部分网络通信问题不会导致整个服务器集群瘫痪,另外即使分成了多个区,当网络故障消除的时候,我们依然可以保证数据一致性,所以我们必须保证分区容错性。

而Eureka,Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的。在部署AWS的背景下,其设计者认为,在云端,特别是大规模部署情况下面,失败是不可以避免的,可能是因为Eureka自身部署失败或者网络分区等情况导致服务不可用,这些问题是不可以避免的,要解决这个问题就需要Eureka在网络分区的时候,还能够正常提供服务,因此Eureka选择满足Availability这个特性。

在生产实践中,服务注册及发现中保留可用以及过期的数据总比丢失可用的数据好。因此,

eureka选择了A也就必须放弃C,也就是说在eureka中采用最终一致性的方式来保证数据的一致性问题,因此实例的注册信息在集群的所有节点之间的数据都不是强一性的,需要客户端能支持负载均衡算法及失败重试等机制。(这也是Eureka被病垢的主要原因,但优点多余缺点,可以通过重试等补偿机制来完善。)

综上,我们可以看到,每个注册中心组件都有其优缺点。我们在实际开发过程当中需要结合实际情况来做技术选型。

4)组件开源

代码是开源的,而且也是由Java语言开发。所以非常便于我们了解它的实现原理和排查问题。需要的话还可以在上面进行二次开发。

3.2 Eureka架构组成

Eureka主要包含Eureka Server和 Eureka Client两部分。其架构设计图如下,

其中,Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Server中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到。

而Eureka Client是一个java客户端,用于简化与Eureka Server的交互,客户端同时也就是一个内置的、使用轮询(round-robin)负载算法的负载均衡器。

在应用启动后,将会向Eureka Server发送心跳,默认周期为30秒,如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,Eureka Server将会从服务注册表中把这个服务节点移除(默认90秒)。

Eureka Server之间通过复制的方式完成数据的同步,Eureka还提供了客户端缓存机制,即使所有的Eureka Server都挂掉,客户端依然可以利用缓存中的信息消费其他服务的API。综上,Eureka通过心跳检查、客户端缓存等机制,确保了系统的高可用性、灵活性和可伸缩性。

Eureka Server 处理过程:

Eureka Server 也可以运行多个实例来构建集群,解决单点问题,但不同于 ZooKeeper 的选举 leader 的过程,Eureka Server 采用的是Peer to Peer 对等通信。这是一种去中心化的架构,无 master/slave 之分,每一个 Peer 都是对等的。

在这种架构风格中,节点通过彼此互相注册来提高可用性,每个节点需要添加一个或多个有效的 serviceUrl 指向其他节点。每个节点都可被视为其他节点的副本。

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

当一个新的 Eureka Server 节点启动后,会首先尝试从邻近节点获取所有注册列表信息,并完成初始化。Eureka Server 通过 getEurekaServiceUrls() 方法获取所有的节点,并且会通过心跳契约的方式定期更新。

默认情况下,如果 Eureka Server 在一定时间内没有接收到某个服务实例的心跳(默认周期为30秒),Eureka Server 将会注销该实例(默认为90秒, eureka.instance.lease-expiration-duration-in-seconds 进行自定义配置)。

当 Eureka Server 节点在短时间内丢失过多的心跳时,那么这个节点就会进入自我保护模式。

Eureka的集群中,只要有一台Eureka还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。除此之外,Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:

Eureka不再从注册表中移除因为长时间没有收到心跳而过期的服务;

Eureka仍然能够接受新服务注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用);

当网络稳定时,当前实例新注册的信息会被同步到其它节点中;

因此,Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使得整个注册服务瘫痪。

3.3 搭建Eureka Server 实战

说明:实战部分可以接着我们昨天讲的例子来继续编写。我这里为了在代码结构上能更加清晰,将Eureka Server和Eureka Client拆分成了两个独立的module。

如下图,

在前一篇文章中,我们其实已经讲解了Eureka Server的搭建。这里就不再赘述,。直接上配置和代码(基于springcloud-eureka-server这个module)。

3.3.1 添加依赖

在项目 springcloud-eureka-server pom.xml文件中引入需要的依赖内容:

<dependency>

    <groupId>org.springframework.cloud</groupId>

    <artifactId>spring-cloud-starter-eureka-server</artifactId>

</dependency>

3.3.2 开启服务注册

通过 @EnableEurekaServer 注解启动一个服务注册中心提供给其他应用进行对话,这个注解需要在springboot工程的启动SpringCloudEurekaServerApp类上加。代码如下,


package com.xintu.springcloud;



import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;



@SpringBootApplication

@EnableEurekaServer //表示可以将项目作为SpringCloud中的注册中心。用于激活Eureka服务器相关配置EurekaServerAutoConfiguration的注释。

public class SpringCloudEurekaServerApp 



public static void main(String[] args) 

SpringApplication.run(SpringCloudEurekaServerApp.class, args);





3.3.3 添加YML配置

在默认设置下,该服务注册中心也会将自己作为客户端来尝试注册它自己,所以我们需要禁用它的客户端注册行为,只需要在application.yml配置文件中增加如下信息:


#指定应用名称

spring:

  application:

    name: eureka-server



# 服务注册中心 (单节点)

server:

  port: 8700

eureka:

  instance:

    hostname: localhost

  client:

    fetch-registry: false # 表示是否从Eureka Server获取注册信息,默认为true.因为这是一个单点的Eureka Server,不需要同步其他的Eureka Server节点的数据,这里设置为false

    register-with-eureka: false # 表示是否将自己注册到Eureka Server,默认为true.由于当前应用就是Eureka Server,故而设置为false.

    service-url:

      # 设置与Eureka Server的地址,查询服务和注册服务都需要依赖这个地址.默认是http://localhost:8761/eureka/;多个地址可使用','风格.

      defaultZone: http://$eureka.instance.hostname:$server.port/eureka/

3.3.4 访问服务

启动工程后,访问:http://localhost:8700/。可以看到下面的页面,其中还没有发现任何服务。

至此,Eureka Serve实战案例搭建完成。

3.4 搭建Eureka Client实战

Eureka Client也称为服务提供方,将自身服务注册到 Eureka 注册中心,从而使服务消费方能够找到。

3.4.1 添加依赖

在项目 spring-cloud-eureka-provider pom.xml中引入需要的依赖内容:

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>

</dependency>

3.4.2 开启服务注册

在应用启动SpringCloudEurekaClientApp中通过加上 @EnableEurekaClient,但只有Eureka 可用,你也可以使用@EnableDiscoveryClient。需要配置才能找到Eureka注册中心服务器。


package com.xintu.springcloud;



import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.client.discovery.EnableDiscoveryClient;



@SpringBootApplication

@EnableDiscoveryClient//代表自己是一个服务提供方

public class SpringCloudEurekaClientApp 



public static void main(String[] args) 

SpringApplication.run(SpringCloudEurekaClientApp.class, args);





3.4.3 添加YML配置

需要配置才能找到Eureka服务器。配置如下,


#指定应用名称

spring:

  application:

    name: eureka-client



server:

  port: 8701 # 服务提供方



# 指定当前eureka客户端的注册地址,

eureka:

  instance:

    hostname: localhost

  client:

    service-url:

      defaultZone: http://$eureka.instance.hostname:8700/eureka

其中defaultZone是一个魔术字符串后备值,为任何不表示首选项的客户端提供服务URL(即它是有用的默认值)。 通过spring.application.name属性,我们可以指定微服务的名称后续在调用的时候只需要使用该名称就可以进行服务的访问。

3.4.4 访问服务

启动该工程后,再次访问启动工程后:http://localhost:8700/可以如下图内容,我们定义的服务被成功注册了。

至此,Eureka Serve实战案例搭建完成。

上面一行红色粗体内容引起我们的注意。

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已经不能确认这些已经启动的实例是否可用,由于最近的续订次数小于续订阈值(续订期望值),为了安全起见(实例可用),当前这些实例不会删除。

这是为什么呢?

出现上面这种情况,其实是Eureka进入自我保护模式(SELF PRESERVATION MODE)。

4、什么自我保护模式

4.1 自我保护原理

我们知道,当微服务客户端启动后,会把自身信息注册到Eureka注册中心,以供其他微服务进行调用。一般情况下,当某个服务不可用时(一段时间内没有检测到心跳或者连接超时等),那么Eureka注册中心就会将该服务从可用服务列表中剔除,但是在微服务架构中,因为服务数量众多,可能存在跨机房或者跨区域的情况,因此当某个服务心跳探测失败并不能完全说明其无法正常提供服务而将其剔除,并且服务一旦剔除后,再重新注册将会重新进行负载均衡等等一系列的操作,考虑到性能问题,eureka会将不可用的服务暂时断开,并期望能够在接下来一段时间内接收到心跳信号,而不是直接剔除,同时,新来的请求将不会分发给暂停服务的实例,这就是eureka的保护机制,它保护了因网络等问题造成的短暂的服务不可用的实例,避免频繁注册服务对整个系统造成影响。

4.2 自我保护触发条件

4.2.1 触发条件

进入自我保护模式的条件:如果最近一分钟实际接收到的心跳值Renews除以期望的心跳阈值 Renews threshold小于等于0.85,即 Renews/Renews threshold≤0.85。

我们这里 Renews/Renews = 2/3 = 0.7 ≤ 0.85,所以触发了以上自我保护提示提示。

下面我们来看下触发自我保护的具体的计算参数含义以及计算逻辑。

4.2.2 Renews threshold

Renews threshold:Eureka注册中心期望接收到的心跳值,计算方法:

服务注册中心不注册自己: (1+2*n)

服务注册中心注册自己: (1+2*(n+1)) 。

参数解析:

1) 数字1

这个是Eureka框架代码里面写时的最低阈值1,意味着没有任何客户端注册,阈值也有1。

2) 数字2

这个是最近一分钟接收到的心跳次数,Eureka客户端和注册中心心跳检测默认是30s一次,那么一分钟就是2次,可以通过下面的参数进行调整。

#定义每分钟发送到服务器的更新数 default is 30 也就是每30秒续订一次

eureka.instance.leaseRenewalIntervalInSeconds=30

3) 数字n

这个是客户端的数量个数,如果注册中心自己不注册,那么有几个客户端,n就是几,如果注册中心自己也要注册,那么就需要把注册中心也加上,这是因为在实际生产环境中,为了保证注册中心的高可用,往往注册中心会搭建集群,那么注册中心A,B,C相互之间也会注册,所以就相当于一个客户端。是否注册可以通过下面的代码进行设置。

#是否在Eureka Server中注册默认是true

eureka.client.registerWithEureka=false

4.2.3 Renews

Renews :注册中心实际接收到的心跳值,计算方法:

服务注册中心不注册自己: 2*n

服务注册中心注册自己: 2*(n+1)

参数解析:

1) 数字2

这个是最近一分钟接收到的心跳次数,Eureka客户端和注册中心心跳检测默认是30s一次,那么一分钟就是2次,可以通过下面的参数进行调整(设置代码同上)

2) 数字n

这个是客户端的数量个数,如果注册中心自己不注册,那么有几个客户端,n就是几,如果注册中心自己也要注册,那么就需要把注册中心也加上,这是因为在实际生产环境中,为了保证注册中心的高可用,往往注册中心会搭建集群,那么注册中心A,B,C相互之间也会注册,所以就相当于一个客户端。是否注册可以通过下面的代码进行设置(设置代码同上)。

3)0.85

0.85,这个参数是Eureka默认的一个比值参数,代表eureka-server最后一分钟收到的心跳次数小于等于总心跳次数的85%,可通过下面的代码进行调整

eureka.server.renewalPercentThreshold=0.85

4.2.4 如何解决

1)生成环境

在生产上可以开自注册,部署两个server 。

2)本地调试

在本机器上测试的时候,可以把比值调低,比如0.49。

eureka.server.renewalPercentThreshold=0.49

1)关闭自我保护

# 默认值是true

eureka.server.enable-self-preservation=false

说明:如果关闭自我保护模式。 在网络/其他问题的情况下,这可能无法保护实例到期,可能提供不可用的服务给客户端调用。

以上!

深入浅出SpringCloud原理及实战「Netflix系列之Hystrix」针对于限流熔断组件Hystrix的基本参数和实现原理介绍分析

[每日一句]

也许你度过了很糟糕的一天,但这并不代表你会因此度过糟糕的一生。

[温馨提示]

承接第一篇文章🏹【深入浅出SpringCloud原理及实战】「Netflix系列之Hystrix」针对于限流熔断组件Hystrix的基本参数和实现原理介绍分析

[背景介绍]

  • 分布式系统的规模和复杂度不断增加,随着而来的是对分布式系统可用性的要求越来越高。在各种高可用设计模式中,【熔断、隔离、降级、限流】是经常被使用的。而相关的技术,Hystrix本身早已算不上什么新技术,但它却是最经典的技术体系!。

  • Hystrix以实现熔断降级的设计,从而提高了系统的可用性。

  • Hystrix是一个在调用端上,实现断路器模式,以及隔舱模式,通过避免级联故障,提高系统容错能力,从而实现高可用设计的一个Java服务组件库。

  • Hystrix实现了资源隔离机制

[熔断器状态]

  • closed:closed是关闭状态,服务调用方每次请求都到服务提供方;

  • open:是open打开状态,意思是如果服务提供方的异常率或者是请求的并发量超过设置的阈值之后,就会开启熔断机制,开启熔断机制之后服务调用方所有的请求都不会在请求到服务提供方,而是直接使用本地的服务降级方法;

  • half-open:是半打开状态,服务调用方所有的请求依然会请求到服务端,hystrix也有自我恢复机制,意思是当服务提供方的熔断机制处于打开状态时,会在开启一个时间窗口,就是一定时间后或者是下一次请求的时间大于时间窗口的时间,hystrix就会重新将这次请求再次发送到服务提供方,如果成功就将状态改为half-open状态,如果失败就继续处于开启状态,并且重新刷新时间窗口的时间。

[配置介绍]

主要参考: https://github.com/Netflix/Hystrix/wiki/Configuration

上一篇文章🏹【Hystrix技术指南】(1)基本使用和配置说明主要是介绍一下相关的使用方式、以及相关的一些实战方面的配置,本篇文章会针对于配置进行具体介绍。

Hystrix属性的4中优先级

  1. 内置全局默认值(Global default from code)

如果下面3种都没有设置,默认是使用此种,后面用“默认值”代指这种。

  1. 动态全局默认属性(Dynamic global default property)

可以通过属性配置来更改全局默认值,后面用“默认属性”代指这种。

  1. 内置实例默认值(Instance default from code)

在代码中,设置的属性值,后面用“实例默认”来代指这种。

  1. 动态配置实例属性(Dynamic instance property)

可以针对特定的实例,动态配置属性值,来代替前面三种,后面用“实例属性”来代指这种。

优先级:1 < 2 < 3 < 4

hystrix.command.default和hystrix.threadpool.default中的default为默认CommandKey

[命令属性]

execution.isolation.strategy

设置HystrixCommand.run()的隔离策略,有两种选项:

  • THREAD — 固定大小线程池中,以单独线程执行,并发请求数受限于线程池大小。

  • SEMAPHORE — 在调用线程中执行,通过信号量来限制并发量。

  • 默认值:THREAD(ExecutionIsolationStrategy.THREAD)

  • 可选值:THREAD,SEMAPHORE

总结:隔离策略,默认是Thread, 可选Thread|Semaphore

默认属性:hystrix.command.default.execution.isolation.strategy

实例属性:hystrix.command.HystrixCommandKey.execution.isolation.strategy

实例默认的设置:


// to use thread isolation

HystrixCommandProperties.Setter()

.withExecutionIsolationStrategy(ExecutionIsolationStrategy.THREAD)

// to use semaphore isolation

HystrixCommandProperties.Setter()

.withExecutionIsolationStrategy(ExecutionIsolationStrategy.SEMAPHORE)

execution.isolation.thread.timeoutInMilliseconds

设置调用者等待命令执行的超时限制,超过此时间,HystrixCommand被标记为TIMEOUT,并执行回退逻辑。

注意:超时会作用在HystrixCommand.queue(),即使调用者没有调用get()去获得Future对象。

默认值:命令执行超时时间,默认1000ms

默认属性: hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds

实例属性:hystrix.command.HystrixCommandKey.execution.isolation.thread.timeoutInMilliseconds

实例默认的设置:

HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(int value)

execution.timeout.enabled

设置HystrixCommand.run()的执行是否有超时限制。

  • 默认值:执行是否启用超时,默认启用true
默认属性:hystrix.command.default.execution.timeout.enabled

实例属性:hystrix.command.HystrixCommandKey.execution.timeout.enabled

实例默认的设置:

HystrixCommandProperties.Setter().withExecutionTimeoutEnabled(boolean value)

execution.isolation.thread.interruptOnTimeout

设置HystrixCommand.run()的执行是否在超时发生时被中断。

  • 默认值:发生超时是是否中断,默认true

默认属性:hystrix.command.default.execution.isolation.thread.interruptOnTimeout

实例属性:hystrix.command.HystrixCommandKey.execution.isolation.thread.interruptOnTimeout

实例默认的设置:

HystrixCommandProperties.Setter()
.withExecutionIsolationThreadInterruptOnTimeout(boolean value)

execution.isolation.thread.interruptOnCancel

设置HystrixCommand.run()的执行但取消动作发生时候可以响应中断。

  • 默认值:false
默认属性:hystrix.command.default.execution.isolation.thread.interruptOnCancel
实例属性:hystrix.command.HystrixCommandKey.execution.isolation.thread.interruptOnCancel

实例默认的设置:

HystrixCommandProperties.Setter().withExecutionIsolationThreadInterruptOnCancel(boolean value)

execution.isolation.semaphore.maxConcurrentRequests

  • 最大并发请求数,默认10,该参数当使用ExecutionIsolationStrategy.SEMAPHORE策略时才有效。如果达到最大并发请求数,请求会被拒绝。理论上选择semaphore size的原则和选择thread size一致,但选用semaphore时每次执行的单元要比较小且执行速度快(ms级别),否则的话应该用thread。

  • 设置当使用ExecutionIsolationStrategy.SEMAPHORE时,HystrixCommand.run()方法允许的最大请求数。如果达到最大并发数时,后续请求会被拒绝。

信号量应该是容器(比如Tomcat)线程池一小部分,不能等于或者略小于容器线程池大小,否则起不到保护作用。

  • 默认值:10
默认属性:hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests

实例属性:hystrix.command.HystrixCommandKey.execution.isolation.semaphore.maxConcurrentRequests

实例默认的设置:

HystrixCommandProperties.Setter()
.withExecutionIsolationSemaphoreMaxConcurrentRequests(int value)

回退方法

下面的属性控制HystrixCommand.getFallback()执行。这些属性对ExecutionIsolationStrategy.THREAD和ExecutionIsolationStrategy.SEMAPHORE都有效。

fallback.isolation.semaphore.maxConcurrentRequests

  • 如果并发数达到该设置值,请求会被拒绝和抛出异常并且fallback不会被调用

  • 设置调用线程产生的HystrixCommand.getFallback()方法的允许最大请求数目。如果达到最大并发数目,后续请求将会被拒绝,如果没有实现回退,则抛出异常。

  • 默认值:10

默认属性:hystrix.command.default.fallback.isolation.semaphore.maxConcurrentRequests

实例属性:hystrix.command.HystrixCommandKey.fallback.isolation.semaphore.maxConcurrentRequests

实例默认:

HystrixCommandProperties.Setter()
.withFallbackIsolationSemaphoreMaxConcurrentRequests(int value)

fallback.enabled

  • 该属性决定当故障或者拒绝发生时,一个调用将会去尝试HystrixCommand.getFallback()。

  • 当执行失败或者请求被拒绝,是否会尝试调用hystrixCommand.getFallback() 。默认true

  • 默认值:true

默认属性:hystrix.command.default.fallback.enabled

实例属性:hystrix.command.HystrixCommandKey.fallback.enabled

实例默认的设置:

HystrixCommandProperties.Setter().withFallbackEnabled(boolean value)

断路器(Circuit Breaker)

circuitBreaker.enabled

设置断路器是否起作用,用来跟踪circuit的健康性,如果未达标则让request短路。默认true

  • 默认值:true
默认属性:hystrix.command.default.circuitBreaker.enabled

实例属性:hystrix.command.HystrixCommandKey.circuitBreaker.enabled

实例默认的设置:

HystrixCommandProperties.Setter().withCircuitBreakerEnabled(boolean value)

circuitBreaker.requestVolumeThreshold

设置在一个滚动窗口中,打开断路器的最少请求数。

  • 比如:如果值是20,在一个窗口内(比如10秒),收到19个请求,即使这19个请求都失败了,断路器也不会打开。

  • 一个rolling window内最小的请求数。如果设为20,那么当一个rolling window的时间内(比如说1个rolling window是10秒)收到19个请求,即使19个请求都失败,也不会触发circuit break。默认20

默认值:20


默认属性:hystrix.command.default.circuitBreaker.requestVolumeThreshold

实例属性:hystrix.command.HystrixCommandKey.circuitBreaker.requestVolumeThreshold

实例默认的设置:

HystrixCommandProperties.Setter().withCircuitBreakerRequestVolumeThreshold(int value)

circuitBreaker.sleepWindowInMilliseconds

设置在回路被打开,拒绝请求到再次尝试请求并决定回路是否继续打开的时间,触发短路的时间值,当该值设为5000时,则当触发circuit break后的5000毫秒内都会拒绝request,也就是5000毫秒后才会关闭circuit。默认5000

  • 默认值:5000(毫秒)
默认属性:hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds

实例属性:hystrix.command.HystrixCommandKey.circuitBreaker.sleepWindowInMilliseconds

实例默认的设置:

HystrixCommandProperties.Setter().withCircuitBreakerSleepWindowInMilliseconds(int value)

circuitBreaker.errorThresholdPercentage

设置打开回路并启动回退逻辑的错误比率,错误比率阀值,如果错误率>=该值,circuit会被打开,并短路所有请求触发fallback。默认50

  • 默认值:50
默认属性:hystrix.command.default.circuitBreaker.errorThresholdPercentage

实例属性:hystrix.command.HystrixCommandKey.circuitBreaker.errorThresholdPercentage

实例默认的设置:

HystrixCommandProperties.Setter().withCircuitBreakerErrorThresholdPercentage(int value)

circuitBreaker.forceOpen

如果该属性设置为true,强制断路器进入打开状态,将会拒绝所有的请求,强制打开熔断器,如果打开这个开关,那么拒绝所有request,默认false

该属性优先级比circuitBreaker.forceClosed高。

  • 默认值:false

默认属性:hystrix.command.default.circuitBreaker.forceOpen

实例属性:hystrix.command.HystrixCommandKey.circuitBreaker.forceOpen

实例默认的设置:

HystrixCommandProperties.Setter().withCircuitBreakerForceOpen(boolean value)

circuitBreaker.forceClosed

如果该属性设置为true,强制断路器进入关闭状态,将会允许所有的请求,无视错误率,强制关闭熔断器 如果这个开关打开,circuit将一直关闭且忽略circuitBreaker.errorThresholdPercentage

  • 默认值:false

默认属性:hystrix.command.default.circuitBreaker.forceClosed

实例属性:hystrix.command.HystrixCommandKey.circuitBreaker.forceClosed

实例默认的设置

HystrixCommandProperties.Setter().withCircuitBreakerForceClosed(boolean value)

请求上下文

requestCache.enabled

设置HystrixCommand.getCacheKey()是否启用,由HystrixRequestCache通过请求缓存提供去重复数据功能。

  • 默认值:true
默认属性:hystrix.command.default.requestCache.enabled

实例属性:hystrix.command.HystrixCommandKey.requestCache.enabled

实例默认的设置:

HystrixCommandProperties.Setter().withRequestCacheEnabled(boolean value)

requestLog.enabled

设置HystrixCommand执行和事件是否要记录日志到HystrixRequestLog。

默认值:true

默认属性:hystrix.command.default.requestLog.enabled

实例属性:hystrix.command.HystrixCommandKey.requestLog.enabled

实例默认的设置:

HystrixCommandProperties.Setter().withRequestLogEnabled(boolean value)

压缩器属性

下面的属性可以控制HystrixCollapser行为。

maxRequestsInBatch

设置触发批处理执行之前,在批处理中允许的最大请求数。

  • 默认值:Integer.MAX_VALUE
默认属性:hystrix.collapser.default.maxRequestsInBatch

实例属性:hystrix.collapser.HystrixCollapserKey.maxRequestsInBatch

实例默认的设置

HystrixCollapserProperties.Setter().withMaxRequestsInBatch(int value)

timerDelayInMilliseconds

设置批处理创建到执行之间的毫秒数。

  • 默认值:10
默认属性:hystrix.collapser.default.timerDelayInMilliseconds

实例属性:hystrix.collapser.HystrixCollapserKey.timerDelayInMilliseconds

实例默认的设置

HystrixCollapserProperties.Setter().withTimerDelayInMilliseconds(int value)

requestCache.enabled

设置请求缓存是否对HystrixCollapser.execute()和HystrixCollapser.queue()的调用起作用。

  • 默认值:true
默认属性:hystrix.collapser.default.requestCache.enabled

实例属性:hystrix.collapser.HystrixCollapserKey.requestCache.enabled

实例默认的设置

HystrixCollapserProperties.Setter().withRequestCacheEnabled(boolean value)

线程池属性

  • 每秒最大支撑的请求数 (99%平均响应时间 + 缓存值),比如:每秒能处理1000个请求,99%的请求响应时间是60ms,那么公式是:(0.060+0.012)

  • 基本得原则时保持线程池尽可能小,他主要是为了释放压力,防止资源被阻塞。 当一切都是正常的时候,线程池一般仅会有1到2个线程激活来提供服务

coreSize

设置核心线程池大小。

  • 默认值:10

    • 线程数默认值10适用于大部分情况(有时可以设置得更小),如果需要设置得更大,那有个基本得公式可以follow:
    • requests per second at peak when healthy × 99th percentile latency in seconds + some breathing room
默认属性:hystrix.threadpool.default.coreSize

实例属性:hystrix.threadpool.HystrixThreadPoolKey.coreSize

实例默认的设置:

HystrixThreadPoolProperties.Setter().withCoreSize(int value)

maximumSize

1.5.9新增属性,设置线程池最大值。这个是在不开始拒绝HystrixCommand的情况下支持的最大并发数。这个属性起作用的前提是设置了allowMaximumSizeToDrivergeFromCoreSize。1.5.9之前,核心线程池大小和最大线程池大小总是相同的。

maxQueueSize

设置BlockingQueue最大的队列值。

  • 如果设置为-1,那么使用SynchronousQueue,否则正数将会使用LinkedBlockingQueue。

  • 如果需要去除这些限制,允许队列动态变化,可以参考queueSizeRejectionThreshold属性。

修改SynchronousQueue和LinkedBlockingQueue需要重启。

默认值:-1

默认属性:hystrix.threadpool.default.maxQueueSize

实例属性:hystrix.threadpool.HystrixThreadPoolKey.maxQueueSize

实例默认的设置:

HystrixThreadPoolProperties.Setter().withMaxQueueSize(int value)

queueSizeRejectionThreshold

设置队列拒绝的阈值——一个人为设置的拒绝访问的最大队列值,即使maxQueueSize还没有达到。

当将一个线程放入队列等待执行时,HystrixCommand使用该属性。

注意:如果maxQueueSize设置为-1,该属性不可用。

  • 默认值:5
默认属性:hystrix.threadpool.default.queueSizeRejectionThreshold

实例属性:hystrix.threadpool.HystrixThreadPoolKey.queueSizeRejectionThreshold

实例默认的设置:

HystrixThreadPoolProperties.Setter().withQueueSizeRejectionThreshold(int value)

keepAliveTimeMinutes

设置存活时间,单位分钟。如果coreSize小于maximumSize,那么该属性控制一个线程从实用完成到被释放的时间。

  • 默认值:1
默认属性:hystrix.threadpool.default.keepAliveTimeMinutes

实例属性:hystrix.threadpool.HystrixThreadPoolKey.keepAliveTimeMinutes

实例默认的设置:

HystrixThreadPoolProperties.Setter().withKeepAliveTimeMinutes(int value)

allowMaximumSizeToDivergeFromCoreSize

在1.5.9中新增的属性。该属性允许maximumSize起作用。属性值可以等于或者大于coreSize值,设置coreSize小于maximumSize的线程池能够支持maximumSize的并发数,但是会将不活跃的线程返回到系统中去。(详见KeepAliveTimeMinutes)

默认值:false

默认属性:hystrix.threadpool.default.allowMaximumSizeToDivergeFromCoreSize

实例属性:hystrix.threadpool.HystrixThreadPoolKey.allowMaximumSizeToDivergeFromCoreSize

实例默认的设置:HystrixThreadPoolProperties.Setter()

.withAllowMaximumSizeToDivergeFromCoreSize(boolean value)

metrics.rollingStats.timeInMilliseconds

  • 设置统计的滚动窗口的时间段大小。该属性是线程池保持指标时间长短。

  • 设置统计的时间窗口值的,毫秒值,circuit break 的打开会根据1个rolling window的统计来计算。若rolling window被设为10000毫秒,则rolling window会被分成n个buckets,每个bucket包含success,failure,timeout,rejection的次数的统计信息。

默认值:10000(毫秒)

默认属性:hystrix.threadpool.default.metrics.rollingStats.timeInMilliseconds

实例属性:hystrix.threadpool.HystrixThreadPoolKey.metrics.rollingStats.timeInMilliseconds

实例默认的设置:HystrixThreadPoolProperties.Setter()

.withMetricsRollingStatisticalWindowInMilliseconds(int value)

metrics.rollingStats.numBuckets

设置滚动的统计窗口被分成的桶(bucket)的数目。

注意:”metrics.rollingStats.timeInMilliseconds % metrics.rollingStats.numBuckets == 0"必须为true,否则会抛出异常。

设置一个rolling window被划分的数量,若numBuckets=10,rolling window=10000,那么一个bucket的时间即1秒。必须符合rolling window % numberBuckets == 0。默认10

默认值:10

可能的值:任何能被metrics.rollingStats.timeInMilliseconds整除的值。

默认属性:hystrix.threadpool.default.metrics.rollingStats.numBuckets

实例属性:hystrix.threadpool.HystrixThreadPoolProperties.metrics.rollingStats.numBuckets

实例默认的设置:HystrixThreadPoolProperties.Setter()

.withMetricsRollingStatisticalWindowBuckets(int value)

其他配置属性

  • hystrix.command.default.metrics.rollingPercentile.enabled:执行时是否enable指标的计算和跟踪,默认true
  • hystrix.command.default.metrics.rollingPercentile.timeInMilliseconds:设置rolling percentile window的时间,默认60000
  • hystrix.command.default.metrics.rollingPercentile.numBuckets:设置rolling percentile window的numberBuckets。逻辑同上。默认6
  • hystrix.command.default.metrics.rollingPercentile.bucketSize:如果bucket size=100,window=10s,若这10s里有500次执行,只有最后100次执行会被统计到bucket里去。增加该值会增加内存开销以及排序的开销。默认100
  • hystrix.command.default.metrics.healthSnapshot.intervalInMilliseconds 记录health 快照(用来统计成功和错误绿)的间隔,默认500ms33 Request Context 相关参数
  • hystrix.command.default.requestCache.enabled 默认true,需要重载getCacheKey(),返回null时不缓存
  • hystrix.command.default.requestLog.enabled 记录日志到HystrixRequestLog,默认true

Collapser Properties 相关参数

  • hystrix.collapser.default.maxRequestsInBatch 单次批处理的最大请求数,达到该数量触发批处理,默认Integer.MAX_VALUE
  • hystrix.collapser.default.timerDelayInMilliseconds 触发批处理的延迟,也可以为创建批处理的时间+该值,默认10
  • hystrix.collapser.default.requestCache.enabled 是否对HystrixCollapser.execute() and HystrixCollapser.queue()的cache,默认true

以上是关于SpringCloud之Eureka原理分析与实战(注册与发现)的主要内容,如果未能解决你的问题,请参考以下文章

微服务之SpringCloud实战:SpringCloud Eureka服务治理

SpringCloud实战之初级入门— 服务注册与服务调用

微服务之SpringCloud实战:SpringCloud Eureka分区

《项目实战》springcloud 之eureka 注册中心生产者

深入浅出SpringCloud原理及实战「Netflix系列之Hystrix」针对于限流熔断组件Hystrix的请求合并机制实现原理分析

深入浅出SpringCloud原理及实战「Netflix系列之Hystrix」针对于限流熔断组件Hystrix的超时机制的原理和实现分析