SpringCloud Alibaba micro-service real twelve - Gateway limiting

REVIEW: by the previous chapters we do in the service layer micro current limiting and integrated SpringCloud Gateway, the main content of this chapter is to move from micro-limiting function to the gateway service layer.

SpringCloud Gateway primeval fault current limiter

Springcloud Gateway native mainly based on limiting filter implementation, we can directly use the built-in filters RequestRateLimiterGatewayFilterFactory, the current RequestRateLimiterGatewayFilterFactoryimplementation relies on Redis, so we have introduced spring-boot-starter-data-redis-reactive.

POM dependence

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifatId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
复制代码

Limiting configuration

spring:
  cloud:
    gateway:
      routes:
      - id: account-service
        uri: lb://account-service
        order: 10000
        predicates:
        - Path=/account-service/**
        filters:
        - name: RequestRateLimiter
          args:
            redis-rate-limiter.replenishRate: 1
            redis-rate-limiter.burstCapacity: 3
            key-resolver: "#{@ipKeyResolver}" 
复制代码

The main is to configure the three main parameters:

  • redis-rate-limiter.replenishRate:
    how many requests per second allows the user
  • redis-rate-limiter.burstCapacity:
    token bucket capacity, the maximum number of requests is completed in one second
  • key-resolver:
    for the name of Bean object parser keys of limiting. It acquires the SpEL expression Bean Spring objects from a container according to # {@ beanName}.

Configuration Bean

/**
* 自定义限流标志的key,多个维度可以从这里入手
* exchange对象中获取服务ID、请求信息,用户信息等
*/
@Bean
KeyResolver ipKeyResolver() {
    return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
}
复制代码

Sentinel limiting

Previous chapter we have talked about Sentinel to use, if there are any questions you can look at the previous section, here mainly talk about the integration with SpringCloud gateway.

Sentinel from version 1.6.0 began offering a Spring Cloud Gateway adapter module, two resources can provide current limiting dimensions:

  • Dimensions route: i.e., disposed in the Spring routing entry in the configuration file, the resource name corresponding custom routeId
  • API dimensions: the user can use the Sentinel API provided from the API to define some packets

Here is our integration steps

POM dependence

<dependency>
	<groupId>com.alibaba.cloud</groupId>
	<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>

<dependency>
	<groupId>com.alibaba.cloud</groupId>
	<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

<dependency>
	<groupId>com.alibaba.csp</groupId>
	<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
复制代码

Since the need to use as a distribution center nacos sentinel, it also introducessentinel-datasource-nacos

Bootstrap Configuration

...
spring:
  cloud:
    sentinel:
      transport:
        dashboard: 10.0.10.48:8858
      eager: true
      datasource:
        ds:
          nacos:
            server-addr: 10.0.10.48:8848
            data-id: gateway-sentinel-flow
            group-id: DEFAULT_GROUP
            rule-type: gw-flow
...
复制代码

Here is the sentinel of the main configuration, the center acquired from nacos configuration gateway-sentinel-flowprofiles, current limiting type is the type of gateway gw-flow.

Limiting configuration

Configuration management based on nacos public page data-idfor the gateway-sentinel-flowconfiguration file (json format), to account-servicethe product-serviceadded limiting rules.

[
  {
    "resource": "account-service",
    "count": 5,
    "grade": 1,
    "paramItem": {
        "parseStrategy": 0
    }
  },
  {
    "resource": "product-service",
    "count": 2,
    "grade": 1,
    "paramItem": {
        "parseStrategy": 0
    }
  }
]
复制代码

After configuration is complete Start Gateway project, log on sentinel console to view current limiting rules:

image.png

Configuration instructions:

以客户端IP作为限流因子
public static final int PARAM_PARSE_STRATEGY_CLIENT_IP = 0;
以客户端HOST作为限流因子
public static final int PARAM_PARSE_STRATEGY_HOST = 1;
以客户端HEADER参数作为限流因子
public static final int PARAM_PARSE_STRATEGY_HEADER = 2;
以客户端请求参数作为限流因子
public static final int PARAM_PARSE_STRATEGY_URL_PARAM = 3;
以客户端请求Cookie作为限流因子
public static final int PARAM_PARSE_STRATEGY_COOKIE = 4;
复制代码

Limiting test

Gateway access by multiple account-servicetesting service http://localhost:8090/account/getByCode/javadailyto view current-limiting effect:

Custom abnormal response

SpringCloud-gateway limiting abnormal default logic implemented SentinelGatewayBlockExceptionHandler, abnormal response can view the source code is as follows key

Due to the back-end services are returned JSON response format, so we need to modify the original exception response, edit it into ResultDatathe response format class. To achieve this function only need to write a new exception handler then inject new exception handler can be configured in SpringCloud GateWay class.

  • Custom exception handlerCustomGatewayBlockExceptionHandler
public class CustomGatewayBlockExceptionHandler implements WebExceptionHandler {
	...
    /**
     * 重写限流响应,改造成JSON格式的响应数据
     * @author javadaily
     * @date 2020/1/20 15:03
     */
    private Mono<Void> writeResponse(ServerResponse response, ServerWebExchange exchange) {
        ServerHttpResponse serverHttpResponse = exchange.getResponse();
        serverHttpResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        ResultData<Object> resultData = ResultData.fail(ReturnCode.RC200.getCode(), ReturnCode.RC200.getMessage());
        String resultString = JSON.toJSONString(resultData);
        DataBuffer buffer = serverHttpResponse.bufferFactory().wrap(resultString.getBytes());
        return serverHttpResponse.writeWith(Mono.just(buffer));
    }

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        if (exchange.getResponse().isCommitted()) {
            return Mono.error(ex);
        } else {
            return !BlockException.isBlockException(ex) ? Mono.error(ex) : this.handleBlockedRequest(exchange, ex).flatMap((response) -> this.writeResponse(response, exchange));
        }
    }
   ...
}
复制代码

You can directly copy SentinelGatewayBlockExceptionHandlerthe class, and then modify the writeResponsemethod Interface

  • Gateway modified configuration class, injectionCustomGatewayBlockExceptionHandler
@Configuration
public class GatewayConfiguration {
	...
    /**
     * 注入自定义网关异常
     */
    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public CustomGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
        // Register the custom block exception handler .
        return new CustomGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
    }
	...
}
复制代码
  • New configuration file in bootstrap.yml
spring:
  main:
    allow-bean-definition-overriding: true
复制代码
  • Retest limiting response following results
{
	"message": "服务开启限流保护,请稍后再试!",
	"status": 200,
	"success": false,
	"timestamp": 1579509123946
}
复制代码

Limiting does not take effect

If you find that in the course of the current limiting layer gateway does not take effect, you can start the gateway service in debug mode, and then gateway filters SentinelGatewayFilterfilter method of debugging, I found that sentinel get to the gateway id is not our arrangement account-service, but added CompositeDiscoveryClient_the prefix, as shown below:

So we need to modify gateway-sentinel-flowthe configuration to our resource also add a prefix, you modify the configuration is as follows:

[{
	"resource": "CompositeDiscoveryClient_account-service",
	"count": 5,
	"grade": 1,
	"paramItem": {
		"parseStrategy": 0
	}
}, {
	"resource": "CompositeDiscoveryClient_product-service",
	"count": 2,
	"grade": 1,
	"paramItem": {
		"parseStrategy": 0
	}
}]
复制代码

To test the interface by using jemter, the gateway can find the normal current limit

After the above steps, we will be limiting the back-end micro-services layer configuration removed, so that the gateway layer assumes the function of current limiting.

Well, ladies and friends, the contents of this issue on all over it, to see the students here are excellent students, under a promotion and pay rise is you! If you find this article to help you, then please scan the following QR code to add a concern.

"Forward" plus "look", to form good habits! Let's See you next time!

SpringCloud Alibaba series

Guess you like

Origin juejin.im/post/5e5daa0d518825490b6487da