简介
实现一个熔断器,防止视频上传的重试风暴,关注其中遇到的并发问题。
关键词:LongAdder、ConcurrentLinkedQueue、读写锁、volatile。
优雅重试
重试的风险:重试会加大直接下游的负载、重试会存在链路放大的效应。
退避策略
对于一些暂时性的错误,如网络抖动等,可能立即重试还是会失败,通常等待一小会儿再重试的话成功率会较高,并且也可能打散上游重试的时间,较少因为同时都重试而导致的下游瞬间流量高峰。
退避策略:决定等多久再重试。
- 线性退避:
Thread.sleep(200);
- 随机退避:
Thread.sleep(100L * (new Random().nextInt(3) + 1));
- 指数退避:
Thread.sleep((long) (100 * Math.pow(2, retryCount)));
防止重试风暴
首先要在单点进行限制,一个服务不能不受限制的重试下游,很容易造成下游被打挂。除了限制用户设定的重试次数上限外,更重要的是限制重试请求的成功率。
我使用一个熔断器限制单点重试,防止熔断风暴,主要组件为一个滑动窗口。
组件
Bucket
:记录了1s内请求的结果- 1s内的成功数:用
private final
修饰 - 1s内的失败数,用
private
- 1s内的成功数:用