@@ -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; | |||
} | |||
} |
@@ -17,7 +17,7 @@ package com.alibaba.csp.sentinel.adapter.gateway.zuul.filters; | |||
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.adapter.gateway.zuul.constants.ZuulConstant; | |||
import com.alibaba.csp.sentinel.context.ContextUtil; | |||
@@ -34,11 +34,11 @@ final class SentinelEntryUtils { | |||
static void tryExitFromCurrentContext() { | |||
RequestContext ctx = RequestContext.getCurrentContext(); | |||
if (ctx.containsKey(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY)) { | |||
Deque<AsyncEntry> asyncEntries = (Deque<AsyncEntry>) ctx.get(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY); | |||
AsyncEntry entry; | |||
while (!asyncEntries.isEmpty()) { | |||
entry = asyncEntries.pop(); | |||
entry.exit(); | |||
Deque<EntryHolder> holders = (Deque<EntryHolder>) ctx.get(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY); | |||
EntryHolder holder; | |||
while (!holders.isEmpty()) { | |||
holder = holders.pop(); | |||
exit(holder); | |||
} | |||
ctx.remove(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY); | |||
} | |||
@@ -50,17 +50,22 @@ final class SentinelEntryUtils { | |||
static void tryTraceExceptionThenExitFromCurrentContext(Throwable t) { | |||
RequestContext ctx = RequestContext.getCurrentContext(); | |||
if (ctx.containsKey(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY)) { | |||
Deque<AsyncEntry> asyncEntries = (Deque<AsyncEntry>) ctx.get(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY); | |||
AsyncEntry entry; | |||
while (!asyncEntries.isEmpty()) { | |||
entry = asyncEntries.pop(); | |||
Tracer.traceEntry(t, entry); | |||
entry.exit(); | |||
Deque<EntryHolder> holders = (Deque<EntryHolder>) ctx.get(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY); | |||
EntryHolder holder; | |||
while (!holders.isEmpty()) { | |||
holder = holders.pop(); | |||
Tracer.traceEntry(t, holder.getEntry()); | |||
exit(holder); | |||
} | |||
ctx.remove(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY); | |||
} | |||
ContextUtil.exit(); | |||
} | |||
static void exit(EntryHolder holder) { | |||
Entry entry = holder.getEntry(); | |||
entry.exit(1, holder.getParams()); | |||
} | |||
private SentinelEntryUtils() {} | |||
} |
@@ -89,7 +89,7 @@ public class SentinelZuulPreFilter extends ZuulFilter { | |||
} | |||
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, | |||
new Predicate<GatewayFlowRule>() { | |||
@Override | |||
@@ -98,8 +98,9 @@ public class SentinelZuulPreFilter extends ZuulFilter { | |||
} | |||
}); | |||
AsyncEntry entry = SphU.asyncEntry(resourceName, ResourceTypeConstants.COMMON_API_GATEWAY, | |||
EntryType.IN, params); | |||
asyncEntries.push(entry); | |||
EntryType.IN, params); | |||
EntryHolder holder = new EntryHolder(entry, params); | |||
holders.push(holder); | |||
} | |||
@Override | |||
@@ -108,12 +109,12 @@ public class SentinelZuulPreFilter extends ZuulFilter { | |||
String origin = parseOrigin(ctx.getRequest()); | |||
String routeId = (String)ctx.get(ZuulConstant.PROXY_ID_KEY); | |||
Deque<AsyncEntry> asyncEntries = new ArrayDeque<>(); | |||
Deque<EntryHolder> holders = new ArrayDeque<>(); | |||
String fallBackRoute = routeId; | |||
try { | |||
if (StringUtil.isNotBlank(routeId)) { | |||
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); | |||
@@ -122,7 +123,7 @@ public class SentinelZuulPreFilter extends ZuulFilter { | |||
} | |||
for (String apiName : matchingApis) { | |||
fallBackRoute = apiName; | |||
doSentinelEntry(apiName, RESOURCE_MODE_CUSTOM_API_NAME, ctx, asyncEntries); | |||
doSentinelEntry(apiName, RESOURCE_MODE_CUSTOM_API_NAME, ctx, holders); | |||
} | |||
} catch (BlockException ex) { | |||
ZuulBlockFallbackProvider zuulBlockFallbackProvider = ZuulBlockFallbackManager.getFallbackProvider( | |||
@@ -140,8 +141,8 @@ public class SentinelZuulPreFilter extends ZuulFilter { | |||
} finally { | |||
// 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. | |||
if (!asyncEntries.isEmpty()) { | |||
ctx.put(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY, asyncEntries); | |||
if (!holders.isEmpty()) { | |||
ctx.put(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY, holders); | |||
} | |||
} | |||
return null; | |||