Fix the bug that the Zuul adapter does not exit the entry with parameters (#1148)

This commit is contained in:
tao.zhang 2019-11-08 22:27:59 +08:00 committed by Eric Zhao
parent ff5c010a51
commit 73188b46b7
3 changed files with 67 additions and 20 deletions

View File

@ -0,0 +1,41 @@
/*
* Copyright 1999-2019 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.csp.sentinel.adapter.gateway.zuul.filters;
import com.alibaba.csp.sentinel.Entry;
/**
* @author wavesZh
*/
class EntryHolder {
final private Entry entry;
final private Object[] params;
public EntryHolder(Entry entry, Object[] params) {
this.entry = entry;
this.params = params;
}
public Entry getEntry() {
return entry;
}
public Object[] getParams() {
return params;
}
}

View File

@ -17,7 +17,7 @@ package com.alibaba.csp.sentinel.adapter.gateway.zuul.filters;
import java.util.Deque; import java.util.Deque;
import com.alibaba.csp.sentinel.AsyncEntry; import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.Tracer; import com.alibaba.csp.sentinel.Tracer;
import com.alibaba.csp.sentinel.adapter.gateway.zuul.constants.ZuulConstant; import com.alibaba.csp.sentinel.adapter.gateway.zuul.constants.ZuulConstant;
import com.alibaba.csp.sentinel.context.ContextUtil; import com.alibaba.csp.sentinel.context.ContextUtil;
@ -34,11 +34,11 @@ final class SentinelEntryUtils {
static void tryExitFromCurrentContext() { static void tryExitFromCurrentContext() {
RequestContext ctx = RequestContext.getCurrentContext(); RequestContext ctx = RequestContext.getCurrentContext();
if (ctx.containsKey(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY)) { if (ctx.containsKey(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY)) {
Deque<AsyncEntry> asyncEntries = (Deque<AsyncEntry>) ctx.get(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY); Deque<EntryHolder> holders = (Deque<EntryHolder>) ctx.get(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY);
AsyncEntry entry; EntryHolder holder;
while (!asyncEntries.isEmpty()) { while (!holders.isEmpty()) {
entry = asyncEntries.pop(); holder = holders.pop();
entry.exit(); exit(holder);
} }
ctx.remove(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY); ctx.remove(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY);
} }
@ -50,17 +50,22 @@ final class SentinelEntryUtils {
static void tryTraceExceptionThenExitFromCurrentContext(Throwable t) { static void tryTraceExceptionThenExitFromCurrentContext(Throwable t) {
RequestContext ctx = RequestContext.getCurrentContext(); RequestContext ctx = RequestContext.getCurrentContext();
if (ctx.containsKey(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY)) { if (ctx.containsKey(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY)) {
Deque<AsyncEntry> asyncEntries = (Deque<AsyncEntry>) ctx.get(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY); Deque<EntryHolder> holders = (Deque<EntryHolder>) ctx.get(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY);
AsyncEntry entry; EntryHolder holder;
while (!asyncEntries.isEmpty()) { while (!holders.isEmpty()) {
entry = asyncEntries.pop(); holder = holders.pop();
Tracer.traceEntry(t, entry); Tracer.traceEntry(t, holder.getEntry());
entry.exit(); exit(holder);
} }
ctx.remove(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY); ctx.remove(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY);
} }
ContextUtil.exit(); ContextUtil.exit();
} }
static void exit(EntryHolder holder) {
Entry entry = holder.getEntry();
entry.exit(1, holder.getParams());
}
private SentinelEntryUtils() {} private SentinelEntryUtils() {}
} }

View File

@ -89,7 +89,7 @@ public class SentinelZuulPreFilter extends ZuulFilter {
} }
private void doSentinelEntry(String resourceName, final int resType, RequestContext requestContext, private void doSentinelEntry(String resourceName, final int resType, RequestContext requestContext,
Deque<AsyncEntry> asyncEntries) throws BlockException { Deque<EntryHolder> holders) throws BlockException {
Object[] params = paramParser.parseParameterFor(resourceName, requestContext, Object[] params = paramParser.parseParameterFor(resourceName, requestContext,
new Predicate<GatewayFlowRule>() { new Predicate<GatewayFlowRule>() {
@Override @Override
@ -98,8 +98,9 @@ public class SentinelZuulPreFilter extends ZuulFilter {
} }
}); });
AsyncEntry entry = SphU.asyncEntry(resourceName, ResourceTypeConstants.COMMON_API_GATEWAY, AsyncEntry entry = SphU.asyncEntry(resourceName, ResourceTypeConstants.COMMON_API_GATEWAY,
EntryType.IN, params); EntryType.IN, params);
asyncEntries.push(entry); EntryHolder holder = new EntryHolder(entry, params);
holders.push(holder);
} }
@Override @Override
@ -108,12 +109,12 @@ public class SentinelZuulPreFilter extends ZuulFilter {
String origin = parseOrigin(ctx.getRequest()); String origin = parseOrigin(ctx.getRequest());
String routeId = (String)ctx.get(ZuulConstant.PROXY_ID_KEY); String routeId = (String)ctx.get(ZuulConstant.PROXY_ID_KEY);
Deque<AsyncEntry> asyncEntries = new ArrayDeque<>(); Deque<EntryHolder> holders = new ArrayDeque<>();
String fallBackRoute = routeId; String fallBackRoute = routeId;
try { try {
if (StringUtil.isNotBlank(routeId)) { if (StringUtil.isNotBlank(routeId)) {
ContextUtil.enter(GATEWAY_CONTEXT_ROUTE_PREFIX + routeId, origin); ContextUtil.enter(GATEWAY_CONTEXT_ROUTE_PREFIX + routeId, origin);
doSentinelEntry(routeId, RESOURCE_MODE_ROUTE_ID, ctx, asyncEntries); doSentinelEntry(routeId, RESOURCE_MODE_ROUTE_ID, ctx, holders);
} }
Set<String> matchingApis = pickMatchingApiDefinitions(ctx); Set<String> matchingApis = pickMatchingApiDefinitions(ctx);
@ -122,7 +123,7 @@ public class SentinelZuulPreFilter extends ZuulFilter {
} }
for (String apiName : matchingApis) { for (String apiName : matchingApis) {
fallBackRoute = apiName; fallBackRoute = apiName;
doSentinelEntry(apiName, RESOURCE_MODE_CUSTOM_API_NAME, ctx, asyncEntries); doSentinelEntry(apiName, RESOURCE_MODE_CUSTOM_API_NAME, ctx, holders);
} }
} catch (BlockException ex) { } catch (BlockException ex) {
ZuulBlockFallbackProvider zuulBlockFallbackProvider = ZuulBlockFallbackManager.getFallbackProvider( ZuulBlockFallbackProvider zuulBlockFallbackProvider = ZuulBlockFallbackManager.getFallbackProvider(
@ -140,8 +141,8 @@ public class SentinelZuulPreFilter extends ZuulFilter {
} finally { } finally {
// We don't exit the entry here. We need to exit the entries in post filter to record Rt correctly. // We don't exit the entry here. We need to exit the entries in post filter to record Rt correctly.
// So here the entries will be carried in the request context. // So here the entries will be carried in the request context.
if (!asyncEntries.isEmpty()) { if (!holders.isEmpty()) {
ctx.put(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY, asyncEntries); ctx.put(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY, holders);
} }
} }
return null; return null;