What problems do we have without the gateway
If the client is allowed to interact directly with each micro-service, there will be the following problems:
- Cross-domain requests exist and are complicated to process in certain scenarios
- Authentication issues, each microservice requires independent authentication
- Some microservices use firewalls or browser-unfriendly protocols, making direct access difficult
What problems can gateways solve for us
Unified access
- Provide unified access service for all wireless applications
- High performance, high concurrency, high availability
- Load balancing, Dr Switchover, and remote survival
Traffic control
- Service degradation
- fusing
- routing
Safety protection
- Black and white list
- Risk control brush, malicious brush and so on
Protocol adapter
- Front-end system (HTTP, HTTPS), back-end system (RPC)
- Long and short links are supported
- Route the front-end request and respond to the result
GateWay GateWay Introduction
Spring Cloud Gateway is an API Gateway officially launched by Spring. The framework includes Spring5, SpringBoot2, Project Reactor, and Netty used by the underlying communication framework. When Spring Cloud Gateway was first launched, Netflix had already launched ZUUL, an API Gateway framework with similar functions. However, ZUUL had a disadvantage that the communication mode was blocked. Although it was later upgraded to non-blocking ZUUL2, However, since Spring Cloud Gateway has been launched for a period of time, it has not been widely used due to the lack of data and poor maintenance.
Related terms
The Route:
A set of rules is a metadata class with attributes such as URI, predicate, filter, and so on. \
Predicate:
This is an approach to Java8 functional programming, where the route rule takes effect when conditions are met.
The Filter:
Filter can be considered as the most core module of Spring Cloud Gateway. It is used to complete fusing, security, logical execution and network invocation, which are subdivided into Gateway Filter and Global Filter. The difference is whether a particular route rule is in effect or all route rules are in effect.
Routing rules
Path: Query: Method:
Datetime:
RemoteAddr:
Header:
Using dynamic configuration (using Eureka)
# # # filters
RewritePathGatewayFilterFactory
PrefixPathGatewayFilterFactory
StripPrefixGatewayFilterFactory
SetPathGatewayFilterFactory
AddRequestParameterGatewayFilterFactory
SetStatusGatewayFilterFactory
Custom filter
public class CustomGatewayFilter implements GatewayFilter, Ordered {/** * @param exchange * @param chain * @return */ @override public Mono<Void> Filter (ServerWebExchange Exchange, GatewayFilterChain chain) {system.out.println (" Custom gateway filter "); return chain.filter(exchange); } @override public int getOrder() {return 0; }}Copy the code
@Configuration public class GatewayRoutesConfiguration { public RouteLocator routeLocator(RouteLocatorBuilder builder) { Path ("/order") // Target uri.uri ("lb://app-order") // Register custom filters.filters (new) CustomGatewayFilter()) // Route ID, unique.id ("app-order")).build(); }}Copy the code
Custom global filters
@Component public class CustomGlobalFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {system.out.println (" Custom global filter "); return chain.filter(exchange); } @Override public int getOrder() { return 0; }}Copy the code
The source code parsing
The Spring Cloud Gateway receives the request and matches the routing rules, which are then handed to the Web Handler. The Web handler executes a series of filter logic.
The entrance
Gateway to the programming model is webflux + reactor, I on this piece of ability is limited, can not explain don’t explain (sweat) org. Springframework. Web. Reactive. DispatcherHandler# handle
public Mono<Void> handle(ServerWebExchange exchange) { if (this.handlerMappings == null) { return createNotFoundError(); } return Flux.fromIterable(this.handlerMappings) .concatMap(mapping -> mapping.getHandler(exchange)) .next() .switchIfEmpty(createNotFoundError()) .flatMap(handler -> invokeHandler(exchange, handler)) .flatMap(result -> handleResult(exchange, result)); }Copy the code
All WebFlux calls go through this interface.
Of all the implementation classes, this one belongs to the Gateway, and that’s it.
Private Route convertToRoute(RouteDefinition RouteDefinition) {// Predicates AsyncPredicate<ServerWebExchange> predicate = combinePredicates(routeDefinition); // getFilters List<GatewayFilter> gatewayFilters = getFilters(routeDefinition); // Encapsulate the contents of the Route and return the object route.async (routeDefinition).asyncpredicate (predicate).replacefilters (gatewayFilters).build(); }Copy the code
protected Mono<Route> lookupRoute(ServerWebExchange exchange) { return this.routeLocator.getRoutes() // individually Filter routes so that filterWhen error delaying is not a. ConcatMap (route -> Mono.just(route).filterWhen(r -> { // add the current route we are testing exchange.getAttributes().put(GATEWAY_PREDICATE_ROUTE_ATTR, r.getId()); return r.getPredicate().apply(exchange); })}Copy the code
All the way back
org.springframework.web.reactive.DispatcherHandler#handle
Public Mono<Void> Handle (ServerWebExchange exchange) exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR); List<GatewayFilter> gatewayFilters = route.getfilters (); List<GatewayFilter> combined = new ArrayList<>(this.globalfilters); // Add to global filter combined. AddAll (gatewayFilters); / / sorting AnnotationAwareOrderComparator. Sort (combined); if (logger.isDebugEnabled()) { logger.debug("Sorted gatewayFilterFactories: " + combined); } / / calls, the most classic responsibility of chain will be executed every global filter again return new DefaultGatewayFilterChain (combined) filter (exchange); }Copy the code
Forward requests
The ForwardRoutingFilter simply uses spring MVC’s capabilities and sends the request to a dispatcherHandler that finds the desired execution logic based on the path prefix.
Response to write
The core class for response write back is NettyWriteResponseFilter
conclusion
I just went through the general process, and I will continue to analyze the details according to the specific situation. I am not familiar with reactor programming, so I can only understand the general aspects, which will be filled in later.