SpringCloud Upgrade Path 2020.0.x-41. Explanation of the basic SpringCloudGateway process

This series of code addresses: https://github.com/JoJoTec/spring-cloud-parent

We continue to analyze the WebHandler mentioned in the previous section, after encapsulating the request as a HTTP WebHandler Adapter for ServerWebExchange, the request passes through the ExceptionHandlingWebHandler

Access Point for Global Web Handling Exception Handler

Previously, some netizens asked the author how to add a global exception handler to Spring Cloud Gateway, which is actually the same as adding an asynchronous Web service based on Spring-Flux, by implementing and registering a WebExceptionHandler Bean:

WebExceptionHandler.java

public interface WebExceptionHandler {
	Mono<Void> handle(ServerWebExchange exchange, Throwable ex);
}

These beans are the ones that ExceptionHandlingWebHandler is added to the entire request processing link:

ExceptionHandlingWebHandler.java

@Override
public Mono<Void> handle(ServerWebExchange exchange) {
	Mono<Void> completion;
	try {
	    //This is actually the assembly of the back link, which calls the handle of the back FilteringWebHandler
		completion = super.handle(exchange);
	}
	catch (Throwable ex) {
		completion = Mono.error(ex);
	}

	for (WebExceptionHandler handler : this.exceptionHandlers) {
		completion = completion.onErrorResume(ex -> handler.handle(exchange, ex));
	}
	return completion;
}

From the source code, you can see that each WebExceptionHandler is joined to the link as Mono's exception handling onErrorResume. OnErrorResume means that if an exception occurs in front of the link, the exception is caught here and handler.handle(exchange, ex) is called to handle it. If understood using blocking code, it is equivalent to:

try {
    //Front Link
} catch(Throwable ex) {
    return handler.handle(exchange, ex)
}

Here we see that there are several WebExceptionHandler s that will append onErrorResume after the link, which is equivalent to:

completion.onErrorResume(ex -> webExceptionHandler1.handle(exchange, ex)).onErrorResume(ex -> webExceptionHandler2.handle(exchange, ex)).onErrorResume(ex -> webExceptionHandler3.handle(exchange, ex))...

Converting to blocking code understanding is:

try {
    completion
} catch(Throwable e1) {
    try {
        return webExceptionHandler1.handle(exchange, e1)
    } catch(Throwable e2) {
        try {
            return webExceptionHandler2.handle(exchange, ex)
        } catch(Throwable e2) {
            return webExceptionHandler3.handle(exchange, ex)
            //Continue overlaying if you still have
        }
    }
}

When WebExceptionHandler can handle this exception, its handle method returns a true response, otherwise it returns an exception, for example:

public class WebExceptionHandler1 implements WebExceptionHandler {
	@Override
	public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
		//If ResponseStatusException is used, the Response Code and HTTP Header inside the exception are used to populate the Response Code and HTTP Header of the response
		if (ex instanceof ResponseStatusException) {
			ServerHttpResponse response = exchange.getResponse();
			ResponseStatusException responseStatusException = (ResponseStatusException) ex;
			response.setRawStatusCode(responseStatusException.getRawStatusCode());
			responseStatusException.getResponseHeaders()
					.forEach((name, values) ->
							values.forEach(value -> response.getHeaders().add(name, value)));
			//Return response complete
			return response.setComplete();
		}
		//Throw exception, continue link exception handling
		return Mono.error(ex);
	}
}

To translate into synchronization code is to understand:

if (ex instanceof ResponseStatusException) {
	ServerHttpResponse response = exchange.getResponse();
	ResponseStatusException responseStatusException = (ResponseStatusException) ex;
	response.setRawStatusCode(responseStatusException.getRawStatusCode());
	responseStatusException.getResponseHeaders()
			.forEach((name, values) ->
					values.forEach(value -> response.getHeaders().add(name, value)));
	//Return response complete
	return response.setComplete();
}
//Throw exception, continue link exception handling
throw ex;

If you want to encapsulate your own uniform error response, you can do so by implementing this interface.

Link Start Point for DefaultWebFilterChain - FilteringWebHandler

Next, go to FilteringWebHandler, noting that it is org.springframework.web.server.handler.FilteringWebHandler, not org.springframework.cloud.gateway.handler.FilteringWebHandler of Spring Cloud Gateway. Here, the WebFilter loaded in the context is stitched into a DefaultWebFilterChain and its filter method is called:

private final DefaultWebFilterChain chain;

public FilteringWebHandler(WebHandler handler, List<WebFilter> filters) {
	super(handler);
	this.chain = new DefaultWebFilterChain(handler, filters);
}

@Override
public Mono<Void> handle(ServerWebExchange exchange) {
	return this.chain.filter(exchange);
}

Spring Cloud Gateway's Filtering WebHandler is the starting point for Spring Cloud Gateway's request processing business. Here we are about to enter the entire Spring Cloud Gateway Filter link, including each path's own GatewayFilter and the global GlobalGatewayFilter, where the processing starts to assemble the full call link. We'll mention that later

Since our project dependencies include the dependencies of Spring Cloud Sleuth and Prometheus, we have three WebFilter s here:

  • org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter: After adding a Prometheus-related dependency, this MetricsWebFilter will be used to record request processing time and collect related metrics.
  • org.springframework.cloud.sleuth.instrument.web.TraceWebFilter: After adding a Spring Cloud Sleuth-related dependency, this TraceWebFilter will appear.
  • org.springframework.cloud.gateway.handler.predicate.WeightCalculatorWebFilter:Spring Cloud Gateway Routing Weight Related Configuration Function Related Implementation Class, which we don't care about here.

Its specific process, we will continue to analyze in detail in the next section.

WeChat Search "My Programming Miao" pays attention to public numbers, brushes every day, easily upgrades technology, and chops various offer s:

Tags: Spring Cloud

Posted on Thu, 25 Nov 2021 12:53:48 -0500 by Barand