Article directory
Spring Cloud Gateway is a brand new project of Spring Cloud. The project is a gateway developed based on reactive programming and event flow technologies such as Spring 5.0, Spring Boot 2.0 and Project Reactor. It aims to provide a simple and effective unity for microservice architecture. API routing management method.
Why do you need a gateway
Gateway is the gatekeeper of our services, the unified entry for all microservices.
The core functional characteristics of the gateway :
- request routing
- Access control
- Limiting
Architecture diagram:
Permission control : The gateway, as the entrance to the microservice, needs to verify whether the user is eligible to request, and if not, intercept it.
Routing and load balancing : All requests must go through the gateway first, but the gateway does not process business, but forwards the request to a microservice according to certain rules. This process is called routing. Of course, when there are multiple target services for routing, load balancing is also required.
Current limit : When the request traffic is too high, the gateway will release the request according to the speed that the downstream microservice can accept to avoid excessive service pressure.
There are two types of gateway implementations in SpringCloud:
gateway
zuul
Zuul is a Servlet-based implementation and belongs to blocking programming. SpringCloudGateway is based on WebFlux provided in Spring5, which belongs to the implementation of reactive programming and has better performance.
gateway quick start
Next, we will demonstrate the basic routing function of the gateway. The basic steps are as follows:
- Create SpringBoot project gateway, introduce gateway dependencies
- Write a startup class
- Write basic configuration and routing rules
- Start the gateway service for testing
Create a gateway service and introduce dependencies
Create the service:
Import dependencies:
<!--网关-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--nacos服务发现依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
Write a startup class
package cn.itcast.gateway;
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);
}
}
Write basic configuration and routing rules
Create an application.yml file with the following content:
server:
port: 10010 # 网关端口
spring:
application:
name: gateway # 服务名称
cloud:
nacos:
server-addr: localhost:8848 # nacos地址
gateway:
routes: # 网关路由配置
- id: user-service # 路由id,自定义,只要唯一即可
# uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
uri: lb://userservice # 路由的目标地址 lb就是负载均衡,后面跟服务名称
predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
- Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求
We will Path
proxy all requests that meet the rules to the address specified by the uri
parameter .
In this example, we proxy the requests /user/**
starting with , lb://userservice
and lb is load balancing, and pull the service list according to the service name to achieve load balancing.
restart test
Restart the gateway, when accessing http://localhost:10010/user/1, the /user/**
rules are met, the request is forwarded to uri: http://userservice/user/1, and the result is obtained:
Flowchart of Gateway Routing
The entire visit process is as follows:
Summarize:
Gateway construction steps:
-
Create a project, introduce nacos service discovery and gateway dependencies
-
Configure application.yml, including basic service information, nacos address, routing
Routing configuration includes:
-
Route id: the unique identifier of the route
-
Routing target (uri): the target address of the route, http stands for fixed address, lb stands for load balancing based on service name
-
Routing assertions (predicates): rules for judging routing,
-
Routing filters (filters): processing requests or responses
Next we discuss the details of route assertions and route filters
assertion factory
The assertion rules we write in the configuration file are just strings, which are read and processed by the Predicate Factory and turned into conditions for routing judgment
For example, Path=/user/** is matched according to the path. This rule is defined by
org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory
class to handle, there are more than a dozen assertion factories like this in SpringCloudGateway:
name | illustrate | 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 a certain point 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 certain cookies | - Cookie=chocolate, ch.p |
Header | The request must contain certain headers | - Header=X-Request-Id, \d+ |
Host | The request must be to access a certain host (domain name) | - Host=.somehost.org,.anotherhost.org |
Method | The request method must be the specified method | - Method=GET,POST |
Path | The request path must conform to the specified rules | - Path=/red/{segment},/blue/** |
Query | Request parameters must contain the specified parameters | - Query=name, Jack or - Query=name |
RemoteAddr | The requester's ip must be in the specified range | - RemoteAddr=192.168.1.1/24 |
Weight | Weight handling |
filter factory
GatewayFilter is a filter provided in the gateway, which can process requests entering the gateway and responses returned by microservices:
Types of Route Filters
Spring provides 31 different route filter factories. E.g:
name | illustrate |
---|---|
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 | Removes a response header from the response result |
RequestRateLimiter | Limit requested traffic |
request header filter
Let's take AddRequestHeader as an example to explain.
Requirement : Add a request header to all requests to userservice: Truth=itcast is freaking awesome!
Just modify the application.yml file of the gateway service and add route filtering:
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://userservice
predicates:
- Path=/user/**
filters: # 过滤器
- AddRequestHeader=Truth, Itcast is freaking awesome! # 添加请求头
The current filter is written under the userservice route, so it is only valid for requests to access userservice.
default filter
If you want to take effect for all routes, you can write the filter factory under default. The format is as follows:
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://userservice
predicates:
- Path=/user/**
default-filters: # 默认过滤项
- AddRequestHeader=Truth, Itcast is freaking awesome!
Summarize
What does a filter do?
-
Process the routed request or response, such as adding request headers
-
The filter configured under the route only takes effect on the request of the current route
What is the role of defaultFilters?
- A filter that applies to all routes
global filter
For the filters we mentioned earlier, the gateway provides 31 types, but the role of each filter is fixed. If we want to intercept requests and do our own business logic, there is no way to achieve it.
global filter action
The role of the global filter is to process all requests and microservice responses entering the gateway, just like the GatewayFilter. The difference is that GatewayFilter is defined by configuration, and the processing logic is fixed; while the logic of GlobalFilter needs to be implemented by writing its own code.
It is defined by implementing the GlobalFilter interface.
public interface GlobalFilter {
/**
* 处理当前请求,有必要的话通过{@link GatewayFilterChain}将请求交给下一个过滤器处理
*
* @param exchange 请求上下文,里面可以获取Request、Response等信息
* @param chain 用来把请求委托给下一个过滤器
* @return {@code Mono<Void>} 返回标示当前过滤器业务结束
*/
Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}
Write custom logic in the filter to achieve the following functions:
- Login status judgment
- permission check
- Request current limit, etc.
custom global filter
Requirements: Define global filters, intercept requests, and determine whether the parameters of the request meet the following conditions:
-
Whether there is authorization in the parameter,
-
Whether the value of the authorization parameter is admin
Release if both are satisfied, otherwise intercept
accomplish:
Define a filter in gateway:
package cn.itcast.gateway.filters;
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.获取请求参数
MultiValueMap<String, String> params = exchange.getRequest().getQueryParams();
// 2.获取authorization参数
String auth = params.getFirst("authorization");
// 3.校验
if ("admin".equals(auth)) {
// 放行
return chain.filter(exchange);
}
// 4.拦截
// 4.1.禁止访问,设置状态码
exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
// 4.2.结束处理
return exchange.getResponse().setComplete();
}
}
filter execution order
Requests entering the gateway will encounter three types of filters: the current route filter, DefaultFilter, GlobalFilter
After requesting a route, the current route filter, DefaultFilter and GlobalFilter will be combined 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 route filters and defaultFilters is specified by Spring, and the default is to increase 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 > Route Filter > GlobalFilter.
For details, you can view the source code:
org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getFilters()
The method is to load the defaultFilters first, then load the filters of a route, and then merge.
org.springframework.cloud.gateway.handler.FilteringWebHandler#handle()
The method will load the global filter, merge it with the previous filter and sort it according to the order, and organize the filter chain
cross domain problem
What is a cross-domain problem
Cross-domain: Inconsistent domain names are cross-domain, including:
-
Different domain names: www.taobao.com and www.taobao.org and www.jd.com and miaosha.jd.com
-
Same domain name, different ports: localhost:8080 and localhost:8081
Cross-domain problem: The browser prohibits the originator of the request from making a cross-domain ajax request with the server, and the request is intercepted by the browser
Solution: CORS, this should be learned before, so I won't repeat it here.
For those who don't know, you can check https://www.ruanyifeng.com/blog/2016/04/cors.html
Simulate cross-domain problems
Put the webpage with cross-domain problem into a web server such as tomcat or nginx, start and access it.
The following error can be seen in the browser console:
Access localhost:10010 from localhost:8090, the port is different, it is obviously a cross-domain request.
Solve cross-domain problems
In the application.yml file of the gateway service, add the following configuration:
spring:
cloud:
gateway:
# 。。。
globalcors: # 全局的跨域处理
add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题
corsConfigurations:
'[/**]':
allowedOrigins: # 允许哪些网站的跨域请求
- "http://localhost:8090"
allowedMethods: # 允许的跨域ajax的请求方式
- "GET"
- "POST"
- "DELETE"
- "PUT"
- "OPTIONS"
allowedHeaders: "*" # 允许在请求中携带的头信息
allowCredentials: true # 是否允许携带cookie
maxAge: 360000 # 这次跨域检测的有效期