What is Gateway
The core of the Spring Cloud Gateway component is a series of filters, which can forward (route) requests sent by clients to pairs
Microservices should be. Spring Cloud Gateway is a firewall and agent added at the forefront of the whole microservice, which hides the IP port information of the microservice node,
So as to strengthen safety protection. Spring Cloud Gateway itself is also a micro service, which needs to be registered with Eureka service registry.
Gateway core concepts
- route
Routing information consists of an ID, a destination URL, a set of assertion factories and a set of filters. If the route assertion is true, the request URL matches the configured route. - Predicate the input type of the assertion function in the Spring Cloud Gateway is Spring
ServerWebExchange in the 5.0 framework. The assertion function of Spring Cloud Gateway allows developers to define and match any information from HTTP Request, such as request header and parameters. - Filter a standard Spring WebFilter. Spring Cloud
There are two types of filters in Gateway: Gateway Filter and Global Filter
Filter. The filter will modify the request and response
One of the important functions of Gateway is to realize the authentication of request. This action is often implemented through the filter provided by the Gateway
Use of Gateway
- Introducing Gateway dependencies
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies>
- Write startup class
@SpringBootApplication @EnableDiscoveryClient public class GatewayApplication { public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args); } }
- Write configuration
server: port: 10010 spring: application: name: api-gateway cloud: gateway: routes: # The routing id can be written at will - id: user-service-route # Service address of agent uri: HTTP://127.0.0.1:9091 # Route assertion, you can configure the mapping path predicates: - Path=/user/** eureka: client: service-url: defaultZone: HTTP://127.0.0.1:10086/eureka instance: prefer-ip-address: true
What is a Gateway filter
One of the important functions of Gateway is to realize the authentication of request. This action is often implemented through the filter provided by the Gateway
Common built-in filters:
Filter name | explain |
---|---|
AddRequestHeader | Add a Header to the matching request |
AddRequestParameters | Add parameters to the request route on the match |
AddResponseHeader | Add a Header for the response returned from the gateway |
StripPrefix | Remove the prefix from the request path on the match |
Routing prefix
If the request address of the client is inconsistent with the service address of the microservice, you can add and remove the path prefix by configuring the path filter.
Address of service provider: http://127.0.0.1:9091/user/8
- Add prefix: add a prefix path to the request address and then use it as the service address of the agent;
http://127.0.0.1:10010/8 --> http://127.0.0.1:9091/user/8 Add prefix path / user
- Remove prefix: remove some prefix paths from the path in the request address, and then serve as the service address of the agent
http://127.0.0.1:10010/api/user/8 --> http://127.0.0.1:9091/user/8 Remove prefix path / API
add prefix
In the gateway, you can add the address in the mapping path by configuring the filter PrefixPath of the route;
spring: cloud: gateway: routes: #The id of the route can be arbitrary - id: user-service-rote #Proxy's microservice address # uri: http://127.0.0.1:9999 uri: lb://user-service # Route assertion, you can configure the mapping path predicates: - Path=/** filters: # Add prefix to request path - PrefixPath=/user
PrefixPath=/xxx specifies the prefix to be added to the route. That is:
- PrefixPath=/user http://localhost:10010/8 -->http://localhost:9091/user/8
- PrefixPath=/user/abc http://localhost:10010/8 -->http://localhost:9091/user/abc/8
add prefix
In the gateway, the address in the mapping path can be removed by configuring the route filter StripPrefix:
spring: cloud: gateway: routes: #The id of the route can be arbitrary - id: user-service-rote #Proxy's microservice address # uri: http://127.0.0.1:9999 uri: lb://user-service # Route assertion, you can configure the mapping path predicates: - Path=/api/user/** filters: # It means filtering 1 path, 2 means two paths, and so on - StripPrefix=1
The number of prefixes to be removed from the route is specified by StripPrefix=1. For example, the path / api/user/1 will be proxied to / user/1. That is:
- StripPrefix=1 http://localhost:10010/api/user/8 -->http://localhost:9091/user/8
- StripPrefix=2 http://localhost:10010/api/user/8 -->http://localhost:9091/8
Execution lifecycle
The Filter life cycle of Spring Cloud Gateway is similar to that of Spring MVC. There are two interceptors: "pre" and "post". "Pre" and "post" are called separately before and after the request is executed.
The pre and post here can be implemented before and after the filter method is executed by the GatewayFilterChain of the filter
Usage scenario
- Request authentication: generally, before the GatewayFilterChain executes the filter method, if it is found that there is no access permission, it will directly return null.
- Exception handling: generally, after the GatewayFilterChain executes the filter method, the exception is recorded and returned.
- Statistics of service call duration: the gateway filterchain performs statistics according to the time before and after the filter method is executed.
Custom local filter
Requirements: in the filter (MyParamGatewayFilterFactory) http://localhost:10010/user/8? The value of the parameter name in name = YH is obtained and output to the console
Add a gateway filter to the application.yml file:
Insert picture description here]( https://img-blog.csdnimg.cn/0bafd595c32841a9872c31236d4a442a.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5bm95ri455m96YWl,size_20,color_FFFFFF,t_70,g_se,x_16)
Create a config file and create a class named MyParamGatewayFiterFactory
be careful! Name xxxgatewayfiterfactory, and xxxx is yml user-defined name + GatewayFiterFactory; The GatewayFiterFactory does not or has an error. The following error will occur
Failed to start bean 'eurekaAutoServiceRegistration'; nested exception is reactor.core.Exceptions$ErrorCallbackNotImplemented: java.lang.IllegalArgumentException: Unable to find GatewayFilterFactory with name MyParam
Inherit MyParamGatewayFiterFactory from the parent class abstractgatewayfilterfactory < MyParamGatewayFiterFactory. Config > and add @ Component annotation
Create a Config class to read the filter configuration parameters, create a String type parameter in the class corresponding to the filter parameter name configured in the application.yml configuration file, and generate the get set method
Override method of parent class:
Override the parent GatewayFilter method. It can be seen from the source code that the required return type is
ServerWebExchange exchange, GatewayFilterChain chain
Complete code snippet
package com.yh.gateway.filter; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.stereotype.Component; import java.util.Arrays; import java.util.List; @Component public class MyParamGatewayFilterFactory extends AbstractGatewayFilterFactory<MyParamGatewayFilterFactory.Config> { public MyParamGatewayFilterFactory() { super(Config.class); } @Override public List<String> shortcutFieldOrder() { return Arrays.asList("param"); } @Override public GatewayFilter apply(Config config) { return (exchange, chain) -> { // http://localhost:10010/user/8?name=yh config.param ==> name //Gets the parameter value of the parameter name corresponding to param in the request parameter ServerHttpRequest request = exchange.getRequest(); if (request.getQueryParams().containsKey(config.param)){ request.getQueryParams().get(config.param).forEach((v) -> { System.out.print("--Local filter--Get parameters "+config.param+"="+ v); }); } return chain.filter(exchange);//Execute request }; } //Read parameters of filter configuration public static class Config{ //Corresponds to the filter parameter name configured in the application.yml configuration file private String param; public String getParam() { return param; } public void setParam(String param) { this.param = param; } } }
Output results:
Custom global filter
Requirements: write a global filter and check whether the request carries the token request header in the filter. If the token request header exists, it will be released; If the token is empty or does not exist, set the returned status code as: unauthorized and no longer executed.
Create a global filter class to implement GlobalFilter,; Ordered is the filter execution order
@Component public class MyGlobalFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { return null; } @Override public int getOrder() { return 0; } }
@Component public class MyGlobalFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { System.out.println("Global filter"); String token = exchange.getResponse().getHeaders().getFirst("token");//Get the first request header named token //No permission if (StringUtils.isBlank(token)) { exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);//If not, return status code 401 return exchange.getResponse().setComplete(); } //Have authority return chain.filter(exchange); } @Override public int getOrder() { //The smaller the value, the more priority is given to execution return 1; } }
Open postman. When there is no request header, the result is 401
Add request header token successfully accessed