[In-depth analysis of spring cloud gateway] 04 Global Filters

In the previous section, we learned about GatewayFilter.
Recall a key point:
The essence of GateWayFilterFactory is to parse the configuration and add Filter to the specified route in order to process the request message.

1. Principle analysis

What is GlobalFilter? First look at the interface definition

public interface GlobalFilter {
    
    
    Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}

Take another look at GatewayFilter

public interface GatewayFilter extends ShortcutConfigurable {
    
    
    Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}

It can be seen that the method signatures of GatewayFilter and GlobalFilter are exactly the same, so why do you need to make another GlobalFilter?
The role of GatewayFilter is mainly to parse out the configuration based on the configuration file or code, which is the configuration of routes, and then process the message. This Filter is forcibly bound to a route.
GlobalFilter is directly forced to load and does not belong to a specified route. Whether the filter needs to be processed is judged in the filter method. If you don't need to handle it yourself, just throw it to the next filter in the chain.
Request processing logic, you can see the following code
FilteringWebHandler.java

@Override
public Mono<Void> handle(ServerWebExchange exchange) {
    
    
    Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
    List<GatewayFilter> gatewayFilters = route.getFilters();

    List<GatewayFilter> combined = new ArrayList<>(this.globalFilters);
    combined.addAll(gatewayFilters);
    // TODO: needed or cached?
    AnnotationAwareOrderComparator.sort(combined);

    if (logger.isDebugEnabled()) {
    
    
        logger.debug("Sorted gatewayFilterFactories: " + combined);
    }

    return new DefaultGatewayFilterChain(combined).filter(exchange);
}

Code analysis:

  • Get the route from the configuration and remove the gatewayFilter that meets the current route conditions
  • GlobalFilter and gatewayFilter are combined into a list and sorted
  • The filter is encapsulated into a chain and the current request is processed in the chain.

2. How to customize a GlobalFilter

@Bean
public GlobalFilter customFilter() {
    
    
    return new CustomGlobalFilter();
}

public class CustomGlobalFilter implements GlobalFilter, Ordered {
    
    

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    
    
        log.info("custom global filter");
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
    
    
        return -1;
    }
}

3. Built-in GlobalFilter

3.1 Forward Routing Filter

The processing URL format is: forward:///localendpoint, which will be forwarded to the address behind forward
3.2 The LoadBalancerClient Filter
has not seen the source code, the local one is SpringCloud 2021.0.1 version
3.3 The ReactiveLoadBalancerClientFilter
If the URL has an lb scheme ( such as lb://myservice), which will use Spring Cloud ReactorLoadBalancer to resolve the name (myservice in the previous example) to the actual host and port, replacing the URI

spring:
  cloud:
    gateway:
      routes:
      - id: myRoute
        uri: lb://service
        predicates:
        - Path=/service/**

3.4 The Netty Routing Filter

If the URL has http or https mode, Netty Routing Filter will be run. It uses Netty HttpClient to make downstream proxy requests.
The response is placed in the ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR exchange attribute.

3.5 The Netty Write Response Filter

If there is a value from the ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR exchange attribute, this filter is executed and used to write the response message to the cache.

3.6 The RouteToRequestUrl Filter

RouteToRequestUrlFilter will run if the Route object exists in the ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR exchange attribute. It creates a new URI based on the request URI, updating it using the uri attribute of the Route object. The new URI is placed in the ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR exchange attribute. If the URI has a prefix scheme, such as lb:ws://serviceid, the lb scheme is stripped from the URI and placed in ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR for later use in the filter chain.

3.7 The Websocket Routing Filter

If there is ws or wss scheme in the ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR exchange attribute, the Websocket Routing Filter will be run. It uses the Spring Web Socket basic module to forward Websockets downstream.
Websockets with URI prefix lb can be load balanced, such as lb:ws://serviceid

spring:
  cloud:
    gateway:
      routes:
      # SockJS route
      - id: websocket_sockjs_route
        uri: http://localhost:3001
        predicates:
        - Path=/websocket/info/**
      # Normal Websocket route
      - id: websocket_route
        uri: ws://localhost:3001
        predicates:
        - Path=/websocket/**

3.8 The Gateway Metrics Filter

To enable gateway metrics, add spring-boot-starter-actuator as a project dependency. Then, by default, the gateway metrics filter will run as long as the property spring.cloud.gateway.metrics.enabled is not set to false. This filter adds a timer metric named spring.cloud.gateway.requests with the following tag

  • routeId: route ID.
  • routeUri: URI to which the API will be forwarded
  • outcome: outcome classification, based on HttpStatus.Series
  • status: Returns the HTTP Status of the client's request
  • httpStatusCode: returns the httpStatusCode of the client's request
  • httpMethod: HTTP method used for requests.
    Additional metrics can be activated via spring.cloud.gateway.metrics.tags.path.enabled (default is false):
  • path: the path of the request.
    These metrics can be obtained from /actuator/metrics/spring.cloud.gateway.requests, and can be easily integrated with Prometheus to create Grafana dashboard.
    Note: To enable pometheus, you need to add micrometer-registry-prometheus as a project dependency.

Guess you like

Origin blog.csdn.net/suyuaidan/article/details/132625746