Netty Channel Handler 接入Sentinel实现请求拦截完成QPS流量控制,但限流规则并未生效。Netty每个请求以Channel为粒度进行处理,Sentinel只支持线程为粒度进行请求的限流吗??
private static void initFlowRule() {
    List<FlowRule> rules = new ArrayList<>();
    FlowRule rule1 = new FlowRule();
    rule1.setResource("/mercury/onOff");
    // set limit qps to 20
    rule1.setCount(20);
    rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
    rule1.setLimitApp("abc");
    rules.add(rule1);
    FlowRuleManager.loadRules(rules);
}
通过定义上诉流量控制规则,QPS最大值为20次,但是规则并没有生效
Netty Handler拦截器代码:
/** * @author pez1420@gmail.com * @version $ID: SentinelRateLimiterFilter.java v 0.1 2018/8/29 13:46 pez1420 Exp $$ */ public class SentinelRateLimiterFilter extends HttpRequestFilter { static { initFlowRule(); }
private static void initFlowRule() {
    List<FlowRule> rules = new ArrayList<>();
    FlowRule rule1 = new FlowRule();
    rule1.setResource("/mercury/onOff");
    // set limit qps to 20
    rule1.setCount(20);
    rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
    rule1.setLimitApp("abc");
    rules.add(rule1);
    FlowRuleManager.loadRules(rules);
}
@Override
public HttpResponse doFilter(HttpRequest copyRequest, NettyHttpServletRequest nettyRequest,
                             ChannelHandlerContext channelHandlerContext) {
    Channel channel = channelHandlerContext.channel();
    ApiConfigDTO apiConfigDTO = ChannelUtils.getAttribute(channel,
        HttpRequestUtils.APICONFIG_ATTRIBUTE);
    Entry entry = null;
    try {
        String target = apiConfigDTO.getFrontPath();
        ContextUtil.enter(target);
        entry = SphU.entry(target, EntryType.IN);
    } catch (DegradeException e) {
        Tracer.trace(e);
        return HttpRequestUtils
            .toJsonResponse(
                ApiResponse.error(
                    new Message(ErrorCodeEnum.DEGRADE_ERROR.getCode(),
                        ErrorCodeEnum.DEGRADE_ERROR.getMsg()),
                    ChannelUtils.getTraceId(channel)));
    } catch (BlockException e) {
        Tracer.trace(e);
        return HttpRequestUtils
            .toJsonResponse(ApiResponse.error(
                new Message(ErrorCodeEnum.RATE_LIMIT_ERROR.getCode(),
                    ErrorCodeEnum.RATE_LIMIT_ERROR.getMsg()),
                ChannelUtils.getTraceId(channel)));
    } catch (Exception e4) {
        Tracer.trace(e4);
        return HttpRequestUtils
            .toJsonResponse(ApiResponse.error(
                new Message(ErrorCodeEnum.RATE_LIMIT_ERROR.getCode(),
                    ErrorCodeEnum.RATE_LIMIT_ERROR.getMsg()),
                ChannelUtils.getTraceId(channel)));
    } finally {
        if (entry != null) {
            entry.exit();
        }
        ContextUtil.exit();
    }
    return null;
}
}
ContextUtil.enter() 创建资源上下文,从代码实现可以看出是以ThreadLocal线程变量完成上下文的统计。
*/ public class ContextUtil {
/**
 * Store the context in ThreadLocal for easy access.
 */
private static ThreadLocal<Context> contextHolder = new ThreadLocal<Context>();
/**
 * Holds all {@link EntranceNode}
 */
private static volatile Map<String, DefaultNode> contextNameNodeMap = new HashMap<String, DefaultNode>();
private static final ReentrantLock LOCK = new ReentrantLock();
private static final Context NULL_CONTEXT = new NullContext();
原提问者GitHub用户JavaPentesters
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
您的流量规则设置不正确,我认为您可能误解了FlowRule.limitApp的意思。只要将此字段设置为“默认”,您当前的测试就可以工作。
原回答者GitHub用户CarpenterLee
阿里云拥有国内全面的云原生产品技术以及大规模的云原生应用实践,通过全面容器化、核心技术互联网化、应用 Serverless 化三大范式,助力制造业企业高效上云,实现系统稳定、应用敏捷智能。拥抱云原生,让创新无处不在。