This is the 20th day of my participation in the August Text Challenge.More challenges in August

The routing configuration

There are three ways to configure urIs in the Spring Cloud Gateway, including

  • Websocket configuration mode
spring:
  cloud:
    gateway:
      routes:
        - id: demo-api
          uri: ws://localhost:9090/
          predicates:
            - Path=/api/**
Copy the code
  • HTTP address configuration mode
spring:
  cloud:
    gateway:
      routes:
        - id: demo-api
          uri: http://localhost:9090/
          predicates:
            - Path=/api/**
Copy the code
  • Registry configuration mode
spring:
  cloud:
    gateway:
      routes:
        - id: demo-api
          uri: lb://demo-api
          predicates:
            - Path=/api/**
Copy the code

Current limiting configuration

As the name suggests, limiting traffic is restricting traffic. Through current limiting, we can control the QPS of the system well, so as to achieve the purpose of protecting the system. Common traffic limiting algorithms are the counter algorithm, Leaky Bucket algorithm, and Token Bucket algorithm.

Spring Cloud Gateway official provides RequestRateLimiterGatewayFilterFactory filter factory, using Redis and Lua scripts for the way the token bucket.

1. Add dependencies

<! -- Spring Data Redis Reactive -->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
Copy the code

2. Traffic limiting rules: Limit traffic according to URI

spring:
  redis:
    host: localhost
    port: 6379
    password: 
  cloud:
    gateway:
      routes:
        # System module
        - id: demo-system
          uri: lb://demo-system
          predicates:
            - Path=/system/**
          filters:
            - StripPrefix=1
            - name: RequestRateLimiter
              args:
                redis-rate-limiter.replenishRate: 1 # Token bucket fill rate per second
                redis-rate-limiter.burstCapacity: 2 Total token bucket capacity
                key-resolver: "#{@pathKeyResolver}" Use SpEL expressions to reference beans by name
Copy the code

prompt

StripPrefix=1: indicates that the gateway automatically intercepts the prefix when forwarding to the service module.

3. Write URI traffic limiting rule configuration classes

package com.demo.gateway.config;

import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;

/** * Traffic limiting rule configuration class */
@Configuration
public class KeyResolverConfiguration
{
    @Bean
    public KeyResolver pathKeyResolver(a)
    {
        returnexchange -> Mono.just(exchange.getRequest().getURI().getPath()); }}Copy the code

4, test validation current-limiting starting gateway service DemoGatewayApplication. Java and system service DemoSystemApplication. Java. Because the gateway service has authentication, you can set the whitelist /system/** to test. If multiple requests are made, HTTP ERROR 429 will be returned, and two keys will be operated in Redis at the same time, indicating that traffic limiting is successful.

request_rate_limiter.{xxx}.timestamp
request_rate_limiter.{xxx}.tokens
Copy the code

Other traffic limiting rules

  1. Parameter current limiting:key-resolver: "#{@parameterKeyResolver}"
@Bean
public KeyResolver parameterKeyResolver(a)
{
	return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("userId"));
}
Copy the code
  1. IP current limit:key-resolver: "#{@ipKeyResolver}"
@Bean
public KeyResolver ipKeyResolver(a)
{
	return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
}
Copy the code

Fusing the drop

1. Add dependencies.

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
Copy the code

2. The configuration requires fuse downgrading service

spring:
  redis:
    host: localhost
    port: 6379Password: cloud: gateway: routes: # System module - id: demo-system URI: lb://demo-system
          predicates:
            - Path=/system/** filters: -stripprefix =1 # degrade configuration - name: Hystrix args: name: default # degrade interface address fallbackUri: 'forward:/fallback'Copy the code

prompt

The above configuration contains a Hystrix filter that applies Hystrix fuses and degradations, wraps the request named RouteHystrixCommand as a fallback, Routehystrixobservablecommand inherits Hystrix Observablecommand, which contains Hystrix circuit breaker core functions such as circuit breaking, resource isolation and degradation. When the request forwarded by the gateway is faulty, the gateway can quickly fail it and execute specific failure logic. Protect gateway security.

The configuration has an optional parameter fallbackUri. Currently, only forward urIs are supported. If the service is degraded, the request is forwarded to the controller corresponding to the URI. The controller can be a custom Fallback interface. Also can make custom Handler, it is necessary to implement the interface org. Springframework. Web. Reactive. The function. The server HandlerFunction < T extends ServerResponse >.

3. Add the return information of fusible downgrading

package com.demo.gateway.handler;

import com.alibaba.fastjson.JSON;
import com.demo.common.core.domain.R;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.HandlerFunction;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;
import java.util.Optional;
import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR;

/** ** fuse downgrade processing ** /
@Component
public class HystrixFallbackHandler implements HandlerFunction<ServerResponse>
{
    private static final Logger log = LoggerFactory.getLogger(HystrixFallbackHandler.class);

    @Override
    public Mono<ServerResponse> handle(ServerRequest serverRequest)
    {
        Optional<Object> originalUris = serverRequest.attribute(GATEWAY_ORIGINAL_REQUEST_URL_ATTR);
        originalUris.ifPresent(originalUri -> log.error("Gateway execution request :{} failed, Hystrix service degraded processing", originalUri));
        return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR.value()).contentType(MediaType.APPLICATION_JSON)
                .body(BodyInserters.fromValue(JSON.toJSONString(R.fail("Service has been downgraded to a circuit breaker.")))); }}Copy the code

Route configuration information plus a controller method to handle redirected /fallback requests

package com.demo.gateway.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.server.RequestPredicates;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import com.demo.gateway.handler.HystrixFallbackHandler;
import com.demo.gateway.handler.ValidateCodeHandler;

/** * Route configuration information ** /
@Configuration
public class RouterFunctionConfiguration
{
    @Autowired
    private HystrixFallbackHandler hystrixFallbackHandler;

    @Autowired
    private ValidateCodeHandler validateCodeHandler;

    @SuppressWarnings("rawtypes")
    @Bean
    public RouterFunction routerFunction(a)
    {
        return RouterFunctions
                .route(RequestPredicates.path("/fallback").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)),
                        hystrixFallbackHandler)
                .andRoute(RequestPredicates.GET("/code").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)), validateCodeHandler); }}Copy the code

4, fusing the drop test services gateway service DemoGatewayApplication. Java, access/system / * * in the test, find return service has to be demoted fusing, said the relegation success.