Преглед на файлове

Polish code and demo of Sentinel Zuul 2.x adapter

Signed-off-by: Eric Zhao <sczyh16@gmail.com>
master
Eric Zhao преди 4 години
родител
ревизия
0536fb6846
променени са 15 файла, в които са добавени 159 реда и са изтрити 273 реда
  1. +6
    -17
      sentinel-adapter/sentinel-zuul2-adapter/README.md
  2. +1
    -0
      sentinel-adapter/sentinel-zuul2-adapter/pom.xml
  3. +19
    -0
      sentinel-adapter/sentinel-zuul2-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul2/HttpRequestMessageItemParser.java
  4. +1
    -1
      sentinel-adapter/sentinel-zuul2-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul2/api/ZuulApiDefinitionChangeObserver.java
  5. +1
    -0
      sentinel-adapter/sentinel-zuul2-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul2/api/ZuulGatewayApiMatcherManager.java
  6. +0
    -30
      sentinel-adapter/sentinel-zuul2-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul2/callback/DefaultRequestOriginParser.java
  7. +0
    -35
      sentinel-adapter/sentinel-zuul2-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul2/callback/RequestOriginParser.java
  8. +0
    -38
      sentinel-adapter/sentinel-zuul2-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul2/callback/ZuulGatewayCallbackManager.java
  9. +4
    -5
      sentinel-adapter/sentinel-zuul2-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul2/constants/SentinelZuul2Constants.java
  10. +2
    -2
      sentinel-adapter/sentinel-zuul2-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul2/fallback/DefaultBlockFallbackProvider.java
  11. +6
    -4
      sentinel-adapter/sentinel-zuul2-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul2/filters/endpoint/SentinelZuulEndpoint.java
  12. +42
    -24
      sentinel-adapter/sentinel-zuul2-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul2/filters/inbound/SentinelZuulInboundFilter.java
  13. +9
    -21
      sentinel-adapter/sentinel-zuul2-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul2/filters/outbound/SentinelZuulOutboundFilter.java
  14. +0
    -96
      sentinel-demo/sentinel-demo-zuul2-gateway/src/main/java/com/alibaba/csp/sentinel/demo/zuul2/gateway/Bootstrap.java
  15. +68
    -0
      sentinel-demo/sentinel-demo-zuul2-gateway/src/main/java/com/alibaba/csp/sentinel/demo/zuul2/gateway/ZuulBootstrap.java

+ 6
- 17
sentinel-adapter/sentinel-zuul2-adapter/README.md Целия файл

@@ -3,11 +3,11 @@
This adapter provides **route level** and **customized API level**
flow control for Zuul 2.x API Gateway.

> *Note*: this adapter only support Zuul 2.x.
> *Note*: this adapter only supports Zuul 2.x.

## How to use

> You can refer to demo `sentinel-demo-zuul2-gateway`
> You can refer to demo [`sentinel-demo-zuul2-gateway`](https://github.com/alibaba/Sentinel/tree/master/sentinel-demo/sentinel-demo-zuul2-gateway).

1. Add Maven dependency to your `pom.xml`:

@@ -29,9 +29,9 @@ filterMultibinder.addBinding().toInstance(new SentinelZuulEndpoint());

## How it works

As Zuul 2.x is based on netty, a event-drive model, so we use `AsyncEntry` to do flow control.
As Zuul 2.x is based on Netty, an event-driven asynchronous model, so we use `AsyncEntry`.

- `SentinelZuulInboundFilter`: This inbound filter will regard all proxy ID (`proxy` in `SessionContext`) and all customized API as resources. When a `BlockException` caught, the filter will set endpoint to find a fallback to execute.
- `SentinelZuulInboundFilter`: This inbound filter will regard all routes (`routeVIP` in `SessionContext` by default) and all customized API as resources. When a `BlockException` caught, the filter will set endpoint to find a fallback to execute.
- `SentinelZuulOutboundFilter`: When the response has no exception caught, the post filter will trace the exception and complete the entries.
- `SentinelZuulEndpoint`: When an exception is caught, the filter will find a fallback to execute.

@@ -40,6 +40,8 @@ As Zuul 2.x is based on netty, a event-drive model, so we use `AsyncEntry` to do
1. Start [Sentinel Dashboard](https://github.com/alibaba/Sentinel/wiki/Dashboard).
2. You can configure the rules in Sentinel dashboard or via dynamic rule configuration.

> You may need to add `-Dcsp.sentinel.app.type=1` property to mark this application as API gateway.

## Fallbacks

You can implement `ZuulBlockFallbackProvider` to define your own fallback provider when Sentinel `BlockException` is thrown.
@@ -86,16 +88,3 @@ Default block response:
"route":"/"
}
```

## Request origin parser

You can register customized request origin parser like this:

```java
public class MyRequestOriginParser implements RequestOriginParser {
@Override
public String parseOrigin(HttpRequestMessage request) {
return request.getInboundRequest().getOriginalHost() + ":" + request.getInboundRequest().getOriginalPort();
}
}
```

+ 1
- 0
sentinel-adapter/sentinel-zuul2-adapter/pom.xml Целия файл

@@ -41,6 +41,7 @@
</exclusions>
</dependency>

<!-- The Spring library is introduced for AntMatcher -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>


+ 19
- 0
sentinel-adapter/sentinel-zuul2-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul2/HttpRequestMessageItemParser.java Целия файл

@@ -1,8 +1,27 @@
/*
* 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.zuul2;

import com.alibaba.csp.sentinel.adapter.gateway.common.param.RequestItemParser;
import com.netflix.zuul.message.http.HttpRequestMessage;

/**
* @author wavesZh
* @since 1.7.2
*/
public class HttpRequestMessageItemParser implements RequestItemParser<HttpRequestMessage> {

@Override


+ 1
- 1
sentinel-adapter/sentinel-zuul2-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul2/api/ZuulApiDefinitionChangeObserver.java Целия файл

@@ -22,7 +22,7 @@ import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinitionChangeOb

/**
* @author Eric Zhao
* @since 1.6.0
* @since 1.7.2
*/
public class ZuulApiDefinitionChangeObserver implements ApiDefinitionChangeObserver {



+ 1
- 0
sentinel-adapter/sentinel-zuul2-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul2/api/ZuulGatewayApiMatcherManager.java Целия файл

@@ -26,6 +26,7 @@ import com.alibaba.csp.sentinel.adapter.gateway.zuul2.api.matcher.HttpRequestMes

/**
* @author wavesZh
* @since 1.7.2
*/
public final class ZuulGatewayApiMatcherManager {



+ 0
- 30
sentinel-adapter/sentinel-zuul2-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul2/callback/DefaultRequestOriginParser.java Целия файл

@@ -1,30 +0,0 @@
/*
* Copyright 1999-2018 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
*
* http://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.zuul2.callback;

import com.netflix.zuul.message.http.HttpRequestMessage;

/**
* @author wavesZh
*/
public class DefaultRequestOriginParser implements RequestOriginParser {

@Override
public String parseOrigin(HttpRequestMessage request) {
return "";
}
}

+ 0
- 35
sentinel-adapter/sentinel-zuul2-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul2/callback/RequestOriginParser.java Целия файл

@@ -1,35 +0,0 @@
/*
* Copyright 1999-2018 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
*
* http://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.zuul2.callback;

import com.netflix.zuul.message.http.HttpRequestMessage;

/**
* The origin parser parses request origin (e.g. IP, user, appName) from HTTP request.
*
* @author tiger
*/
public interface RequestOriginParser {

/**
* Parse the origin from given HTTP request.
*
* @param request HTTP request
* @return parsed origin
*/
String parseOrigin(HttpRequestMessage request);
}

+ 0
- 38
sentinel-adapter/sentinel-zuul2-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul2/callback/ZuulGatewayCallbackManager.java Целия файл

@@ -1,38 +0,0 @@
/*
* 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.zuul2.callback;

import com.alibaba.csp.sentinel.util.AssertUtil;

/**
* @author Eric Zhao
* @since 1.6.0
*/
public final class ZuulGatewayCallbackManager {

private static volatile RequestOriginParser originParser = new DefaultRequestOriginParser();

public static RequestOriginParser getOriginParser() {
return originParser;
}

public static void setOriginParser(RequestOriginParser originParser) {
AssertUtil.notNull(originParser, "originParser cannot be null");
ZuulGatewayCallbackManager.originParser = originParser;
}

private ZuulGatewayCallbackManager() {}
}

sentinel-adapter/sentinel-zuul2-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul2/constants/ZuulConstant.java → sentinel-adapter/sentinel-zuul2-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul2/constants/SentinelZuul2Constants.java Целия файл

@@ -16,15 +16,14 @@

package com.alibaba.csp.sentinel.adapter.gateway.zuul2.constants;


/**
* @author wavesZh
*/
public class ZuulConstant {
public class SentinelZuul2Constants {
/**
* Zuul use Sentinel as default context when serviceId is empty.
* The default entrance (context) name when the routeId is empty.
*/
public static final String ZUUL_DEFAULT_CONTEXT = "zuul_default_context";
public static final String ZUUL_DEFAULT_CONTEXT = "zuul2_default_context";
/**
* Zuul context key for keeping Sentinel entries.
*/
@@ -36,5 +35,5 @@ public class ZuulConstant {
*/
public static final String ZUUL_CTX_SENTINEL_BLOCKED_FLAG = "_sentinel_blocked_flag";

private ZuulConstant(){}
private SentinelZuul2Constants() {}
}

+ 2
- 2
sentinel-adapter/sentinel-zuul2-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul2/fallback/DefaultBlockFallbackProvider.java Целия файл

@@ -19,7 +19,7 @@ package com.alibaba.csp.sentinel.adapter.gateway.zuul2.fallback;
import com.alibaba.csp.sentinel.slots.block.BlockException;

/**
* Default Fallback provider for sentinel {@link BlockException}, {@literal *} meant for all routes.
* Default fallback provider for Sentinel {@link BlockException}, {@literal *} meant for all routes.
*
* @author tiger
*/
@@ -33,7 +33,7 @@ public class DefaultBlockFallbackProvider implements ZuulBlockFallbackProvider {
@Override
public BlockResponse fallbackResponse(String route, Throwable cause) {
if (cause instanceof BlockException) {
return new BlockResponse(429, "Sentinel block exception", route);
return new BlockResponse(429, "SentinelBlockException", route);
} else {
return new BlockResponse(500, "System Error", route);
}


+ 6
- 4
sentinel-adapter/sentinel-zuul2-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul2/filters/endpoint/SentinelZuulEndpoint.java Целия файл

@@ -16,10 +16,11 @@

package com.alibaba.csp.sentinel.adapter.gateway.zuul2.filters.endpoint;

import com.alibaba.csp.sentinel.adapter.gateway.zuul2.constants.ZuulConstant;
import com.alibaba.csp.sentinel.adapter.gateway.zuul2.constants.SentinelZuul2Constants;
import com.alibaba.csp.sentinel.adapter.gateway.zuul2.fallback.BlockResponse;
import com.alibaba.csp.sentinel.adapter.gateway.zuul2.fallback.ZuulBlockFallbackManager;
import com.alibaba.csp.sentinel.adapter.gateway.zuul2.fallback.ZuulBlockFallbackProvider;

import com.netflix.zuul.context.SessionContext;
import com.netflix.zuul.filters.http.HttpSyncEndpoint;
import com.netflix.zuul.message.http.HttpRequestMessage;
@@ -32,13 +33,14 @@ import com.netflix.zuul.message.http.HttpResponseMessageImpl;
* @author wavesZh
*/
public class SentinelZuulEndpoint extends HttpSyncEndpoint {

@Override
public HttpResponseMessage apply(HttpRequestMessage request) {
SessionContext context = request.getContext();
Throwable throwable = context.getError();
String fallBackRoute = (String) context.get(ZuulConstant.ZUUL_CTX_SENTINEL_FALLBACK_ROUTE);
ZuulBlockFallbackProvider zuulBlockFallbackProvider = ZuulBlockFallbackManager.getFallbackProvider(
fallBackRoute);
String fallBackRoute = (String) context.get(SentinelZuul2Constants.ZUUL_CTX_SENTINEL_FALLBACK_ROUTE);
ZuulBlockFallbackProvider zuulBlockFallbackProvider = ZuulBlockFallbackManager
.getFallbackProvider(fallBackRoute);
BlockResponse response = zuulBlockFallbackProvider.fallbackResponse(fallBackRoute, throwable);
HttpResponseMessage resp = new HttpResponseMessageImpl(context, request, response.getCode());
resp.setBodyAsText(response.toString());


+ 42
- 24
sentinel-adapter/sentinel-zuul2-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul2/filters/inbound/SentinelZuulInboundFilter.java Целия файл

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.alibaba.csp.sentinel.adapter.gateway.zuul2.filters.inbound;

import java.util.ArrayDeque;
@@ -21,20 +20,22 @@ import java.util.Deque;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.function.Function;

import com.alibaba.csp.sentinel.AsyncEntry;
import com.alibaba.csp.sentinel.EntryType;
import com.alibaba.csp.sentinel.ResourceTypeConstants;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.adapter.gateway.common.param.GatewayParamParser;
import com.alibaba.csp.sentinel.adapter.gateway.zuul2.HttpRequestMessageItemParser;
import com.alibaba.csp.sentinel.adapter.gateway.zuul2.api.ZuulGatewayApiMatcherManager;
import com.alibaba.csp.sentinel.adapter.gateway.zuul2.api.matcher.HttpRequestMessageApiMatcher;
import com.alibaba.csp.sentinel.adapter.gateway.zuul2.callback.ZuulGatewayCallbackManager;
import com.alibaba.csp.sentinel.adapter.gateway.zuul2.constants.ZuulConstant;
import com.alibaba.csp.sentinel.adapter.gateway.zuul2.constants.SentinelZuul2Constants;
import com.alibaba.csp.sentinel.adapter.gateway.zuul2.filters.EntryHolder;
import com.alibaba.csp.sentinel.adapter.gateway.zuul2.filters.endpoint.SentinelZuulEndpoint;
import com.alibaba.csp.sentinel.context.ContextUtil;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.util.AssertUtil;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.netflix.zuul.context.SessionContext;
import com.netflix.zuul.filters.http.HttpInboundFilter;
@@ -45,7 +46,7 @@ import rx.schedulers.Schedulers;
import static com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants.*;

/**
* Zuul2 inboundFilter for Sentinel.
* The Zuul inbound filter wrapped with Sentinel route and customized API group entries.
*
* @author wavesZh
*/
@@ -57,31 +58,53 @@ public class SentinelZuulInboundFilter extends HttpInboundFilter {

private final String blockedEndpointName;
/**
* if executor is null, flow control action will do on I/O thread
* If the executor is null, flow control action will be performed on I/O thread
*/
private final Executor executor;
/**
* true if blocked but the rest of inbound filters will be skipped;
* false even if blocked, user can invoke other inbound filters by yourself.
* If true, the rest of inbound filters will be skipped when the request is blocked.
*/
private final boolean fastError;
private final Function<HttpRequestMessage, String> routeExtractor;

private final GatewayParamParser<HttpRequestMessage> paramParser = new GatewayParamParser<>(
new HttpRequestMessageItemParser());

/**
* Constructor of the inbound filter, which extracts the route from the context route VIP attribute by default.
*
* @param order the order of the filter
*/
public SentinelZuulInboundFilter(int order) {
this(order, null);
this(order, m -> m.getContext().getRouteVIP());
}

public SentinelZuulInboundFilter(int order, Executor executor) {
this(order, DEFAULT_BLOCK_ENDPOINT_NAME, executor, true);
}
public SentinelZuulInboundFilter(int order, Function<HttpRequestMessage, String> routeExtractor) {
this(order, null, routeExtractor);
}

public SentinelZuulInboundFilter(int order, String blockedEndpointName, Executor executor, boolean fastError) {
public SentinelZuulInboundFilter(int order, Executor executor, Function<HttpRequestMessage, String> routeExtractor) {
this(order, DEFAULT_BLOCK_ENDPOINT_NAME, executor, true, routeExtractor);
}

/**
* Constructor of the inbound filter.
*
* @param order the order of the filter
* @param blockedEndpointName the endpoint to go when the request is blocked
* @param executor the executor where Sentinel do flow checking. If null, it will be executed in current thread.
* @param fastError whether the rest of the filters will be skipped if the request is blocked
* @param routeExtractor the route ID extractor
*/
public SentinelZuulInboundFilter(int order, String blockedEndpointName, Executor executor, boolean fastError,
Function<HttpRequestMessage, String> routeExtractor) {
AssertUtil.notEmpty(blockedEndpointName, "blockedEndpointName cannot be empty");
AssertUtil.notNull(routeExtractor, "routeExtractor cannot be null");
this.order = order;
this.blockedEndpointName = blockedEndpointName;
this.executor = executor;
this.fastError = fastError;
this.routeExtractor = routeExtractor;
}

@Override
@@ -100,18 +123,17 @@ public class SentinelZuulInboundFilter extends HttpInboundFilter {

private Observable<HttpRequestMessage> apply(HttpRequestMessage request) {
SessionContext context = request.getContext();
String origin = parseOrigin(request);
Deque<EntryHolder> holders = new ArrayDeque<>();
String routeId = context.getRouteVIP();
String routeId = routeExtractor.apply(request);
String fallBackRoute = routeId;
try {
if (StringUtil.isNotBlank(routeId)) {
ContextUtil.enter(GATEWAY_CONTEXT_ROUTE_PREFIX + routeId, origin);
ContextUtil.enter(GATEWAY_CONTEXT_ROUTE_PREFIX + routeId);
doSentinelEntry(routeId, RESOURCE_MODE_ROUTE_ID, request, holders);
}
Set<String> matchingApis = pickMatchingApiDefinitions(request);
if (!matchingApis.isEmpty() && ContextUtil.getContext() == null) {
ContextUtil.enter(ZuulConstant.ZUUL_DEFAULT_CONTEXT, origin);
ContextUtil.enter(SentinelZuul2Constants.ZUUL_DEFAULT_CONTEXT);
}
for (String apiName : matchingApis) {
fallBackRoute = apiName;
@@ -119,8 +141,8 @@ public class SentinelZuulInboundFilter extends HttpInboundFilter {
}
return Observable.just(request);
} catch (BlockException t) {
context.put(ZuulConstant.ZUUL_CTX_SENTINEL_BLOCKED_FLAG, Boolean.TRUE);
context.put(ZuulConstant.ZUUL_CTX_SENTINEL_FALLBACK_ROUTE, fallBackRoute);
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);
@@ -130,7 +152,7 @@ public class SentinelZuulInboundFilter extends HttpInboundFilter {
return Observable.error(t);
} finally {
if (!holders.isEmpty()) {
context.put(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY, holders);
context.put(SentinelZuul2Constants.ZUUL_CTX_SENTINEL_ENTRIES_KEY, holders);
}
// clear context to avoid another request use incorrect context
ContextUtil.exit();
@@ -139,14 +161,10 @@ public class SentinelZuulInboundFilter extends HttpInboundFilter {

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, EntryType.IN, 1, params);
AsyncEntry entry = SphU.asyncEntry(resourceName, ResourceTypeConstants.COMMON_API_GATEWAY, EntryType.IN, params);
holders.push(new EntryHolder(entry, params));
}

private String parseOrigin(HttpRequestMessage request) {
return ZuulGatewayCallbackManager.getOriginParser().parseOrigin(request);
}

private Set<String> pickMatchingApiDefinitions(HttpRequestMessage message) {
Set<String> apis = new HashSet<>();
for (HttpRequestMessageApiMatcher matcher : ZuulGatewayApiMatcherManager.getApiMatcherMap().values()) {


+ 9
- 21
sentinel-adapter/sentinel-zuul2-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/zuul2/filters/outbound/SentinelZuulOutboundFilter.java Целия файл

@@ -17,26 +17,19 @@
package com.alibaba.csp.sentinel.adapter.gateway.zuul2.filters.outbound;

import java.util.Deque;
import java.util.List;
import java.util.stream.Collectors;

import com.alibaba.csp.sentinel.AsyncEntry;
import com.alibaba.csp.sentinel.Tracer;
import com.alibaba.csp.sentinel.adapter.gateway.zuul2.constants.ZuulConstant;
import com.alibaba.csp.sentinel.adapter.gateway.zuul2.constants.SentinelZuul2Constants;
import com.alibaba.csp.sentinel.adapter.gateway.zuul2.filters.EntryHolder;
import com.alibaba.csp.sentinel.context.ContextUtil;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.netflix.zuul.context.SessionContext;
import com.netflix.zuul.filters.FilterError;
import com.netflix.zuul.filters.http.HttpOutboundFilter;
import com.netflix.zuul.message.http.HttpResponseMessage;
import org.apache.commons.collections.CollectionUtils;
import rx.Observable;

/**
* Zuul2 outboundFilter for Sentinel.
* <p>
* The filter will complete the entries and trace the exception that happen in previous filters.
* The Zuul outbound filter which will complete the Sentinel entries and
* trace the exception that happened in previous filters.
*
* @author wavesZh
*/
@@ -61,23 +54,18 @@ public class SentinelZuulOutboundFilter extends HttpOutboundFilter {
public HttpResponseMessage apply(HttpResponseMessage response) {
SessionContext context = response.getContext();

if (context.get(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY) == null) {
if (context.get(SentinelZuul2Constants.ZUUL_CTX_SENTINEL_ENTRIES_KEY) == null) {
return response;
}
List<FilterError> errors = context.getFilterErrors().stream()
.filter(e -> BlockException.isBlockException(e.getException()))
.collect(Collectors.toList());
boolean notBlocked = true;
if (CollectionUtils.isEmpty(errors)) {
notBlocked = false;
}
Deque<EntryHolder> holders = (Deque<EntryHolder>) context.get(ZuulConstant.ZUUL_CTX_SENTINEL_ENTRIES_KEY);
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 (notBlocked) {
if (!previousBlocked) {
Tracer.traceEntry(context.getError(), holder.getEntry());
holder.getEntry().exit(1, holder.getParams());
}
holder.getEntry().exit(1, holder.getParams());
}
return response;
}


+ 0
- 96
sentinel-demo/sentinel-demo-zuul2-gateway/src/main/java/com/alibaba/csp/sentinel/demo/zuul2/gateway/Bootstrap.java Целия файл

@@ -1,96 +0,0 @@
package com.alibaba.csp.sentinel.demo.zuul2.gateway;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPathPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayParamFlowItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import com.google.inject.Injector;
import com.google.inject.Scopes;
import com.netflix.appinfo.EurekaInstanceConfig;
import com.netflix.appinfo.providers.MyDataCenterInstanceConfigProvider;
import com.netflix.config.ConfigurationManager;
import com.netflix.governator.InjectorBuilder;
import com.netflix.zuul.netty.server.BaseServerStartup;
import com.netflix.zuul.netty.server.Server;

public class Bootstrap {
public static void main(String[] args) {
new Bootstrap().start();
}

public void start() {
Server server;
try {
new GatewayRuleConfig().doInit();

ConfigurationManager.loadCascadedPropertiesFromResources("application");
Injector injector = InjectorBuilder.fromModule(new ZuulModule()).createInjector();
injector.getInstance(FiltersRegisteringService.class);
BaseServerStartup serverStartup = injector.getInstance(BaseServerStartup.class);
server = serverStartup.server();
server.start(true);
} catch (IOException e) {
e.printStackTrace();
}
}

private void initGatewayRules() {
Set<GatewayFlowRule> rules = new HashSet<>();
rules.add(new GatewayFlowRule("another_customized_api")
.setResourceMode(SentinelGatewayConstants.RESOURCE_MODE_CUSTOM_API_NAME)
.setCount(1)
.setIntervalSec(1)
.setParamItem(new GatewayParamFlowItem()
.setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_URL_PARAM)
.setFieldName("pa")
)
);
rules.add(new GatewayFlowRule("some_customized_api")
.setResourceMode(SentinelGatewayConstants.RESOURCE_MODE_CUSTOM_API_NAME)
.setCount(5)
.setIntervalSec(1)
.setParamItem(new GatewayParamFlowItem()
.setParseStrategy(SentinelGatewayConstants.PARAM_PARSE_STRATEGY_URL_PARAM)
.setFieldName("pn")
)
);
GatewayRuleManager.loadRules(rules);
}

private void initCustomizedApis() {
Set<ApiDefinition> definitions = new HashSet<>();
ApiDefinition api1 = new ApiDefinition("some_customized_api")
.setPredicateItems(new HashSet<ApiPredicateItem>() {{
add(new ApiPathPredicateItem().setPattern("/ahas"));
add(new ApiPathPredicateItem().setPattern("/aliyun/**")
.setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
}});
ApiDefinition api2 = new ApiDefinition("another_customized_api")
.setPredicateItems(new HashSet<ApiPredicateItem>() {{
add(new ApiPathPredicateItem().setPattern("/**")
.setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
}});
definitions.add(api1);
definitions.add(api2);
GatewayApiDefinitionManager.loadApiDefinitions(definitions);
}

public static class ZuulModule extends ZuulSampleModule {
@Override
protected void configure() {
//DataCenterInfo
bind(EurekaInstanceConfig.class)
.toProvider(MyDataCenterInstanceConfigProvider.class)
.in(Scopes.SINGLETON);
super.configure();
}
}
}

+ 68
- 0
sentinel-demo/sentinel-demo-zuul2-gateway/src/main/java/com/alibaba/csp/sentinel/demo/zuul2/gateway/ZuulBootstrap.java Целия файл

@@ -0,0 +1,68 @@
/*
* 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.demo.zuul2.gateway;

import java.io.IOException;

import com.google.inject.Injector;
import com.google.inject.Scopes;
import com.netflix.appinfo.EurekaInstanceConfig;
import com.netflix.appinfo.providers.MyDataCenterInstanceConfigProvider;
import com.netflix.config.ConfigurationManager;
import com.netflix.governator.InjectorBuilder;
import com.netflix.zuul.netty.server.BaseServerStartup;
import com.netflix.zuul.netty.server.Server;

/**
* <p>The Zuul 2.x demo with Sentinel gateway flow control.</p>
* <p>Run with {@code -Dcsp.sentinel.api.type=1} to mark the demo as API gateway.</p>
*
* @author wavesZh
*/
public class ZuulBootstrap {

public static void main(String[] args) {
new ZuulBootstrap().start();
}

public void start() {
Server server;
try {
// Load sample rules. You may also manage rules in Sentinel dashboard.
new GatewayRuleConfig().doInit();

ConfigurationManager.loadCascadedPropertiesFromResources("application");
Injector injector = InjectorBuilder.fromModule(new ZuulModule()).createInjector();
injector.getInstance(FiltersRegisteringService.class);
BaseServerStartup serverStartup = injector.getInstance(BaseServerStartup.class);
server = serverStartup.server();
server.start(true);
} catch (IOException e) {
e.printStackTrace();
}
}

public static class ZuulModule extends ZuulSampleModule {
@Override
protected void configure() {
//DataCenterInfo
bind(EurekaInstanceConfig.class)
.toProvider(MyDataCenterInstanceConfigProvider.class)
.in(Scopes.SINGLETON);
super.configure();
}
}
}

Loading…
Отказ
Запис