GateWay
API gateway refers to the unified entrance of the system. It encapsulates the internal structure of the application 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, routing and forwarding etc.
Official document address : https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/
Examples of functions that can be realized by the API gateway:
- Focus on Stability and Security
- global flow control
- log statistics
- Prevent SQL injection
- Prevent web attacks
- Mask tool scan
- Black and white IP list
- Certificate/encryption and decryption processing
- provide better service
- service level flow control
- Service downgrade and circuit breaker
- Routing and load balancing, grayscale strategy
- Service filtering, aggregation and discovery
- Authorization Verification and User Level Policies
- Business rules and parameter validation
- multi-level caching strategy
Spring Cloud Gateway is the second-generation gateway framework officially launched by Spring Cloud, which is positioned to replace Netflix Zuul1.0. Compared with Zuul, Spring Cloud Gateway provides better performance and more powerful functions.
Spring Cloud Gateway 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.
Spring Cloud Gateway aims to provide a simple and effective API routing management method for the microservice architecture, and provides basic functions of the gateway based on Filter, such as security authentication, monitoring, current limiting, and so on.
Features
- Built on Spring Framework 5, Project Reactor and Spring Boot 2.0
- Dynamic routing: able to match any request attribute
- Support path rewriting
- Integrate Spring Cloud service discovery function (Nacos, Eruka)
- Can integrate flow control downgrade function (Sentinel, Hystrix)
- Easy-to-write Predicate (assertion) and Filter (filter) can be specified on the route
Core idea
- Routing (route) Routing is the most basic part of the 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.
- Assertion (predicates) The assertion function in Java8, the type of assertion function 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.
- Filter (Filter) The filter in SpringCloud Gateway is divided into Gateway FilIer and Global Filter. Filter can process requests and responses.
working principle
The execution process is as follows:
- Gateway Client sends a request to Gateway Server.
- The request will first be extracted by the HttpWebHandlerAdapter and assembled into a gateway context.
- The context of the gateway is then passed to the DispatcherHandler, which is responsible for dispatching the request to the 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.
First experience with GateWay
-
Build a SpringBoot project
-
import dependencies
#父工程中已经引入的 spring cloud 其他的依赖 <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </exclusion> </exclusions> </dependency>
-
add configuration file
server: port: 8088 spring: application: name: api-gateway cloud: # gateway的配置 gateway: # 路由规则 routes: - id: order_route # 路由的唯一标识,路由到order uri: http://localhost:8010 # 需要转发的地址 # 断言规则 用于路由规则的匹配 predicates: - Path=/order-serv/** # http://localhost:8088/order-serv/order/add 路由到 ↓ # http://localhost:8010/order-serv/order/add filters: - StripPrefix=1 # 转发之前去掉一级路径 order-serv # http://localhost:8010/order/add
-
Access configured rules via GateWay
GateWay integrates nacos
-
add dependencies
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>
-
Modify the configuration file
server: port: 8088 spring: application: name: api-gateway cloud: # gateway的配置 gateway: # 路由规则 routes: - id: order_route # 路由的唯一标识,路由到order uri: lb://order-service # 需要转发的地址 # lb是从nacos中按照名称获取服务,并遵循负载均衡策略 # 断言规则 用于路由规则的匹配 predicates: - Path=/order-serv/** # http://localhost:8088/order-serv/order/add 路由到 ↓ # http://localhost:8010/order-serv/order/add filters: - StripPrefix=1 # 转发之前去掉一级路径 order-serv # http://localhost:8010/order/add # 添加nacos配置信息 nacos: server-addr: 192.168.2.7:8848 discovery: username: nacos password: nacos namespace: public
Affirmation
When requesting the gateway, use the assertion to match the request, if the match is successful, the route will be forwarded, and if the match fails, 404 will be returned.
Built-in assertion factory
-
Assertion factory based on Datetime type
This type of assertion is judged according to time, there are three main types:-
AfterRoutePredicateFactory: Receive a date parameter to determine whether the requested date is later than the specified date
- After=2017-01-20T17:42:47.789-07:00[America/Denver]
-
BeforeRoutePredicateFactory: Receive a date parameter to determine whether the requested date is earlier than the specified date
- Before=2017-01-20T17:42:47.789-07:00[America/Denver]
-
BetweenRoutePredicateFactory: Receive two date parameters to determine whether the requested date is within the specified time period
- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]
-
-
The remote address-based assertion factory
RemoteAddrRoutePredicateFactory: receives an IP address segment and determines whether the requesting host address is in the address segment‐ RemoteAddr=192.168.1.1/24
-
Cookie-based assertion factory
CookieRoutePredicateFactory: Receives two parameters, cookie name and a regular expression. Judgment request. Whether the cookie has the given name and value matches the regular expression.‐Cookie=chocolate, ch.
-
Header-based assertion factory
HeaderRoutePredicateFactory: Receives two parameters, header name and regular expression. Determine if the request header has the given name and the value matches the regular expression.‐Header=X‐Request‐Id, \d+
-
Host-based assertion factory
HostRoutePredicateFactory: Receives a parameter, the host name pattern. Determine whether the requested Host meets the matching rules.‐Host=**.testhost.org
-
MethodRoutePredicateFactory , an assertion factory based on the Method request method
: receives a parameter to determine whether the request type matches the specified type.‐Method=GET
-
PathRoutePredicateFactory , an assertion factory based on the Path request path
: receives a parameter to determine whether the URI part of the request satisfies the path rule.‐Path=/foo/{ segment}
-
The assertion factory QueryRoutePredicateFactory based on Query request parameters
: receives two parameters, request param and regular expression, and judges whether the request parameter has the given name and the value matches the regular expression.‐Query=baz, ba.
-
WeightRoutePredicateFactory , an assertion factory based on route weight
: receives a [group name, weight], and then forwards 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
Custom Assertion Factory
- Custom assertion factories must be handed over to spring management
- The custom assertion factory class name must end with RoutePredicateFactory (the convention is greater than the configuration idea)
- Inherit the AbstractRoutePredicateFactory abstract class
- The custom assertion factory internally declares a static inner class, and the declaration attribute is used to receive the corresponding assertion information in the configuration file
- Data binding using the shortcutFieldOrder method
- Make logical judgments in applay
@Component
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config> {
public MyRoutePredicateFactory() {
super(Config.class);
}
public Predicate<ServerWebExchange> apply(Config config) {
return new GatewayPredicate() {
public boolean test(ServerWebExchange serverWebExchange) {
return config.getName().equals("zhangsan");
}
public String toString() {
return String.format("MyRoute: param=%s", config.getName());
}
};
}
public List<String> shortcutFieldOrder() {
return Collections.singletonList("name");
}
public static class Config{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
filter
built-in filter
Gateway has many built-in filter factories, through which we can perform some business logic processors, such as adding and removing response headers, adding and removing parameters, etc.
There are examples of filters on the official website, please refer to the official website
https://docs.spring.io/spring-cloud-gateway/docs/2.2.5.RELEASE/reference/html/#gatewayfilter-factories
filter factory | effect | parameter |
---|---|---|
AddRequestHeader | Add Header to the original request | Header name and value |
AddRequestParameter | Add request parameters to the original request | Parameter name and value |
AddResponseHeader | Add Header to raw response | Header name and value |
DedupeResponseHeader | Eliminate duplicate values in response headers | Header names and deduplication strategies that need to be deduplicated |
Hystrix | Introducing Hystrix's circuit breaker protection for routing | The name of the HystrixCommand |
FallbackHeaders | Add specific exception information to the request header of fallbackUri | Header name |
PrefixPath | Prefix the original request path | prefix path |
PreserveHostHeader | Add a preserveHostHeader=true attribute to the request, and the routing filter will check this attribute to decide whether to send the original Host | none |
RequestRateLimiter | Used to limit the flow of requests, the current limiting algorithm is token bucket | keyResolver、rateLimiter、statusCode、denyEmptyKey、emptyKeyStatus |
RedirectTo | Redirects the original request to the specified URL | http status code and redirected url |
RemoveHopByHopHeadersFilter | Delete a series of headers specified by the IETF organization for the original request | It is enabled by default, and you can specify which headers to delete only by configuration |
RemoveRequestHeader | Remove a header for the original request | Header name |
RemoveResponseHeader | Remove a header for the original response | Header name |
RewritePath | Rewrite the original request path | The original path regular expression and the regular expression of the rewritten path |
RewriteResponseHeader | Rewrite a Header in the original response | Header name, regular expression of value, rewritten value |
SaveSession | Force a WebSession::save operation before forwarding the request | none |
SecureHeaders | Add a series of security response headers to the original response | None, support modifying the value of these security response headers |
SetPath | Modify the original request path | modified path |
SetResponseHeader | Modify the value of a Header in the original response | Header name, modified value |
SetStatus | Modify the status code of the original response | HTTP status code, which can be a number or a string |
StripPrefix | The path used to truncate the original request | Use a number to indicate the number of paths to truncate |
Retry | Retry with a different response | retries、statuses、methods、series |
RequestSize | Sets the size of the largest request packet allowed to be received. If the request packet size exceeds the set value, return 413 Payload Too Large | Request packet size, the unit is byte, the default value is 5M |
ModifyRequestBody | Modify the original request body content before forwarding the request | Modified request body content |
ModifyResponseBody | Modify the content of the original response body | Modified response body content |
custom filter
The custom filter is similar to the previous custom assertion factory process.
The custom filter adds the response header, MyGatewayFilter: test filter
code show as below:
@Component
public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory<MyGatewayFilterFactory.MyConfig> {
public MyGatewayFilterFactory() {
super(MyGatewayFilterFactory.MyConfig.class);
}
@Override
public GatewayFilter apply(MyConfig config) {
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String name = exchange.getRequest().getQueryParams().getFirst("name");
if(StringUtils.isNotBlank(name)){
if (config.getValue().equals(name)){
exchange.getResponse().getHeaders().set("MyGatewayFilter","test filter");
return chain.filter(exchange);
}else{
exchange.getResponse().setStatusCode(HttpStatus.NOT_FOUND);
exchange.getResponse().setComplete();
}
}
//正常请求
return chain.filter(exchange);
}
};
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("value","key");
}
public static class MyConfig{
private String value;
private String key;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
}
}
The configuration file is as follows:
server:
port: 8088
spring:
application:
name: api-gateway
cloud:
gateway:
routes:
- id: order_route
uri: lb://order-service
predicates:
- Path=/order-serv/**
- My=zhangsan
filters:
- My=zhangsan
- StripPrefix=1
nacos:
server-addr: 192.168.2.7:8848
discovery:
username: nacos
password: nacos
namespace: public
View the effect:
global filter
The difference between local filters and global filters:
The GlobalFilter interface has the same interface definition as the GatewayFilter, but the GlobalFilter will act on all routes.
Local: For a certain route, it needs to be configured in the applied route.
Global: For all routing requests, once defined, it can take effect.
Gateway comes with a built-in global filter
custom global filter
Just implement the GlobalFilter interface;
@Component
public class MyGlobalLogFilter implements GlobalFilter {
Logger log = LoggerFactory.getLogger(this.getClass());
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("访问路径为{}",exchange.getRequest().getPath().value());
return chain.filter(exchange);
}
}
Gateway integrates sentinel
Gateway current limiting official document
-
add dependencies
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId> </dependency>
-
add configuration file
sentinel: transport: dashboard: 127.0.0.1:8080
-
Startup project, nacos, sentinel
-
View the effect
There are some differences between this console and the simple project integration sentinel page, and the large configuration is basically the same. Some flow control rules can refer to my sentinel notes