Spring Cloud Hystrix fuse (E)

Preface

Hystrix very exciting feeling, the document stresses is also very good, this summary to go where it is

Before writing Hystrix, let's talk about simple fuse, and current limiting, so after you read, you can easily understand Hystrix

Fuse

Martin Fowler's model derived fuse Circuit Breaker article. "Fuse" itself is a switching device for overload protection circuit on the circuit, when there is electrical short-circuit line, "fuse" timely cutting fault circuit against overload, fever occurs, even serious fire as a result of.

There are three state fuse design, generation after generation, ad infinitum.

  1. Closed (closed state, the normal traffic can enter)
  2. open (i.e. blown state, once an error threshold is reached, the fuse opens, reject all traffic)
  3. half-open (half-open state, the open state after a period of time automatically enters this state, newly received traffic request fails once again enters the open state, but if the number reaches a threshold successful, will enter the closed state)

Overall process shown below:

CLOSED closed state : Allow traffic .

OPEN open : do not allow traffic through , that is in a degraded state, go to downgrade logic.

HALF_OPEN half-open state : allow certain traffic through and focus on the results of these flows, if the timeout, abnormal appearance, will enter the OPEN state , if successful, will enter the CLOSED state .

In a distributed architecture, the role of the fuse pattern is similar, when a service unit fails (with similar electrical short circuit), the fault monitoring circuit breaker (similar to a blown fuse), returns an error response to the caller rather than the long wait. This does not make the thread due to a fault call service is prolonged occupation does not release, to avoid the spread of a failure in a distributed system.

Limiting

在开发高并发系统时,有很多手段保护系统,比如缓存降级限流。缓存的目的是提升系统访问速度和增大系统处理能力,可谓是抗高并发的银弹。而降级是当服务出问题或者影响到核心流程的性能,需要暂时屏蔽掉,待高峰过去或者问题解决后再打开的场景。而有些场景并不能用缓存和降级来解决,比如稀缺资源(秒杀、抢购)、写服务(如评论、下单)、频繁的复杂查询(评论的最后几页)等。因此,需要有一种手段来限制这些场景下的并发/请求量,这种手段就是限流。

限流的目的是通过对并发访问/请求进行限速或者一个时间窗口内的请求进行限速来保护系统,一旦达到限速速率则可以拒绝服务(定向到错误页或告知资源没有了)、排队或等待(比如秒杀、评论、下单)、降级(返回兜底数据或者默认数据,如商品详情页库存默认有货)。在压测时,我们能找出每个系统的处理峰值,然后通过设定峰值阈值,当系统过载时,通过拒绝过载的请求来保障系统可用。另外,也可以根据系统的吞吐量、响应时间、可用率来动态调整限流阈值。

一般开发高并发系统场景的限流有:限制总并发数(比如数据库连接池、线程池)、限制瞬时并发数(如Nginx的limit_conn模块,用来限制瞬间并发连接数)、限制时间窗口内的平均速率(如Guava的RateLimiter、Nginx的limit_req模块,用来限制每秒的平均速率),以及限制远程接口调用速率、限制MQ的消费速率等。另外还可以根据网络连接数、网络流量、CPU或内存负载等来限流。

限流算法

常见的限流算法有:令牌桶、漏桶。计数器也可以用来进行粗暴限流实现。

令牌桶算法

令牌桶算法,是一个存放固定容量令牌的桶,按照固定速率往桶里添加令牌。令牌桶算法的描述如下:

  • 假设限制2r/s,则按照500毫秒的固定速率往桶内添加令牌。
  • 桶中最多存放b个令牌,当桶满时,新添加的令牌会被丢弃或拒绝。
  • 当一个n个字节大小的数据包到达,将从桶中删除n个令牌,接着数据包被发送到网络上。
  • 如果桶中的令牌不足n个,则不会删除令牌,且该数据包被限流(要么丢弃,要么在缓冲区等待)。

漏桶算法

漏桶作为计量工具时,可以用于流量整形和流量控制,漏桶算法的描述如下:

  • 一个固定容量的漏桶,按照常量固定速率流出水滴。
  • 如果桶是空的,则不需流出水滴。
  • 可以以任意速率流入水滴到漏桶。
  • 如果流入水滴超过了桶的容量,则流入的水滴溢出了(被丢弃),而漏桶容量是不变的。

常见的限流方式有:限制总并发数(数据库连接池、线程池)、限制瞬时并发数(如Nginx的limit_conn模块)、限制时间窗口的平均速率(如Guava的RateLimiter、Nginx的limit_req模块)、限制远程接口的调用速率限制MQ的消费速率等。从应用的层面上来讲,又可以分为:接入层限流应用层限流分布式限流等。

Hystrix是什么

这一节方便阅读,我都抄下来来,具体看文档Hystrix:https://github.com/Netflix/Hystrix/wiki

在分布式环境中,许多服务依赖项中的一些不可避免地会失败。Hystrix是一个库,可通过添加延迟容错和容错逻辑来帮助您控制这些分布式服务之间的交互。Hystrix通过隔离服务之间的访问点,阻止它们之间的级联故障以及提供后备选项来实现这一目标,所有这些都可以提高系统的整体弹性。

Hystrix旨在执行以下操作:

  • 通过第三方客户端库访问(通常通过网络)依赖关系,以防止和控制延迟和故障。
  • 在复杂的分布式系统中停止级联故障。
  • 快速失败并迅速恢复。
  • 在可能的情况下,后退并优雅地降级。
  • 实现近实时监控,警报和操作控制。

复杂分布式体系结构中的应用程序有许多依赖项,每个依赖项在某些时候都不可避免地会失败。如果主机应用程序没有与这些外部故障隔离,那么它有可能被他们拖垮。

例如,对于一个依赖于30个服务的应用程序,每个服务都有99.99%的正常运行时间,你可以期望如下:

99.9930 = 99.7% 可用

也就是说一亿个请求的0.03% = 3000000 会失败

如果一切正常,那么每个月有2个小时服务是不可用的

现实通常是更糟糕 


当一切正常时,请求看起来是这样的:

当其中有一个系统有延迟时,它可能阻塞整个用户请求:

在高流量的情况下,一个后端依赖项的延迟可能导致所有服务器上的所有资源在数秒内饱和(PS:意味着后续再有请求将无法立即提供服务)

当您使用Hystrix来包装每个底层依赖项时,上图中显示的体系结构将更改为类似于下图。每个依赖项彼此隔离,在发生延迟时可以饱和的资源受到限制,并且在回退逻辑中涵盖,该逻辑决定了在依赖项中发生任何类型的故障时要做出的响应:

Feign调用使用Hystrix示例

首先,前几节的环境,都有啊,没有或需要的去看我前几篇文章吧

pom.xml

 <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>

feign调用接口

@FeignClient(name = "trade-promotion", fallback = PromotionClientFallback.class)
public interface PromotionClient {
    @RequestMapping(value = "/Promotion/delete", method = RequestMethod.GET)
    String releasePromotion(@RequestParam int orderID);
}

fallback类

@Component
public class PromotionClientFallback implements PromotionClient {
    @Override
    public String releasePromotion(@RequestParam int orderID) {
        return "hello ,fallback !";
    }
}

调用

@RestController
@RequestMapping(value = "/promotion", method = RequestMethod.GET)
public class PromotionController {
    @Autowired
    PromotionClient promotionClient;

    @RequestMapping(value = "/delete")
    public String delete(@RequestParam int orderID) {
        return promotionClient.releasePromotion(orderID);
    }
}

配置文件

#hystrix
feign.hystrix.enabled=true

好啦,可以啦.说下,就是如果远程调用接口异常,会执行Fallback返回 "hello ,fallback !";

如果你想知道为什么失败,失败的原因

@Component
public class PromotionClientFallbackFactory implements FallbackFactory<PromotionClient> {
    @Override
    public PromotionClient create(Throwable cause) {
        return new PromotionClient() {
            @Override
            public String releasePromotion(int orderID) {
                return "fallback:orderid=" + orderID + ",message:" + cause.getMessage();
            }
        };
    }
}
@FeignClient(name = "trade-promotion", fallbackFactory = PromotionClientFallbackFactory.class)
public interface PromotionClient {
    @RequestMapping(value = "/Promotion/delete", method = RequestMethod.GET)
    String releasePromotion(@RequestParam int orderID);
}

好啦,这样就ok啦.

Hystrix配置

#hystrix
feign.hystrix.enabled=true
#是否开启fallback功能,默认为true
hystrix.command.default.fallback.enabled=true
#开启hystrix请求超时机制 也可以设置成永久不超时
hystrix.command.default.execution.timeout.enabled=true
#设置调用者执行的超时时间(单位毫秒),默认:1000
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=10000
#此属性设置从调用线程允许HystrixCommand.getFallback()方法允许的最大并发请求数
#如果达到最大的并发量,则接下来的请求会被拒绝并且抛出异常.
#默认为10
hystrix.command.default.fallback.isolation.semaphore.maxConcurrentRequests = 500
#当HystrixCommand.run()使用SEMAPHORE的隔离策略时,设置最大的并发量
hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests = 1000
#是否开启断路器功能,默认为true
hystrix.command.default.circuitBreaker.enabled=true
#该属性设置滚动窗口中将使断路器跳闸的最小请求数量
#如果此属性值为20,则在窗口时间内(如10s内),如果只收到19个请求且都失败了,则断路器也不会开启。
#默认值:20
hystrix.command.default.circuitBreaker.requestVolumeThreshold=200
#断路器跳闸后,在此值的时间的内,hystrix会拒绝新的请求,只有过了这个时间断路器才会打开闸门
#默认值:5000
hystrix.command.default.circuitBreaker.sleepWindowInMilliseconds=60000
#设置失败百分比的阈值。如果失败比率超过这个值,则断路器跳闸并且进入fallback逻辑
#默认值:50 ,即50%
hystrix.command.default.circuitBreaker=50
#如果设置true,则强制使断路器进行关闭状态,此时会允许执行所有请求,无论是否失败的次数达到circuitBreaker.errorThresholdPercentage值
#默认值:false
hystrix.command.default.circuitBreaker.forceOpe=false
#如果设置true,则强制使断路器进行关闭状态,此时会允许执行所有请求,无论是否失败的次数达到circuitBreaker.errorThresholdPercentage值
#默认值:false
hystrix.command.default.circuitBreaker.forceClosed=false
#设置线程池的core size,这是最大的并发执行数量。默认10
hystrix.threadpool.default.coreSize=500
#最大队列长度。设置BlockingQueue的最大长度。默认-1。
#如果设置成-1,就会使用SynchronizeQueue。
#如果其他正整数就会使用LinkedBlockingQueue。
hystrix.threadpool.default.maxQueueSize=1000
#设置拒绝请求的临界值。只有maxQueueSize为-1时才有效。
#设置设个值的原因是maxQueueSize值运行时不能改变,我们可以通过修改这个变量动态修改允许排队的长度。默认5
hystrix.threadpool.default.queueSizeRejectionThreshold=1000
#设置统计滚动窗口的时间长度,默认值:10000
hystrix.command.default.metrics.rollingStats.timeInMilliseconds=10000
#设置统计滚动窗口的桶数量,
#注意:以下配置必须成立,否则会抛出异常。
#metrics.rollingStats.timeInMilliseconds % metrics.rollingStats.numBuckets == 0
#如:10000/10、10000/20是正确的配置,但是10000/7错误的
#在高并发的环境里,每个桶的时间长度建议大于100ms
#默认值:10
hystrix.command.default.metrics.rollingStats.numBuckets=10
#设置执行延迟是否被跟踪,并且被计算在失败百分比中。如果设置为false,则所有的统计数据返回-1
#默认值: true
hystrix.command.default.metrics.rollingPercentile.enabled=true
#此属性设置统计滚动百分比窗口的持续时间,默认值:60000
hystrix.command.default.metrics.rollingPercentile.timeInMilliseconds=60000
#设置统计滚动百分比窗口的桶数量
#注意:以下配置必须成立,否则会抛出异常。
#metrics.rollingPercentile.timeInMilliseconds % metrics.rollingPercentile.numBuckets == 0
#如: 60000/6、60000/60是正确的配置,但是10000/7错误的
#在高并发的环境里,每个桶的时间长度建议大于1000ms
#默认值:6
hystrix.command.default.metrics.rollingPercentile.numBuckets=6
#此属性设置每个桶保存的执行时间的最大值。如果桶数量是100,统计窗口为10s,如果这10s里有500次执行,只有最后100次执行会被统计到bucket里去
#默认值:100
hystrix.command.default.metrics.rollingPercentile.bucketSize=100
#采样时间间隔
hystrix.command.default.metrics.healthSnapshot.intervalInMilliseconds=500

总结

多看官放文档,推荐看下hystrix是如何工作的,很精彩.去吧,再次方便你,学不好就怪自己太忙,没时间看文档吧: https://github.com/Netflix/Hystrix/wiki

有时间再把hystrix的监控写下,今天就这啦,88

Guess you like

Origin www.cnblogs.com/knowledgesea/p/11208023.html