Table of contents
1. Introduction to Microservice Gateway
2. Gateway gateway introduction
3. Introduction to Spring Cloud Gateway
4.1.1 Import maven dependencies
4.1.3 Start the service and test
4.2.1 Introducing nacos dependencies
4.2.2 Modify configuration file
4.3 Integrate nacos automatic service discovery
5. Gateway routing assertion factory
5.1 Common routing assertion factories
5.1.1 Assertion factory based on Datetime type
5.1.2 Assertion factories based on remote addresses
5.1.4 Header-based assertion factory
5.1.5 Host-based assertion factory
5.1.6 Assertion factory based on Method request method
5.1.7 Assertion factory based on Path request path
5.1.8 Assertion factory based on Query request parameters
5.1.9 Assertion factory based on route weight
5.2 Routing assertion factory use
5.2.3 Query request parameter assertion
5.3 Custom route assertion factory
5.3.1 Custom routing assertion factory class
5.3.2 Configure custom classes to configuration files
6.1.2 Use of request header parameters
6.2.2 Modify configuration file
6.3.2 Global filter classification
7. Gateway cross-domain settings
7.1.1 Modify configuration file
Eight, written at the end of the text
1. Introduction to Microservice Gateway
In a mature and stable microservice architecture, in order to protect the security of the back-end interface and avoid exposing the real interface address, usually before the request reaches the interface, it will go through a layer of service called "gateway", proxy and forward through the gateway, and then To the backend, that's what the gateway does. For example, familiar nginx, gateway, zuul, etc. can be said to be used in the products of Internet companies. What are the functions of gateways?
1.1 The role of the gateway
It can be said that the gateway plays a very important role in a system:
- Hide the real API address from the outside world to protect the security of API resources;
- Identify and intercept malicious requests, filter and audit requests in advance;
- The bearer traffic entrance forwards the requested traffic according to the system load;
1.2 Common gateways
As the microservice architecture becomes more and more common, gateways play an increasingly important role in the rectification architecture. With the rise of cloud native and large-scale implementation, various new types of gateways have gradually begun to appear.
1.2.1 Traditional Gateway
Under the springcloud microservice system, traditional gateways can still be considered, as follows:
- nginx;
- zul;
- gateway;
1.2.2 Cloud Native Gateway
With the large-scale application of k8s, some related gateways have also begun to appear, such as:
- ingress;
- istio(envoy);
- api gateway;
- kong;
- apisix...
2. Gateway gateway introduction
2.1 Origin of the problem
In the microservice architecture, a system is split into many microservices. So how to call so many microservices as a client? If there is no gateway, we can only record the address of each microservice on the client and use it separately.
2.2 Issues raised
There are many problems with the above structure:
2.2.1 Reinventing the wheel
Each business needs to carry out logic such as authentication, current limiting, authority verification, cross-domain, etc. independently, and each business is fighting on its own, making its own wheels to achieve it;
2.2.2 Call inefficiency
If the business volume is relatively simple, there will be no problem for the time being. As the business becomes more and more complex, a complex page may involve hundreds of microservices working together. If each microservice is assigned a domain name, On the one hand, the client code will be difficult to maintain, involving hundreds of domain names. On the other hand, it is the bottleneck of the number of connections. Imagine that you open an app and find that hundreds of remote calls are involved through packet capture. would be very inefficient;
2.2.3 Complex Refactoring
If you need to refactor microservices in the later stage, it will also become very troublesome. You need the client to cooperate with you in the transformation, such as commodity services. As the business becomes more and more complex, it needs to be split into multiple microservices later. Services, at this time, the services provided to the outside world also need to be split into multiple parts, and at the same time, the client needs to cooperate with you in the transformation, which is very painful;
2.3 gateway improvement
For the above problems, API gateway can be used to solve them
The so-called API gateway refers to the unified entrance of the system. It encapsulates the internal structure of the application program and provides unified services for the client. Some public logic that has nothing to do with the functions of the business itself can be implemented here, such as authentication, authentication, monitoring, and routing. Retweet and more.
After adding the API gateway, the architecture diagram of the system becomes as follows
3. Introduction to Spring Cloud Gateway
3.1 Gateway overview
- It is the second-generation gateway framework officially launched by Spring Cloud, positioned to replace Netflix Zuul1.0. Compared with Zuul, Spring Cloud Gateway provides better performance and more powerful functions;
- It is a responsive API gateway implemented by WebFlux + Netty + Reactor. It doesn't work in a traditional servlet container, nor can it be built into a war package;
- It aims to provide a simple and effective API routing management method for the microservice architecture, and provide the basic functions of the gateway based on the Filter method, such as security authentication, monitoring, current limiting, etc.;
3.2 Gateway features
Compared with the first generation gateway zuul, Gateway provides rich and powerful functions;
1) Build based on Spring Framework 5, Project Reactor and Spring Boot 2.0;
2) Dynamic routing: able to match any request attribute;
3) Support path rewriting;
4) Integrate Spring Cloud service discovery function (Nacos, Eureka);
5) Flow control downgrade function (Sentinel, Hystrix) can be integrated;
6) You can specify easy-to-write Predicate (assertion) and Filter (filter) for routing;
3.3 Gateway core concept
3.3.1 Routing (route)
Routing is the most basic part of a gateway. Routing information includes an ID, a destination URI, a set of assertion factories, and a set of Filters. If the assertion is true, the requested URL matches the configured route.
3.3.2 predicates
The assertion function in Java8, the assertion function type in SpringCloud Gateway is ServerWebExchange in the Spring5.0 framework. The assertion function allows developers to define any information that matches the Http request, such as request headers and parameters.
3.3.3 Filter
The filters in SpringCloud Gateway are divided into Gateway FilIer and Global Filter. Filter can process requests and responses.
3.4 Gateway working principle
According to the above figure, the workflow of the gateway is roughly as follows:
- Gateway Client sends a request to Gateway Server;
- The request will first be extracted and assembled into a gateway context by the HttpWebHandlerAdapter;
- Then the context of the gateway will be passed to DispatcherHandler, which is responsible for dispatching the request to RoutePredicateHandlerMapping;
- RoutePredicateHandlerMapping is responsible for route lookup, and judges whether the route is available according to the route assertion;
- If the assertion succeeds, the filter chain is created and called by FilteringWebHandler;
- The request will go through the PreFilter--microservice--PostFilter method once, and finally return the response;
4. Quick use of Gateway
Next, quickly experience the use of gateway through a case
4.1 Operation steps
4.1.1 Import maven dependencies
To create a new project, you only need to import this dependency
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
4.1.2 Add configuration file
Refer to the comments in the configuration file for understanding. The core of the gateway function lies in the use of the configuration file, which can flexibly control routing through declarative configuration;
server:
port: 8088
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
#当前路由的唯一标识,路由到哪个服务上面去
- id: order-route
uri: http://localhost:8083
predicates:
#即所有以order-serv开头的请求都转发到这个微服务处理
- Path=/order-serv/**
filters:
#访问的时候,Gateway会自动的把order-serv过滤掉,从而转发到对应微服务的正确路径上
#比如客户端访问的是 http://localhost:8088/order-serv/order/add,通过gateway之后实际访问的是http://localhost:8088/order/add
- StripPrefix=1
4.1.3 Start the service and test
@SpringBootApplication
public class GatewayApp01 {
public static void main(String[] args) {
SpringApplication.run(GatewayApp01.class,args);
}
}
Before starting the order module and stock module, there is an /order/add interface in the order module. According to the above configuration, our access needs to be forwarded by the gateway, so the complete request address is: http://localhost:8088/ order -serv/order/add , if accessing this address can have the same effect as accessing: http://localhost:8083/order/add , it means that the configuration of the gateway has taken effect, and the effect of the browser access interface is as follows:
4.2 Integrate nacos
In the above configuration file, it can be found that the address of the gateway forwarding path is directly written in the configuration file. This method is not standardized and will cause many problems. The correct and reasonable way is to forward through the specified service name. Next, use nacos as the registration center to obtain this address from the registration center;
4.2.1 Introducing nacos dependencies
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
4.2.2 Modify configuration file
There are two main points, one is to add the address of nacos, but to change the forwarded uri address to the service name on nacos
server:
port: 8088
spring:
application:
name: api-gateway
# nacos注册中心地址
cloud:
nacos:
discovery:
server-addr: localhost:8848 #服务注册中心地址
gateway:
routes:
#当前路由的唯一标识,路由到哪个服务上面去
- id: order-route
uri: lb://order-service #需要转发的服务地址,nacos上注册的那个服务地址
predicates:
#即所有以order-serv开头的请求都转发到这个微服务处理
- Path=/order-serv/**
filters:
#访问的时候,Gateway会自动的把pay过滤掉,从而转发到对应微服务的正确路径上
#比如客户端访问的是 http://localhost:8088/order-serv/order/add,实际访问的是http://localhost:8088/order/add
- StripPrefix=1
4.2.3 Effect Test
After starting the services of several modules, call the same interface again, which is consistent with the above effect
4.3 Integrate nacos automatic service discovery
Based on the integration of nacos, the configuration file of the gateway can be further simplified as follows. Through this configuration, when the request address is: /order-service/order/add interface, it will automatically go to nacos to find out whether there is such a service exist;
server:
port: 8088
spring:
application:
name: api-gateway
# nacos注册中心地址
cloud:
nacos:
discovery:
server-addr: localhost:8848 #服务注册中心地址
gateway:
discovery:
locator:
enabled: true #是否启动自动发现nacos上面的服务
After starting the service and testing again, the correct return result can still be obtained;
5. Gateway routing assertion factory
Gateway provides the configuration of the routing assertion factory, which makes the processing of requests richer and more flexible. Developers only need to set some rules in the configuration file according to the business scenario. Spring Cloud Gateway includes a number of built-in assertion factories, all of which match different attributes of HTTP requests, as follows:
5.1 Common routing assertion factories
5.1.1 Assertion factory based on Datetime type
This type of assertion is judged based on time, and there are three main types:
- AfterRoutePredicateFactory: Receive a date parameter to determine whether the requested date is later than the specified date;
- BeforeRoutePredicateFactory: Receive a date parameter to determine whether the requested date is earlier than the specified date;
- BetweenRoutePredicateFactory: Receive two date parameters to determine whether the requested date is within the specified time period
‐ After=2022‐12‐29T23:59:59.789+08:00[Asia/Shanghai]
5.1.2 Assertion factories based on remote addresses
RemoteAddrRoutePredicateFactory: Receive an IP address segment and determine whether the requesting host address is in the address segment
‐ RemoteAddr=192.168.1.1/24
5.1.3 Cookie-based assertion factory
CookieRoutePredicateFactory: Receives two parameters, the cookie name and a regular expression. Determine if the request cookie has the given name and the value matches the regular expression
‐Cookie=china, ch
5.1.4 Header-based assertion factory
HeaderRoutePredicateFactory: Receives two parameters, header name and regular expression. Determine whether the request header has the given name and the value matches the regular expression
‐Header=X‐Request‐Id, \d+
5.1.5 Host-based assertion factory
HostRoutePredicateFactory: Receives one parameter, the host name pattern. Determine whether the requested Host meets the matching rules
‐Host=**.testhost.org
5.1.6 Assertion factory based on Method request method
MethodRoutePredicateFactory: Receive a parameter to determine whether the request type matches the specified type
‐ Method = GET
5.1.7 Assertion factory based on Path request path
PathRoutePredicateFactory: Receive a parameter to determine whether the URI part of the request satisfies the path rules
‐Path=/foo/{segment}
5.1.8 Assertion factory based on Query request parameters
QueryRoutePredicateFactory : Receive two parameters, request param and regular expression, determine whether the request parameter has the given name and the value matches the regular expression
‐Query=baz, ba.
5.1.9 Assertion factory based on route weight
WeightRoutePredicateFactory: Receive a [group name, weight], and then forward the routes in the same group according to the weight
routes:
‐id: weight_route1
uri: host1
predicates:
‐Path=/product/**
‐Weight=group3, 1
‐id: weight_route2
uri: host2
predicates:
‐Path=/product/**
‐Weight= group3, 9
5.2 Routing assertion factory use
5.2.1 Time Assertions
Add the following configuration file, which means that under the premise of satisfying the routing and forwarding rules, the time needs to be after the configured time;
server:
port: 8088
spring:
application:
name: api-gateway
# nacos注册中心地址
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
routes:
- id: order-route
uri: lb://order-service
predicates:
- Path=/order/**
- After=2022-12-29T23:59:59.789+08:00[Asia/Shanghai]
Start again and access the interface, see the following effect
5.2.2 header assertion
Add the following configuration, which means that the request header also needs to carry a parameter whose key is username and value is jerry
server:
port: 8088
spring:
application:
name: api-gateway
# nacos注册中心地址
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
routes:
- id: order-route
uri: lb://order-service
predicates:
- Path=/order/**
- After=2022-12-29T23:59:59.789+08:00[Asia/Shanghai]
- Header=username,jerry
Initiate a request through postman, you can see the following effect
If the parameters in the header are removed or written incorrectly, 404 will appear;
5.2.3 Query request parameter assertion
Add the following configuration, that is, the request must carry the name parameter
server:
port: 8088
spring:
application:
name: api-gateway
# nacos注册中心地址
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
routes:
- id: order-route
uri: lb://order-service
predicates:
- Path=/order/**
- After=2022-12-29T23:59:59.789+08:00[Asia/Shanghai]
#- Header=username,jerry
- Query=name
Request the interface again, if you do not carry the name, you will see the request 404
after carrying name
5.3 Custom route assertion factory
If the built-in routing assertion factory still cannot meet your individual needs, you can consider customizing the routing assertion factory.
The custom routing assertion factory needs to inherit the AbstractRoutePredicateFactory class and rewrite the logic of the apply method. In the apply method, you can get the ServerHttpRequest object through exchange.getRequest(), so that you can get the requested parameters, request method, request header and other information.
Points to note for custom routing assertion factories:
- Must be a spring component bean;
- The class must end with RoutePredicateFactory;
- AbstractRoutePredicateFactory must be inherited;
- A static inner class must be declared, and properties must be declared to receive the information of the corresponding assertion in the configuration file;
- It needs to be bound with shortcutFieldOrder;
- Make a logical judgment through apply, true means the match is successful, and false means the match fails;
5.3.1 Custom routing assertion factory class
@Component
public class CheckAuthRoutePredicateFactory extends AbstractRoutePredicateFactory<CheckAuthRoutePredicateFactory.Config> {
public CheckAuthRoutePredicateFactory() {
super(CheckAuthRoutePredicateFactory.Config.class);
}
public List<String> shortcutFieldOrder() {
return Arrays.asList("name");
}
public Predicate<ServerWebExchange> apply(CheckAuthRoutePredicateFactory.Config config) {
return new GatewayPredicate() {
public boolean test(ServerWebExchange exchange) {
if(config.getName().equals("hello")){
return true;
}
return false;
}
};
}
//接受配置文件中中的参数
@Validated
@Data
public static class Config {
private String name;
}
}
5.3.2 Configure custom classes to configuration files
5.3.3 Effect Test
After starting the related module service, call the interface again, and you can see the following effect
The above shows that the parameters in the configuration file can be routed normally after matching the assertion factory. If the parameters in the configuration file are modified
Test the interface again, you can see the following effect
6. Gateway filter factory
From the execution flow chart of gateway at the beginning of the article, we can see that Gateway has many built-in filter factories. We can perform some business logic processors through some filter factories, such as adding and removing response headers, adding and removing parameters, etc., and gateway filtering Detailed description of the filter: gateway filter description
The existence and use of filters can control the source requests more carefully, so as to achieve the purpose of protecting the server interface resources.
6.1 Gateway filter use
6.1.1 Request header usage
Function: Add Header for the original request, corresponding filter factory: AddRequestHeader, modify the configuration file
server:
port: 8088
spring:
application:
name: api-gateway
# nacos注册中心地址
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
routes:
- id: order-route
uri: lb://order-service
predicates:
- Path=/order/**
- After=2022-12-29T23:59:59.789+08:00[Asia/Shanghai]
#- Header=username,jerry
#- Query=name
#- CheckAuth=jerry
filters:
- AddRequestHeader=X-Request-color,red
Add the following test interface to OrderController
@GetMapping("/header")
public String header(@RequestHeader("X-Request-color") String color){
return color;
}
Browser request interface, you can see the following effect, indicating that the request forwarded from the gateway has the parameter red;
6.1.2 Use of request header parameters
Add the following configuration parameters
Add a test interface to OrderController
@GetMapping("/request-param")
public String testRequestParam(@RequestParam("color")String color) throws Exception {
logger.info("获取请求参数:" + color);
return color;
}
Test the interface, you can see the following effects
6.2 Since
6.2 Custom Filter Factory
In some cases, if the built-in gateway filter does not meet the requirements, you can consider custom filters, which are relatively simple to use, custom classes, and inherit AbstractNameValueGatewayFilterFactory, and the custom class name must end with GatewayFilterFactory and Hand over to spring management;
6.2.1 Custom filter class
@Component
public class CheckAuthGatewayFilterFactory extends AbstractGatewayFilterFactory<CheckAuthGatewayFilterFactory.Config> {
public CheckAuthGatewayFilterFactory() {
super(CheckAuthGatewayFilterFactory.Config.class);
}
public List<String> shortcutFieldOrder() {
return Arrays.asList("name");
}
public GatewayFilter apply(CheckAuthGatewayFilterFactory.Config config) {
return (exchange, chain) -> {
String paramValue = exchange.getRequest().getQueryParams().getFirst("name");
if (StringUtils.isNotEmpty(paramValue) && paramValue.equals("jerry")) {
return chain.filter(exchange);
} else {
exchange.getResponse().setStatusCode(HttpStatus.NOT_FOUND);
return exchange.getResponse().setComplete();
}
};
}
@Data
public static class Config {
private String name;
}
}
6.2.2 Modify configuration file
6.2.3 Interface Test
Start the related module service, call the /order/add interface through the gateway, if the name parameter is passed in and the value is correct
If the value is incorrect, the following effect will appear
6.3 Global Filters
The above filters can be considered as partial filters according to the classification. The local filter needs to be configured in the route for a certain route. However, if there are many routes that need to be controlled in the actual business, it is necessary to write a lot of local filters. Filters, especially those scenes that have the same need to be filtered, are redundant. At this time, you can consider using global filters
6.3.1 Overview
For all routing requests, once defined, it will take effect globally. The GlobalFilter interface has the same interface definition as GatewayFilter, but GlobalFilter will act on all routes.
6.3.2 Global filter classification
The following lists the official and commonly used gateway global filters
6.3.3 Global filter usage
Customize a class to implement the GlobalFilter interface
@Component
@Slf4j
public class LogFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info(exchange.getRequest().getPath().value());
return chain.filter(exchange);
}
}
6.3.4 Interface Test
After starting the relevant module services, access the above interface, you can see that the console outputs the requested path information;
7. Gateway cross-domain settings
The concept of crossing is familiar to many students. There are many solutions to cross domains. For example, setting in nginx is a relatively common one. Gateway also provides solutions to cross domains.
7.1 Operation process
Official document: gateway cross-domain configuration manual
7.1.1 Modify configuration file
Add cross-domain related configuration information
server:
port: 8088
spring:
application:
name: api-gateway
# nacos注册中心地址
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
# ----------- 跨域相关的配置
globalcors:
cors-configurations:
'[/**]': #拦截的请求
allowedOrigins: #允许跨域的请求来源
- "http://localhost:8080"
allowedMethods: #运行跨域的请求方式
- "GET"
- "POST"
routes:
- id: order-route
uri: lb://order-service
predicates:
- Path=/order/**
- After=2022-12-29T23:59:59.789+08:00[Asia/Shanghai]
#- Header=username,jerry
#- Query=name
#- CheckAuth=jerry
filters:
#- AddRequestHeader=X-Request-color,red
#- AddRequestParameter=color,blue
- CheckAuth=name,jerry
Eight, written at the end of the text
This article explains the use of gateway in detail in a large space. For more information about the use of gateway, you can refer to the official website documents for learning, such as using gateway for unified authentication, current limiting, etc., as an excellent programmable service gateway , it is necessary to study and understand it in depth before it can be used reasonably in the design of the architecture.