springcloudlibaba-gateway gateway

Spring Cloud Gateway is a new project of Spring Cloud, which is a gateway developed based on Spring 5.0, Spring Boot 2.0 and Project Reactor and other reactive programming and event flow technologies. It aims to provide a simple and effective unified API route management method.

1. Why do you need a gateway

Gateway is the gatekeeper of our services, the unified entrance of all microservices.

The core functional characteristics of the gateway :

  • request routing

  • access control

  • Limiting

Architecture diagram:

Access control : As the entry point of microservices, the gateway needs to verify whether the user is eligible for the request, and intercept it if not.

Routing and load balancing : All requests must first pass through the gateway, 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 limiting : When the request traffic is too high, the gateway will release the request according to the speed that the downstream microservice can accept, so as to avoid excessive service pressure.

There are two types of gateway implementations in Spring Cloud:

  • gateway

  • zul

Zuul is a Servlet-based implementation and belongs to blocking programming. Spring Cloud Gateway is based on WebFlux provided in Spring 5, which is an implementation of responsive programming and has better performance.

2. Gateway quick start

Next, we will demonstrate the basic routing function of the gateway. The basic steps are as follows:

  1. Create a SpringBoot project gateway and introduce gateway dependencies

  2. Write startup class

  3. Write basic configuration and routing rules

  4. Start the gateway service for testing

1) Create a gateway service and introduce dependencies

Create a 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>

2) Write the 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);
	}
}

3) 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:8849 # nacos地址
    gateway:
      routes: # 网关路由配置
        - id: user-service # 路由id,自定义,只要唯一即可
          # uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
          uri: lb://userservice # 路由的目标地址 lb就是nacos中的负载均衡,后面跟服务名称
          predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
            - Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求
        - id: order-service
          uri: lb://orderservice
          predicates:
            - Path=/order/** # 路径匹配

We will Pathproxy all requests that match the rules to the address specified by urithe parameter .

In this example, we proxy the request /user/**beginning lb://userservicewith , and lb uses the load balancing strategy in nacos to pull the service list according to the service name to achieve load balancing.

gateway:
      discovery:
        locator:
          enabled: true
          lower-case-service-id: true
      routes:
      - id: service_consumer
        uri: lb://service-consumer
        predicates:
        - Path= /consumer/**
        filters:
        - StripPrefix=1

In the above configuration, a path predicat is configured, and requests starting with /consumer/** will be forwarded to the address whose uri is lb://service-consumer, lb://service-consumer (in the registration center The name of the service) is the load balancing address of the service-consumer service, and use the filter of StripPrefix to remove /consumer before forwarding.

At the same time, change spring.cloud.gateway.discovery.locator.enabled to false. If you do not change it, the previous request address such as http://localhost:8081/service-consumer/user/info can also be accessed normally, because this 2 routers are created for each service.

The second part of this article and this section describe two configuration methods in total, and both configurations can realize the function of request routing and forwarding. The parameter spring.cloud.gateway.discovery.locator.enabled is true, indicating that Gateway enables service registration and discovery functions, and Spring Cloud Gateway automatically creates a router for each service based on service discovery. This router will start with the service name The request path is forwarded to the corresponding service. spring.cloud.gateway.discovery.locator.lowerCaseServiceId is to configure the service name on the request path as lowercase (because when the service is registered, the service name is converted to uppercase when registering with the registry).

4) Restart the test

Restart the gateway, when accessing http://localhost:10010/user/1 , it complies with /user/**the rules, and the request is forwarded to uri: http://userservice/user/1 , and the result is obtained:

5) Flow chart of gateway routing

The entire access process is as follows:

Summarize:

Gateway construction steps:

  1. Create a project, introduce nacos service discovery and gateway dependencies

  2. Configure application.yml, including basic service information, nacos address, routing

Routing configuration includes:

  1. route id : the unique identifier of the route

  2. Routing destination (uri) : the destination address of the routing, http stands for fixed address, lb stands for load balancing based on service name

  3. Routing assertions (predicates) : Rules for judging routing,

  4. Route filters (filters) : process the request or response

3. Assertion factory (the function is to judge network requests, and only those that meet the requirements can pass )

The assertion rules we write in the configuration file are just strings, which will be read and processed by the Predicate Factory and turned into conditions for routing judgments

For example, Path=/user/** is matched according to the path. This rule is determined by

org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactoryclass to

For processing, there are more than a dozen assertion factories like this in Spring Cloud Gateway:

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 some point in time - Before=2031-04-13T15:14:47.433+08:00[Asia/Shanghai]
Between is a request before a certain two points in time - Between=2037-01-20T17:42:47.789-07:00[America/Denver], 2037-01-21T17:42:47.789-07:00[America/Denver]
Cookie Requests must contain certain cookies - Cookie=chocolate, ch.p
Header Requests 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 specified - Method=GET,POST
Path The request path must conform to the specified rules - Path=/red/{segment},/blue/**
Query The 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 processing

We only need to master the routing engineering of Path.  

2. Route filter filter (GatewayFilter), processing the request entering the gateway and the response returned by the microservice (processing the request header and request parameters)

Let's take AddRequestHeader as an example to explain.

Requirement : Add a request header to all requests entering userservice: Truth=itcast is freaking awesome!

You only need to modify the application.yml file of the gateway service, and add routing filter  filters (only valid for the current service, and a request header will be added directly to the current service request) :

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 .

3. Route filter (GatewayFilter) - default filter

 Add the default-filters field, which is at the same level as routes, and all requests will carry this global 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! 
      - AddResponseHeader=Truth, Itcast is freaking awe222some!

5. Global filter GlobalFilter ( the system default is fixed, implement your own request logic, no need to configure, use code to implement )

For the filters learned in the previous section, the gateway provides 31 types, but the role of each filter is fixed. If we want to intercept the request and do our own business logic, there is no way to achieve it

5.1. Global filter function

The role of the global filter is also to process all requests and microservice responses entering the gateway, which is the same as the role of GatewayFilter. The difference is that GatewayFilter is defined through configuration, and the processing logic is fixed; while the logic of GlobalFilter needs to be implemented by writing code yourself.

The definition method is to implement the GlobalFilter interface ( the class written by the system ).

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 filter to achieve the following functions:

  • Login Status Judgment

  • permission check

  • Request throttling, etc.

3.5.2. Custom global filter

Requirements: Define a global filter, intercept requests, and determine whether the parameters of the request meet the following conditions:

  • Whether there is authorization in the parameter,

  • Whether the authorization parameter value is admin

If it is satisfied at the same time, let it go, otherwise block it

accomplish:

Define a filter in gateway ( written by yourself ):

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值越小,优先级越高,执行顺序越靠前
@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();
    }
}

Then request the following connection, you can pass, otherwise it will not let you go

http://127.0.0.1:10010/order/101?authorization=admin

5.3. Filter execution order

When a request enters the gateway, it will encounter three types of filters: current route filter, DefaultFilter, GlobalFilter

After requesting routing, the current routing filter, DefaultFilter, and GlobalFilter will be merged into a filter chain (collection), and each filter will be executed in turn after sorting:

What are the rules for sorting?

  • Each filter must specify an int type order value, 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 routing filters and defaultFilter is specified by Spring, and the default is to increase from 1 according to the order of declaration.

  • When the order values ​​of the filters are the same, they 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 certain route, and then merge them.

org.springframework.cloud.gateway.handler.FilteringWebHandler#handle()The method will load the global filter, sort according to the order after merging with the previous filter, and organize the filter chain

6.3. Solving cross-domain problems

In the application.yml file of the gateway service, add the following configuration globalcors :

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 # 这次跨域检测的有效期

Guess you like

Origin blog.csdn.net/zxc472504515/article/details/125744086