Based on the previous episode
brief introduction
- Spring Cloud Gateway is a gateway service developed on the spring official website based on Spring 5.0, Spring Boot 2.0, Project Reactor and other technologies.
- Spring Cloud Gateway provides the basic functions of the gateway based on the Filter chain: security, monitoring / embedding point, current limiting, etc.
- Spring Cloud Gateway provides a simple, effective and unified API routing management method for microservice architecture.
- Spring Cloud Gateway is a solution to replace Netflix Zuul.
The core of the Spring Cloud Gateway component is a series of filters that can forward (route) requests sent by clients to corresponding microservices. Spring Cloud Gateway is a firewall and agent added at the forefront of the whole microservice to hide the IP port information of microservice nodes, so as to strengthen security protection. Spring Cloud Gateway itself is also a micro service, which needs to be registered with Eureka service registry.
The core functions of the gateway are: filtering and routing
Architecture after Gateway is added
- Whether it is a request from the client (PC or mobile terminal) or an internal call of the service. All requests for services can pass through the Gateway, and then the Gateway can realize authentication, dynamic routing and so on. The Gateway is the unified entrance to our services.
Core concept
- Route: 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 ServerWebExchange in the Spring 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. There are two types of filters in Spring Cloud Gateway: Gateway Filter and Global Filter. The filter will modify the request and response.
quick get start
Create project
Open the Heima springcloud \ Heima gateway \ pom.xml file and modify it as follows:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>heima-springcloud</artifactId> <groupId>com.itheima</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>heima-geteway</artifactId> <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> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> </project>
Write startup class
Create the com.itheima.gateway.GatewayApplication startup class in Heima gateway
package com.itheima.gateway; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @EnableDiscoveryClient public class GatewayApplication { public static void main(String[] args) { SpringApplication.run(GatewayApplication.class, args); } }
Write configuration
Create the Heima gateway \ SRC \ main \ resources \ application.yml file as follows:
server: port: 10010 spring: application: name: api-gateway eureka: client: service-url: defaultZone: http://127.0.0.1:10086/eureka instance: prefer-ip-address: true
Write routing rules
You need to use the gateway to proxy the user service. First look at the service status in the control panel:
ip: 127.0.0.1
Port: 9091
Modify the Heima gateway \ SRC \ main \ resources \ application.yml file to:
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
All requests that conform to the Path rule are proxied to the address specified by the uri parameter. In this example, we proxy requests starting with / user / * * in the Path to http://127.0.0.1:9091
Start test
The mapping path of the configuration rule needs to be added to the access path. We access: http://localhost:10010/user/8
Service oriented routing
In the routing rule just now, the service address corresponding to the path is written dead! This is obviously unreasonable if there are multiple instances of the same service.
According to the name of the service, go to Eureka registry to find the list of all instances corresponding to the service, and then conduct dynamic routing!
Modify the mapping configuration and obtain the mapping information through the service name
Because the Eureka client has been configured, you can obtain the address information of the service from Eureka.
Modify the Heima gateway \ SRC \ main \ resources \ application.yml file as follows:
server: port: 10010 spring: application: name: api-gateway cloud: gateway: routes: #Routing id, which can be customized - id: user-service-route # The service address of the agent, lb indicates the specific service obtained from eureka # When the protocol used for uri in routing configuration is lb (take uri: LB: / / user service as an example), gateway will use LoadBalancerClient to # The user service is parsed into the actual host and port through eureka, and the ribbon load is balanced. uri: lb://user-service # uri: http://127.0.0.1:9091 # Route assertion, you can configure the mapping path predicates: - Path=/** eureka: client: service-url: defaultZone: http://127.0.0.1:10086/eureka instance: prefer-ip-address: true
- When the protocol used in the uri in the routing configuration is lb (take uri: LB: / / user service as an example), the gateway will use the LoadBalancerClient to parse the user service into the actual host and port through eureka, and carry out ribbon load balancing.
Start test
Start Heima gateway again. This time, when the gateway acts as an agent, it will use the Ribbon for load balancing access:
Routing prefix
add prefix
In the gateway, you can add the address in the mapping path by configuring the filter PrefixPath of the route;
Modify the Heima gateway \ SRC \ main \ resources \ application.yml file:
server: port: 10010 spring: application: name: api-gateway cloud: gateway: routes: #Routing id, which can be customized - id: user-service-route # The service address of the agent, lb indicates the specific service obtained from eureka # When the protocol used for uri in routing configuration is lb (take uri: LB: / / user service as an example), gateway will use LoadBalancerClient to # The user service is parsed into the actual host and port through eureka, and the ribbon load is balanced. uri: lb://user-service # uri: http://127.0.0.1:9091 # Route assertion, you can configure the mapping path predicates: - Path=/** filters: # Add prefix to request path - PrefixPath=/user eureka: client: service-url: defaultZone: http://127.0.0.1:10086/eureka instance: prefer-ip-address: true
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
Remove prefix
In the gateway, the address in the mapping path can be removed by configuring the route filter StripPrefix;
Modify the Heima gateway \ SRC \ main \ resources \ application.yml file:
server: port: 10010 spring: application: name: api-gateway cloud: gateway: routes: #Routing id, which can be customized - id: user-service-route # The service address of the agent, lb indicates the specific service obtained from eureka # When the protocol used for uri in routing configuration is lb (take uri: LB: / / user service as an example), gateway will use LoadBalancerClient to # The user service is parsed into the actual host and port through eureka, and the ribbon load is balanced. uri: lb://user-service # uri: http://127.0.0.1:9091 # Route assertion, you can configure the mapping path predicates: - Path=/** filters: # It means filtering 1 path, 2 means two paths, and so on - StripPrefix=1 eureka: client: service-url: defaultZone: http://127.0.0.1:10086/eureka instance: prefer-ip-address: true
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
and so on.
filter
brief introduction
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.
The functions in the previous routing prefix chapter are also implemented using filters.
- The Gateway has dozens of built-in filters, and the common built-in filters are:
See the official website for details
Configure global default filters
These built-in filters can be similar to the usage in the section using route prefix, or they can be configured not only for a route; Instead, it can take effect for all routes, that is, configure the default filter:
Understand the following:
server: port: 10010 spring: application: name: api-gateway cloud: gateway: #Default filter, effective for all routes default-filters: # The response header filter sets the header attribute name of the output response as X-Response-Default-MyName and the value as itcast; # If there are multiple parameters, override one line to set different parameters - AddResponseHeader=X-Response-Default-MyName, itcast routes: #Routing id, which can be customized - id: user-service-route # The service address of the agent, lb indicates the specific service obtained from eureka # When the protocol used for uri in routing configuration is lb (take uri: LB: / / user service as an example), gateway will use LoadBalancerClient to # The user service is parsed into the actual host and port through eureka, and the ribbon load is balanced. uri: lb://user-service # uri: http://127.0.0.1:9091 # Route assertion, you can configure the mapping path predicates: - Path=/** filters: # Add the prefix of the requested path and the final actual address of the browser address bar # PrefixPath=/user http://localhost:10010/8 -->http://localhost:9091/user/8 # PrefixPath=/user/abc http://localhost:10010/8 -->http://localhost:9091/user/abc/8 # - PrefixPath=/user # It means filtering 1 path, 2 means two paths, and so on # 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: the final actual address of the browser address bar # 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 - StripPrefix=1 - MyParam=name eureka: client: service-url: defaultZone: http://127.0.0.1:10086/eureka instance: prefer-ip-address: true
After adding the above global filter, you can see it in the corresponding header
- Filter type: there are two types of filters in Gateway implementation;
- Local filter: configured through spring.cloud.gateway.routes.filters under specific routes and only works on the current route; The built-in filter can be configured or customized according to the built-in filter. If spring.cloud.gateway.default-filters is configured, it will take effect for all routes, which is also regarded as a global filter; However, the implementation of these filters is to implement the GatewayFilterFactory interface.
- Global filter: it does not need to be configured in the configuration file and acts on all routes; Just implement the GlobalFilter interface.
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 gateway filterchain of the filter.
Usage scenario
Common application scenarios are as follows:
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 filter
Custom local filter
Requirement: configure a filter for a route in application.yml. The filter can specify the value of the request parameter with the name in the console output configuration file.
1) Write filter
- Note: the name of the custom filter should be * * * GatewayFilterFactory
package com.heima.gateway.filter; import org.springframework.cloud.gateway.filter.GatewayFilter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.OrderedGatewayFilter; import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; import java.lang.reflect.Array; import java.util.Arrays; import java.util.List; /** * @ClassName MyParamGatewayFilterFactory * @Description The value of the request parameter with the specified name in the console output configuration file. * @Author He Zhanhong * @Date 2021/10/2 11:54 * @Version 1.0.0 */ @Component public class MyParamGatewayFilterFactory extends AbstractGatewayFilterFactory<MyParamGatewayFilterFactory.Config> { public static final String PARAM_NAME = "param"; public MyParamGatewayFilterFactory() { super(Config.class); } @Override public List<String> shortcutFieldOrder() { return Arrays.asList(PARAM_NAME); } @Override public GatewayFilter apply(MyParamGatewayFilterFactory.Config config) { return new GatewayFilter() { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { //Get the value corresponding to param in the request parameter ServerHttpRequest request = exchange.getRequest(); if (request.getQueryParams().containsKey(config.param)){ //Gets the value of param request.getQueryParams().get(config.param) .forEach(value -> System.out.printf("----Local filter------%s = %s",config.param,value)); } //Continue with other filters return chain.filter(exchange); } }; } public static class Config { //Corresponds to the parameter name specified when configuring the filter private String param; public String getParam() { return param; } public void setParam(String param) { this.param = param; } } }
2) Modify profile
Modify the heimagateway\src\main\resources\application.yml configuration file in the Heima Gateway project
server: port: 10010 spring: application: name: api-gateway cloud: gateway: #Default filter, effective for all routes default-filters: # The response header filter sets the header attribute name of the output response as X-Response-Default-MyName and the value as itcast; # If there are multiple parameters, override one line to set different parameters - AddResponseHeader=X-Response-Default-MyName, itcast routes: #Routing id, which can be customized - id: user-service-route # The service address of the agent, lb indicates the specific service obtained from eureka # When the protocol used for uri in routing configuration is lb (take uri: LB: / / user service as an example), gateway will use LoadBalancerClient to # The user service is parsed into the actual host and port through eureka, and the ribbon load is balanced. uri: lb://user-service # uri: http://127.0.0.1:9091 # Route assertion, you can configure the mapping path predicates: - Path=/** filters: # Add the prefix of the requested path and the final actual address of the browser address bar # PrefixPath=/user http://localhost:10010/8 -->http://localhost:9091/user/8 # PrefixPath=/user/abc http://localhost:10010/8 -->http://localhost:9091/user/abc/8 # - PrefixPath=/user # It means filtering 1 path, 2 means two paths, and so on # 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: the final actual address of the browser address bar # 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 - StripPrefix=1 # Custom filter - MyParam=name # Address cross domain access issues globalcors: corsConfigurations: '[/**]': #allowedOrigins: * # This way of writing or the following can be used, * means all allowedOrigins: - "http://docs.spring.io" allowedMethods: - GET eureka: client: service-url: defaultZone: http://127.0.0.1:10086/eureka instance: prefer-ip-address: true
Test access: http://localhost:10010/api/user/8?name=itcast check whether the background outputs name and itcast; But if you visit
http://localhost:10010/api/user/8?name2=itcast will not be output.
Custom global filter
Requirement: simulate the verification of a login. Basic logic: if there is a token parameter in the request, the request is considered valid and released.
Write the global filter class MyGlobalFilter in the Heima Gateway project
package com.heima.gateway.filter; import org.apache.commons.lang.StringUtils; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.http.HttpStatus; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; /** * @ClassName MyGlobalFilter * @Description Custom global filter * @Author He Zhanhong * @Date 2021/10/2 13:45 * @Version 1.0.0 */ @Component public class MyGlobalFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { System.out.println("---------Global filter----------"); ServerHttpRequest request = exchange.getRequest(); String token = request.getQueryParams().getFirst("token"); //Judge whether the token exists if (StringUtils.isBlank(token)){ //Set the response status code to unauthorized exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); //Return directly and do not continue to execute the subsequent filtering requests return exchange.getResponse().setComplete(); } //If normal, release return chain.filter(exchange); } @Override public int getOrder() { //The lower the filter execution priority, the higher the priority return 1; } }
Do not carry token parameter:
Carry token parameters:
Load balancing and fusing (understand)
By default, Ribbon load balancing and Hystrix fuse mechanism have been integrated in the Gateway. However, all timeout policies are the default values. For example, the fuse timeout is only 1S, which is easy to trigger. Therefore, it is recommended to configure manually:
# The Gateway also integrates hystrix and ribbon to modify its configuration hystrix: command: default: execution: isolation: thread: timeoutInMilliseconds: 6000 ribbon: ConnectTimeout: 1000 ReadTimeout: 2000 MaxAutoRetries: 0 MaxAutoRetriesNextServer: 0
Gateway cross domain configuration
Generally, the gateway is the unified entrance of all micro services, and cross domain problems will inevitably occur when called.
Cross domain: in js request access, if the access address is inconsistent with the domain name, ip or port number of the current server, it is called cross domain request. If it is not solved, the return result of the corresponding address cannot be obtained.
For example, from http://localhost:9090 js access in http://localhost:9000 Because the ports are different, the data is also a cross domain request.
If there is a cross domain problem when accessing the Spring Cloud Gateway server; You can configure the gateway server to determine which services can be requested across domains; The specific configuration is as follows:
server: port: 10010 spring: application: name: api-gateway cloud: gateway: #Default filter, effective for all routes default-filters: # The response header filter sets the header attribute name of the output response as X-Response-Default-MyName and the value as itcast; # If there are multiple parameters, override one line to set different parameters - AddResponseHeader=X-Response-Default-MyName, itcast routes: #Routing id, which can be customized - id: user-service-route # The service address of the agent, lb indicates the specific service obtained from eureka # When the protocol used for uri in routing configuration is lb (take uri: LB: / / user service as an example), gateway will use LoadBalancerClient to # The user service is parsed into the actual host and port through eureka, and the ribbon load is balanced. uri: lb://user-service # uri: http://127.0.0.1:9091 # Route assertion, you can configure the mapping path predicates: - Path=/** filters: # Add the prefix of the requested path and the final actual address of the browser address bar # PrefixPath=/user http://localhost:10010/8 -->http://localhost:9091/user/8 # PrefixPath=/user/abc http://localhost:10010/8 -->http://localhost:9091/user/abc/8 # - PrefixPath=/user # It means filtering 1 path, 2 means two paths, and so on # 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: the final actual address of the browser address bar # 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 - StripPrefix=1 # Custom filter - MyParam=name # Address cross domain access issues globalcors: corsConfigurations: '[/**]': #allowedOrigins: * # This way of writing or the following can be used, * means all allowedOrigins: - "http://docs.spring.io" allowedMethods: - GET eureka: client: service-url: defaultZone: http://127.0.0.1:10086/eureka instance: prefer-ip-address: true # The Gateway also integrates hystrix and ribbon to modify its configuration hystrix: command: default: execution: isolation: thread: timeoutInMilliseconds: 6000 ribbon: ConnectTimeout: 1000 ReadTimeout: 2000 MaxAutoRetries: 0 MaxAutoRetriesNextServer: 0
The above configuration indicates that it is allowed to http://docs.spring.io Get service data by get request.
allowedOrigins specifies the server address allowed to access, such as: http://localhost:10000 It's OK.
'[/ * *]' indicates the address of all requests to access the gateway server
Specific instructions on the official website
Gateway high availability (learn)
Start multiple Gateway services and automatically register with Eureka to form a cluster. In case of internal service access, access the Gateway and automatic load balancing. No problem.
However, the Gateway is more external access, such as PC terminal, mobile terminal, etc. They can't load balance through Eureka, so what should I do?
At this time, other service gateways can be used to proxy the Gateway. For example: Nginx
Difference between Gateway and Feign
- As the traffic entrance of the whole application, the Gateway receives all requests, such as PC and mobile terminal, and forwards different requests to different processing micro service modules, which can be regarded as nginx; In most cases, it is used for permission authentication and server-side flow control
- Feign exposes some service interfaces of the current microservices and is mainly used for service calls between microservices