sentinel源码分析第六篇一sentinel-adapter模块一第四章zuul2网关

SentinelZuulInboundFilter

  • 路由提取器提取资源信息进行限流
  • 根据api等信息进行限流
  • 发生限流则返回
  • 构建ZUUL_CTX_SENTINEL_ENTRIES_KEY信息交由OutBound完成sentinel工作现场清理
public class SentinelZuulInboundFilter extends HttpInboundFilter {

    @Override
    public Observable<HttpRequestMessage> applyAsync(HttpRequestMessage request) {
        限流执行入口
        if (executor != null) {
            return Observable.just(request).subscribeOn(Schedulers.from(executor)).flatMap(this::apply);
        } else {
            return Observable.just(request).flatMap(this::apply);
        }
    }

    应用sentinel限流逻辑
    private Observable<HttpRequestMessage> apply(HttpRequestMessage request) {
        SessionContext context = request.getContext();
        Deque<EntryHolder> holders = new ArrayDeque<>();
        String routeId = routeExtractor.apply(request);
        String fallBackRoute = routeId;
        try {
            提起路由id
            if (StringUtil.isNotBlank(routeId)) {
                构建context
                ContextUtil.enter(GATEWAY_CONTEXT_ROUTE_PREFIX + routeId);
                执行限流逻辑
                doSentinelEntry(routeId, RESOURCE_MODE_ROUTE_ID, request, holders);
            }
            提取匹配的api信息
            Set<String> matchingApis = pickMatchingApiDefinitions(request);
            if (!matchingApis.isEmpty() && ContextUtil.getContext() == null) {
                ContextUtil.enter(SentinelZuul2Constants.ZUUL_DEFAULT_CONTEXT);
            }
            限流拦截
            for (String apiName : matchingApis) {
                fallBackRoute = apiName;
                doSentinelEntry(apiName, RESOURCE_MODE_CUSTOM_API_NAME, request, holders);
            }
            return Observable.just(request);
        } catch (BlockException t) {
            发生限流
            context.put(SentinelZuul2Constants.ZUUL_CTX_SENTINEL_BLOCKED_FLAG, Boolean.TRUE);
            context.put(SentinelZuul2Constants.ZUUL_CTX_SENTINEL_FALLBACK_ROUTE, fallBackRoute);
            if (fastError) {
                context.setShouldSendErrorResponse(true);
                context.setErrorEndpoint(blockedEndpointName);
            } else {
                context.setEndpoint(blockedEndpointName);
            }
            return Observable.error(t);
        } finally {
            交给出栈过滤器如何清空entry
            if (!holders.isEmpty()) {
                context.put(SentinelZuul2Constants.ZUUL_CTX_SENTINEL_ENTRIES_KEY, holders);
            }
            ContextUtil.exit();
        }
    }

    执行限流逻辑
    private void doSentinelEntry(String resourceName, final int resType, HttpRequestMessage input, Deque<EntryHolder> holders) throws BlockException {
        Object[] params = paramParser.parseParameterFor(resourceName, input, r -> r.getResourceMode() == resType);
        AsyncEntry entry = SphU.asyncEntry(resourceName, ResourceTypeConstants.COMMON_API_GATEWAY, EntryType.IN, params);
        holders.push(new EntryHolder(entry, params));
    }
}

SentinelZuulOutboundFilter

  • 通过Outbound完成资源清理
public class SentinelZuulOutboundFilter extends HttpOutboundFilter {

    @Override
    public Observable<HttpResponseMessage> applyAsync(HttpResponseMessage input) {
        return Observable.just(apply(input));
    }

    public HttpResponseMessage apply(HttpResponseMessage response) {
        SessionContext context = response.getContext();
        不存在entry则直接响应
        if (context.get(SentinelZuul2Constants.ZUUL_CTX_SENTINEL_ENTRIES_KEY) == null) {
            return response;
        }
        存在entry则通过exit清理entry
        boolean previousBlocked = context.getFilterErrors().stream()
            .anyMatch(e -> BlockException.isBlockException(e.getException()));
        Deque<EntryHolder> holders = (Deque<EntryHolder>) context.get(SentinelZuul2Constants.ZUUL_CTX_SENTINEL_ENTRIES_KEY);
        while (!holders.isEmpty()) {
            EntryHolder holder = holders.pop();
            if (!previousBlocked) {
                Tracer.traceEntry(context.getError(), holder.getEntry());
                holder.getEntry().exit(1, holder.getParams());
            }
        }
        return response;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值