Microservice Architecture - Service Gateway (Gateway) - Filter Principle and Life Cycle

Filter principle and life cycle

We have learned the routing and assertion functions of Gateway before. In this section, we will learn about the filter principle, and then pick a few commonly used filters to learn.

1. The working mode of the filter

All open source frameworks implement the same filter mode. In a way similar to the chain of responsibility, the events in the traditional chain of responsibility mode will be passed until a processing object takes over, and the filter is a bit different from the traditional chain of responsibility. It's more like the opening handshake of a football team. All the players are lined up, and you have to shake hands with all the players in turn from beginning to end.

The filters in the Gateway are also the same model, they are prioritized, and all gateway call requests start from the highest priority filter. All the way to the end until it is processed by the last filter.

2. Implementation of the filter

Implementing a filter in Gateway is very simple, just implement the default method of the GatewayFilter interface

@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    
    
    // 随意发挥
    return chain.filter(exchange);    
}

There are two key information here:
ServerWebExchange: This is the HTTP request-response interaction protocol encapsulated by Spring, from which we can obtain various request parameters in request and response, and also add content to it;

GatewayFilterChain: It is the call chain of the filter. At the end of the method, we need to pass the exchange object to the next object in the call chain.

3. The execution phase of the filter

Different from the definition of Pre and Post of filters in Zuul, the previous generation gateway component in Spring Cloud, Gateway achieves effects similar to Pre and Post through the code in Filter.

Pre and Post refer to the execution phase of the current filter. Pre is executed before the next filter, and Post is executed after the filter is executed. We can also define the execution logic of Pre and Post in Gateway Filter.

3.1, Pre type

Let's take AddResponseHeaderGatewayFilterFactoryfor example, it can add header information to Response:

@Override
public GatewayFilter apply(NameValueConfig config) {
    
    
	return (exchange, chain) -> {
    
    
        exchange.getResponse().getHeaders().add(config.getName(), config.getValue());
        return chain.filter(exchange);
    };
}

The specific execution method here is defined to be executed before calling the "chain.filter() method, that is, before forwarding to the lower-level call link, so it can be understood as a Pre-type filter.

3.2, Post type

Let's take SetStatusGatewayFilterFactoryan example. After the filter is executed, it returns the specified HTTP status to the caller.

return chain.filter(exchange).then(Mono.fromRunnable(() -> {
    
    
		// 这里是业务逻辑
		}));

The main logic of this filter is in the then method, and then is a callback function, which is executed after the lower-level call links are completed, so this type of filter can be regarded as a Post Filter.

4. Seats of filters

In Gateway, we can org.spingfamewok core.Orderedspecify the execution order for the filter by implementing the interface. The following generation implements the Ordered interface method, and sets the filter execution order to 0.

@Override
public int getOrder() {
    
    
	return 0;
}

For Pre-type filters, the larger the number, the higher the priority, and the earlier it will be executed, but for the Post-type filter, the smaller the number, the earlier it will be executed.

5. Filter example

5.1, Header filter

There are many sets of filters in this series, AddRequestHeader and AddResponseHeader, add the specified Header to the Request and Response respectively, and the corresponding RemoveRequestHeader and RemoveResponseHeader respectively perform the removal operation, and the usage is also very simple:

.filters(f -> f.addResponseHeader("who", "gateway-header"))

The above example will add a who attribute to the header, and the corresponding value is gateway-header.

5.2, StripPrefix filter

This is a more commonly used filter, and its function is to remove part of the URL path. For example, our filter configuration is as follows:

.route(r -> r.path("/gateway-test/**")
             .filters(f -> f.stripPrefix(1))
             .uri("lb://FEIGN-SERVICE-PROVIDER/")
)

If the HTTP request is accessed /gateway-test/sample/update, if there is no StripPrefixfilter, FEIGN-SERVICE-PROVIDERthe access path forwarded to the service is the same.

When we add this filter, Gateway will stripPrefix(1)take the path in the URL according to the value in, for example, here we set 1, then remove a prefix, and finally send the path to the background service "sample/update".

5.3, PrefixPath filter

It StripPrefixis exactly the opposite of the function, and will add a prefix in front of the request path

.route(r -> r.path("/gateway-test/**")
             .filters(f -> f.prefixPath("go"))
             .uri("lb://FEIGN-SERVICE-PROVIDER/")
)

For example, when we visit “/gateway-test/sample”, the filter configured in the above example will send the request to "go/gateway-test/sample”.

5.4, ​​RedirectTo filter

It can redirect requests receiving a specific status code to a specified URL:

.filters(f -> f.redirect(302, "https://www.study.com/"))

The above example receives two parameters, HTTP status code and URL. If the request result is 404, it will redirect to the page specified by the second parameter. This function can also perform unified exception handling, redirecting or requesting to the login Unauthorizedpage Forbidden.

5.5, SaveSession filter

We know that microservices are stateless sessions, so most of them do not rely on the session mechanism, but if you have distributed session requirements, for example, some functions are implemented based on spring-session and spring-security, then this filter Maybe it will work for you, it will force save the session before calling the service:

.filters(f -> f.saveSession())

Guess you like

Origin blog.csdn.net/jianghao233/article/details/130055779