前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >微服务架构之容错Hystrix

微服务架构之容错Hystrix

作者头像
公众号_松华说
修改2019-07-30 13:21:31
5530
修改2019-07-30 13:21:31
举报
文章被收录于专栏:松华说松华说松华说

一、容错的必要性

假设单体应用可用率为99.99%,即使拆分后每个微服务的可用率还是保持在99.99%,总体的可用率还是下降的。因为凡是依赖都可能会失败,凡是资源都是有限制的,另外网络并不可靠,有可能一个很不起眼的微服务模块高延迟最后导致整体服务不可用

二、容错的基本模块

1、主动超时,一般设置成2秒或者5秒超时时间

2、服务降级,一般会降级成直接跳转到静态CDN托底页或者提示活动太火爆,以免开天窗

3、限流,一般使用令牌机制限制最大并发数

4、隔离,对不同依赖进行隔离,容器CPU绑核就是一种隔离措施

5、弹性熔断,错误数达到一定阀值后,开始拒绝请求,健康检查发现恢复后再次接受请求

三、Hystrix主要概念

Hystrix流程

想要使用Hystrix,只需要继承HystrixCommand或者HystrixObservableCommand并重写业务逻辑方法即可,区别在于HystrixCommand.run()返回一个结果或者异常,HystrixObservableCommand.construct()返回一个Observable对象

Hystrix真正执行命令逻辑是通过execute()、queue()、observe()、toObservable()的其中一种,区别在于execute是同步阻塞的,queue通过myObservable.toList().toBlocking().toFuture()实现异步非阻塞,observe是事件注册前执行,toObservable是事件注册后执行,后两者是基于发布和订阅响应式的调用

每个熔断器默认维护10个bucket,每秒一个bucket,每个bucket记录成功,失败,超时,拒绝的状态,默认错误超过50%且10秒内超过20个请求才进行中断拦截。当断路器打开时,维护一个窗口,每过一个窗口时间,会放过一个请求以探测后端服务健康状态,如果已经恢复则断路器会恢复到关闭状态

当断路器打开、线程池提交任务被拒绝、信号量获得被拒绝、执行异常、执行超时任一情况发生都会触发降级fallBack,Hystrix提供两种fallBack方式HystrixCommand.getFallback()和HystrixObservableCommand.resumeWithFallback()

四、线程和信号量隔离

1、线程隔离,针对不同的服务依赖创建线程池

2、信号量隔离,本质是一个共享锁。当信号量中有可用的许可时,线程能获取该许可(seaphore.acquire()),否则线程必须等待,直到有可用的许可为止。线程用完必须释放(seaphore.release())否则其他线程永久等待

类型

优点

不足

适用

线程

支持排队和超时、支持异步调用

线程调用和切换产生额外开销

不受信客户(比如第三方服务稳定性是无法推测的)

信号量

轻量且无额外开销

不支持任务排队和超时,不支持异步

受信客户、高频高速调用服务(网关、cache)

五、Hystrix主要配置项

配置项(前缀hystrix.command.*.)

含义

execution.isolation.strategy

线程“THREAD”或信号量“SEMAPHORE”隔离(Default: THREAD)

execution.isolation.thread.timeoutInMilliseconds

run()方法执行超时时间(Default: 1000)

execution.isolation.semaphore.maxConcurrentRequests

信号量隔离最大并发数(Default:10)

circuitBreaker.errorThresholdPercentage

熔断的错误百分比阀值(Default:50)

circuitBreaker.requestVolumeThreshold

断路器生效必须满足的流量阀值(Default:20)

circuitBreaker.sleepWindowInMilliseconds

熔断后重置断路器的时间间隔(Default:5000)

circuitBreaker.forceOpen

设true表示强制熔断器进入打开状态(Default: false)

circuitBreaker.forceClosed

设true表示强制熔断器进入关闭状态(Default: false)

配置项(前缀hystrix.threadpool.*.)

含义

coreSize

使用线程池时的最大并发请求(Default: 10)

maxQueueSize

最大LinkedBlockingQueue大小,-1表示用SynchronousQueue(Default:-1)

default.queueSizeRejectionThreshold

队列大小阀值,超过则拒绝(Default:5)

六、使用

1、请求上下文,下面将要提到的请求缓存、请求合并都依赖请求上下文,我们可以在拦截器中进行管理

public class HystrixRequestContextServletFilter implements Filter {

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
     throws IOException, ServletException {
        HystrixRequestContext context = HystrixRequestContext.initializeContext();
        try {
            chain.doFilter(request, response);
        } finally {
            context.shutdown();
        }
    }
}

2、请求缓存,减少相同参数请求后端服务的开销,需要重写getCacheKey方法返回缓存key

public class CommandUsingRequestCache extends HystrixCommand<Boolean> {

    private final int value;

    protected CommandUsingRequestCache(int value) {
        super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
        this.value = value;
    }

    @Override
    protected Boolean run() {
        return value == 0 || value % 2 == 0;
    }

    @Override
    protected String getCacheKey() {
        return String.valueOf(value);
    }
}

3、请求合并。请求合并在Nginx静态资源加载中也很常见,Nginx使用的是nginx-http-concat扩展模块。但是在Hystric中请求合并会导致延迟增加,所以要求两者启动执行间隔时长足够小,减少等待合并的时间,超过10ms间隔不会自动合并

public class CommandCollapserGetValueForKey extends HystrixCollapser<List<String>, String, Integer> {
    private final Integer key;

    public CommandCollapserGetValueForKey(Integer key) {
        this.key = key;
    }

    @Override
    public Integer getRequestArgument() {
        return key;
    }

    @Override
    protected HystrixCommand<List<String>> createCommand(final Collection<CollapsedRequest<String, Integer>> requests) {
        return new BatchCommand(requests);
    }

    @Override
    protected void mapResponseToRequests(List<String> batchResponse, Collection<CollapsedRequest<String, Integer>> requests) {
        int count = 0;
        for (CollapsedRequest<String, Integer> request : requests) {
            request.setResponse(batchResponse.get(count++));
        }
    }

    private static final class BatchCommand extends HystrixCommand<List<String>> {
        private final Collection<CollapsedRequest<String, Integer>> requests;

        private BatchCommand(Collection<CollapsedRequest<String, Integer>> requests) {
                super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"))
                    .andCommandKey(HystrixCommandKey.Factory.asKey("GetValueForKey")));
            this.requests = requests;
        }

        @Override
        protected List<String> run() {
            ArrayList<String> response = new ArrayList<String>();
            for (CollapsedRequest<String, Integer> request : requests) {
                // artificial response for each argument received in the batch
                response.add("ValueForKey: " + request.getArgument());
            }
            return response;
        }
    }
}

4、快速失败,不走降级逻辑,直接抛出异常,通常用于非幂等性的写操作。幂等性是指一次和多次请求某一个资源应该具有同样的副作用,比如bool take(ticket_id, account_id, amount)取钱操作,不管任何时候请求失败或超时,调用方都可以重试,当然把参数ticket_id去掉就是非幂等性的了。注意:在Hystrix可以轻松实现重试,只需降级时判断isCircuitBreakerOpen断路器状态可用然后重试即可,不会使问题雪上加霜

public class CommandThatFailsFast extends HystrixCommand<String> {

private final boolean throwException;

public CommandThatFailsFast(boolean throwException) {
    super(HystrixCommandGroupKey.Factory.asKey("ExampleGroup"));
    this.throwException = throwException;
}

@Override
protected String run() {
    if (throwException) {
        throw new RuntimeException("failure from CommandThatFailsFast");
    } else {
        return "success";
    }
}

作者BLOG:www.liangsonghua.me 作者介绍:京东资深工程师-梁松华,在稳定性保障、敏捷开发、JAVA高级、微服务架构方面有深入的理解

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-04-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 松华说 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、容错的必要性
  • 二、容错的基本模块
  • 三、Hystrix主要概念
  • 四、线程和信号量隔离
  • 1、线程隔离,针对不同的服务依赖创建线程池
  • 五、Hystrix主要配置项
  • 六、使用
相关产品与服务
内容分发网络 CDN
内容分发网络(Content Delivery Network,CDN)通过将站点内容发布至遍布全球的海量加速节点,使其用户可就近获取所需内容,避免因网络拥堵、跨运营商、跨地域、跨境等因素带来的网络不稳定、访问延迟高等问题,有效提升下载速度、降低响应时间,提供流畅的用户体验。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档