spring Cloud gateway has the following features:
Dynamic routing: it can match any request attribute;
You can specify Predicate assertions and filters for routes
Integrate spring cloud service discovery
Easy to write Predicate assertions and filters
Request current limiting function
Support path rewriting
Three core concepts
route:
Routing is the basic module for building a gateway. It consists of id, target uri, a series of assertions and filters. If the assertion is true, the route will be matched
Assertion:
The developer can match all the contents of the http request (such as the request header and request parameters), and route the request if it matches the assertion
Filtering:
It refers to the instance of gatewayfilter in the spring framework. Using the filter, you can modify the request before or after it is routed
Namely
The web request locates the real service node by matching some conditions. And some fine control is carried out before and after the forwarding process.
Assertion is our matching condition, and filter can be understood as an omnipotent interceptor. With these two elements and the uri of the target, we can realize the specific routing
gateway configuration
The basic steps are as follows
- Create a SpringBoot project gateway and introduce gateway dependencies
- Write startup class
- Write basic configuration and routing rules
- Start the gateway service for testing
Import dependency:
<!--gateway--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!--nacos Service discovery dependency--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>
Write startup class
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class GatewayApplication { public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args); } }
Basic configuration and routing rules
Create the application.yml file as follows:
server: port: 10010 # Gateway port spring: application: name: gateway # Service name cloud: nacos: server-addr: localhost:8848 # nacos address gateway: routes: # Gateway routing configuration - id: user-service # Routing id, user-defined, as long as it is unique # uri: http://127.0.0.1: the destination address of 8081 # route http is the fixed address uri: lb://The target address lb of userservice # route is load balancing, followed by the service name predicates: # Routing assertion is to judge whether the request meets the conditions of routing rules - Path=/user/** # This is matched according to the path. It meets the requirements as long as it starts with / user /
We proxy all requests that meet the Path rule to the address specified by the uri parameter.
In this example, we proxy the request starting with / user / * * to lb://userservice. lb is load balancing. Pull the service list according to the service name to achieve load balancing. State routing
By default, the gateway will create a dynamic route with the microservices on the registry as the path for forwarding according to the service list registered in the registry, so as to realize the function of dynamic routing
Flow chart of Gateway Routing
Summary:
Gateway building steps:
-
Create a project to introduce nacos service discovery and gateway dependency
-
Configure application.yml, including basic service information, nacos address and routing
Routing configuration includes:
-
Route id: the unique identifier of the route, which is similar to the primary key of the database and can be globally unique
-
Routing destination (uri): the destination address of the route. http represents the fixed address and lb represents load balancing according to the service name (dynamic routing)
-
Route assertions: Rules for judging routes,
-
Routing filters: process requests or responses
Assertion factory
The assertion rules we write in the configuration file are just strings. These strings will be read and processed by the predict factory and transformed into conditions for routing judgment
For example, Path=/user / * * matches according to the path. This rule is determined by
org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory class
There are more than a dozen assertion factories like this in the spring cloud gateway:
name | explain | Example |
---|---|---|
After | Is a request after a certain point in time | - After=2037-01-20T17:42:47.789-07:00[America/Denver] |
Before | Is a request before a certain point in time | - Before=2031-04-13T15:14:47.433+08:00[Asia/Shanghai] |
Between | Is a request before two points in time | - Between=2037-01-20T17:42:47.789-07:00[America/Denver], 2037-01-21T17:42:47.789-07:00[America/Denver] |
Cookie | The request must contain some cookie s | - Cookie=chocolate, ch.p |
Header | The request must contain some header s | - Header=X-Request-Id, \d+ |
Host | The request must be to access a host (domain name) | - Host=.somehost.org,.anotherhost.org |
Method | The request mode must be the specified mode | - Method=GET,POST |
Path | The request path must conform to the specified rules | - Path=/red/{segment},/blue/** |
Query | The request parameter must contain the specified parameter | -Query=name, Jack or - Query=name |
RemoteAddr | The ip address of the requester must be in the specified range | - RemoteAddr=192.168.1.1/24 |
Weight | Weight processing |
Filter factory
Gateway filter is a filter provided in the gateway, which can process the requests entering the gateway and the responses returned by the microservice:
Types of routing filters
Spring provides 31 different routing filter factories. For example:
name | explain |
---|---|
AddRequestHeader | Add a request header to the current request |
RemoveRequestHeader | Remove a request header from the request |
AddResponseHeader | Add a response header to the response result |
RemoveResponseHeader | There is a response header removed from the response result |
RequestRateLimiter | Limit requested traffic |
Request header filter
Let's take AddRequestHeader as an example.
Requirement: add a request header to all requests entering userservice: truth = feifeifeiyyds
You only need to modify the application.yml file of the gateway service and add routing filtering:
spring: application: name: gateway cloud: gateway: routes: - id: orderservice #The unique id of the route, the id of the route, has no fixed rules but requires uniqueness. It is recommended to match the service name uri: lb://userservice # satisfies the path to jump for this route and provides the route address of the service predicates: #The assertion determines whether this route is satisfied - Path=/order/** filters: - AddRequestHeader=Truth,feifeiyyds # Add request header nacos: discovery: #nacos service discovery server-addr: localhost:8848
The current filter is written under the userservice route, so it is only valid for requests to access the userservice.
Default filter
If you want to be effective for all routes, you can write the filter factory to default. The format is as follows:
spring: cloud: gateway: routes: - id: user-service uri: lb://userservice predicates: - Path=/user/** default-filters: # Default filter - AddRequestHeader=Truth, Itcast is freaking awesome!
summary
What is the function of the filter?
① Process the routed request or response, such as adding a request header
② The filter configured under the route is only effective for the requests of the current route
What is the role of defaultFilters?
① Filters in effect for all routes
Global filter
In the previous section, the gateway provides 31 filters, but the function of each filter is fixed. If we want to intercept requests and do our own business logic, we can't do it.
Global filter action
The global filter is also used to handle all requests and microservice responses entering the gateway, just like the gateway filter. The difference is that the gateway filter is defined by configuration, and the processing logic is fixed; The logic of GlobalFilter needs to be implemented by writing code.
This is defined by implementing the GlobalFilter interface.
public interface GlobalFilter { /** * Process the current request. If necessary, pass the request to the next filter through {@ link GatewayFilterChain} * * @param exchange Request context, which can obtain request, Response and other information * @param chain Used to delegate requests to the next filter * @return {@code Mono<Void>} Return to indicate the end of the current filter business */ Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain); }
Writing custom logic in filter can realize the following functions:
- Login status judgment
- Permission verification
- Request current limit, etc
Custom global filter
Requirement: define a global filter, intercept the request, and judge whether the requested parameters meet the following conditions:
-
Whether there is authorization in the parameter,
-
Whether the authorization parameter value is admin
If both are met, release, otherwise intercept
realization:
Define a filter in the gateway:
import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.annotation.Order; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; @Order(-1) @Component public class AuthorizeFilter implements GlobalFilter { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 1. Get request parameters MultiValueMap<String, String> params = exchange.getRequest().getQueryParams(); // 2. Get the authorization parameter String auth = params.getFirst("authorization"); // 3. Calibration if ("admin".equals(auth)) { // Release return chain.filter(exchange); } // 4. Interception // 4.1. Prohibit access and set the status code exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN); // 4.2. End processing return exchange.getResponse().setComplete(); } }
You can also register filters in this way
package com.cxf.globalFilter; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.http.HttpStatus; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.util.MultiValueMap; @Configuration @Slf4j public class myfilter { @Value("${server.port}") String port; @Bean @Order(-1) /** * Simply judge whether you have login permission */ public GlobalFilter globalFilter1(){ return (exchange, chain) -> { MultiValueMap<String, String> queryParams = exchange.getRequest().getQueryParams(); log.warn("The currently accessed port number is{}",port); String name = queryParams.getFirst("name"); if("feifei".equals(name)) return chain.filter(exchange); ServerHttpResponse response = exchange.getResponse(); response.setStatusCode(HttpStatus.UNAUTHORIZED); return response.setComplete(); }; } }
Filter execution sequence
The request to enter the gateway will encounter three types of filters: the filter of the current route, DefaultFilter and GlobalFilter
After requesting a route, the current route filter, DefaultFilter and GlobalFilter will be merged into a filter chain (Collection), and each filter will be executed in turn after sorting:
What are the sorting rules?
- Each filter must specify an order value of type int. the smaller the order value, the higher the priority and the higher the execution order.
- GlobalFilter specifies the order value by implementing the Ordered interface or adding the @ order annotation, which is specified by ourselves
- The order of routing filter and defaultFilter is specified by Spring. By default, it is incremented from 1 in the order of declaration.
- When the order value of the filter is the same, it will be executed in the order of defaultfilter > routing filter > globalfilter.
For details, you can view the source code:
org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getFilters() method is to load defaultFilters first, then load filters of a route, and then merge.
The org.springframework.cloud.gateway.handler.FilteringWebHandler#handle() method will load the global filter, merge it with the previous filter, sort it according to the order, and organize the filter chain
Cross domain problem
Solve cross domain problems
In the application.yml file of gateway service, add the following configuration:
spring: cloud: gateway: # . . . globalcors: # Global cross domain processing add-to-simple-url-handler-mapping: true # Solve the problem that the options request is intercepted corsConfigurations: '[/**]': allowedOrigins: # Which websites are allowed to make cross domain requests - "http://localhost:8090" allowedMethods: # Allowed cross domain ajax request mode - "GET" - "POST" - "DELETE" - "PUT" - "OPTIONS" allowedHeaders: "*" # Header information allowed to be carried in the request allowCredentials: true # Allow cookie s maxAge: 360000 # Validity of this cross domain detection