带你读《2022技术人的百宝黑皮书》——一个搞定责任链的注解(6)https://developer.aliyun.com/article/1339672?groupCode=taobaotech
场景实战
下面举一个项目中真实的例子-消息分级限流。
消息发送的流量现状:
- 同一个请求可能包含有多个AppKey的消息
- 同一个请求可能包含多个消息分级的消息
- 同一个请求的消息可能经过多个接口
- 每个消息都会有对应的Appkey、消息分级
限流规则如下:
- 需要对消息所属的AppKey进行单独限流
- 仅对营销类消息进行限流,IM&实时类消息无需限流
- 如果一个消息已经被一个接口限流过,经过下一个接口时不应该被限流
- 对于同一个请求,只有整体限流和整体不限流 两种情况,不允许部分成功部分失败的情况(历史遗留问题)
面对这种的场景,该如何设计呢?
- 首先是将限流规则拆分成三个步骤:消息分级处理、去重处理、请求限流令牌处理
- 将整体限流和整体不限流抽象成合并策略,通过proxy的方式对外暴露
代码设计如下: 限流接口类
/** * 消息限流器 */ @AutoPipeline public interface MessageThrottler { /** *节流单个消息 * *@param messageThrottlerToken 消息限流令牌 *@return 是否被节流 */ boolean throttle(MessageThrottlerToken messageThrottlerToken);
14 |
|
|
15 |
|
/** |
16 |
|
* 节流多个消息。任意一个消息被节流将返回true,否则返回false |
17 |
|
* |
18 |
|
* @param messageThrottlerTokens 多个消息限流令牌 |
19 |
|
* @return 是否被节流 |
20 |
|
*/ |
21 |
|
boolean anyThrottle(List<MessageThrottlerToken> messageThrottlerTokens); |
22 |
|
|
23 |
|
/** |
24 |
|
* 节流多个消息。所有消息被节流才会返回true, 否则返回false |
25 |
|
* |
26 |
|
* @param messageThrottlerTokens 多个消息限流令牌 |
27 |
|
* @return 是否被节流 |
28 |
|
*/ |
29 |
|
boolean allThrottle(List<MessageThrottlerToken> messageThrottlerTokens); |
30 |
} |
|
将限流规则拆分成三个不同的处理类ClassificationThrottlerHandler
/** * 消息分类节流器 * * <p> * 目前仅针对营销消息进行节流7 */ public class ClassificationThrottlerHandler implements MessageThrottlerHandler { 9 @Override public boolean throttle(MessageThrottlerToken messageThrottlerToken, MessageThrottlerHandler- Context context) { if (!ClassificationConstant.MARKETING.equals(messageThrottlerToken.getClassification())) { return false; } return context.throttle(messageThrottlerToken); } @Override public boolean anyThrottle(List<MessageThrottlerToken> messageThrottlerTokens, MessageThrot- tlerHandlerContext context) { if (CollectionUtils.isEmpty(messageThrottlerTokens)) { return false; } // 获取营销消息 List<MessageThrottlerToken> marketingMessageThrottlerTokens = messageThrottlerTo- kens.stream().filter(messageThrottlerToken -> { return ClassificationConstant.MARKETING.equals(messageThrottlerToken.getClassification()); }).collect(Collectors.toList()); // 如果营销消息为空,说明消息均不需要被限流,直接返回false if (CollectionUtils.isEmpty(marketingMessageThrottlerTokens)) { return false; } return context.anyThrottle(marketingMessageThrottlerTokens); } @Override public boolean allThrottle(List<MessageThrottlerToken> messageThrottlerTokens, MessageThrot- tlerHandlerContext context) { if (CollectionUtils.isEmpty(messageThrottlerTokens)) { return false; } // 获取营销消息 List<MessageThrottlerToken> marketingMessageThrottlerTokens = messageThrottlerTo- kens.stream().filter(messageThrottlerToken -> { return ClassificationConstant.MARKETING.equals(messageThrottlerToken.getClassification()); }).collect(Collectors.toList()); // 存在非营销消息,非营销消息不会被限流 if (marketingMessageThrottlerTokens.size() < messageThrottlerTokens.size()) { return false; } return context.allThrottle(marketingMessageThrottlerTokens); } }
带你读《2022技术人的百宝黑皮书》——一个搞定责任链的注解(8)https://developer.aliyun.com/article/1339670?groupCode=taobaotech