【SpringCloud】Gateway use


Official website
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/

Overview

  • Gateway is an API gateway service built on top of the Spring ecosystem, based on technologies such as Spring 5, Spring Boot 2 and Project Reactor.
  • Gateway aims to provide a simple and effective way to route APIs, as well as provide some powerful filter functions, such as: fusing, current limiting, retry, etc.
    Insert image description here

Blocking processing model and non-blocking processing model concepts

Blocking Processing Model

Disadvantages
servlet is a simple network IO model. When a request enters the servlet container, the servlet container will bind a thread to it. This model is applicable in scenarios where concurrency is not high. But once the concurrency is high (such as using jemeter to suppress the problem), the number of threads will increase, and the cost of thread resources is expensive (online text switching, large memory consumption), seriously affecting the request processing time. In some simple business scenarios, you do not want to allocate a thread for each request. Only one or a few threads are needed to handle extremely concurrent requests. In this business scenario, the servlet model has no advantages.
Insert image description here

There is asynchronous non-blocking support after Servlet3.1. WebFlux is a typical non-blocking asynchronous framework, and its core is implemented based on Reactor's related APIs. Compared with traditional web frameworks, it can run on containers such as Netty, Undertow and Servlet3.1. Non-blocking + functional programming (Spring5 must let you use java8)

Spring WebFlux is a new reactive framework introduced in Spring 5.0. Different from Spring MVC, it does not need to rely on the Servlet API. It is completely asynchronous and non-blocking, and is based on Reactor to implement the reactive flow specification.

Three Core Concepts

  1. Route
  2. Predicate
  3. Filter
    Insert image description here

work process

Core: routing forwarding + execution filter chain

  1. The client makes a request to Spring Cloud Gateway. Then find the route that matches the request in Gateway Handler Mapping and send it to Gateway Web Handler.

  2. Handler then sends the request to our actual service to execute business logic through the specified filter chain, and then returns.

  3. Filters are separated by dotted lines because filters may execute business logic before ("pre") or after ("post") sending the proxy request.

  4. Filters of the "pre" type can perform parameter verification, permission verification, traffic monitoring, log output, protocol conversion, etc. Filters of the "post" type can modify response content and response headers, and modify logs. Output, traffic monitoring, etc. play a very important role.

use

POM

<dependencies>
    <!--gateway-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <!--eureka-client-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <!-- 引入自己定义的api通用包,可以使用Payment支付Entity -->
    <dependency>
        <groupId>com.atguigu.springcloud</groupId>
        <artifactId>cloud-api-commons</artifactId>
        <version>${project.version}</version>
    </dependency>
    <!--一般基础配置类-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>
<!--不需要这两个!!!!!!!!!!!!!!-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

YML

server:
  port: 9527

spring:
  application:
    name: cloud-gateway

eureka:
  instance:
    hostname: cloud-gateway-service
  client: #服务提供者provider注册进eureka服务列表内
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka

Startup class

@SpringBootApplication
@EnableEurekaClient

configure routing

server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
      routes:
        - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8001          #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/get/**         # 断言,路径相匹配的进行路由

        - id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          uri: http://localhost:8001          #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/lb/**         # 断言,路径相匹配的进行路由
            #- After=2020-02-21T15:51:37.485+08:00[Asia/Shanghai]
            #- Cookie=username,zzyy
            #- Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性并且值为整数的正则表达式

eureka:
  instance:
    hostname: cloud-gateway-service
  client: #服务提供者provider注册进eureka服务列表内
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka

Configuration via coding

@Configuration
public class GateWayConfig
{
    
    
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder)
    {
    
    
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();

        routes.route("path_route_atguigu",
                r -> r.path("/guonei")
                        .uri("http://news.baidu.com/guonei")).build();

        return routes.build();
    }
}

dynamic routing

server:
  port: 9527

spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
      routes:
        - id: payment_routh #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/get/**         # 断言,路径相匹配的进行路由

        - id: payment_routh2 #payment_route    #路由的ID,没有固定规则但要求唯一,建议配合服务名
          #uri: http://localhost:8001          #匹配后提供服务的路由地址
          uri: lb://cloud-payment-service #匹配后提供服务的路由地址
          predicates:
            - Path=/payment/lb/**         # 断言,路径相匹配的进行路由
            #- After=2020-02-21T15:51:37.485+08:00[Asia/Shanghai]
            #- Cookie=username,zzyy
            #- Header=X-Request-Id, \d+  # 请求头要有X-Request-Id属性并且值为整数的正则表达式

eureka:
  instance:
    hostname: cloud-gateway-service
  client: #服务提供者provider注册进eureka服务列表内
    service-url:
      register-with-eureka: true
      fetch-registry: true
      defaultZone: http://eureka7001.com:7001/eureka

Commonly used Route Predicates

  1. After Route Predicate
    Insert image description here
import java.time.ZoneId;
import java.time.ZonedDateTime;
public class ZonedDateTimeDemo
{
    
    
    public static void main(String[] args)
    {
    
    
        ZonedDateTime zbj = ZonedDateTime.now(); // 默认时区
        System.out.println(zbj);
//        ZonedDateTime zny = ZonedDateTime.now(ZoneId.of("America/New_York")); // 用指定时区获取当前时间
//        System.out.println(zny);
    }
}
  1. Before Route Predicate
  2. Between Route Predicate
  3. Cookie Route Predicate
    Insert image description here
    Cookie Route Predicate requires two parameters, one is Cookie name and the other is regular expression.
    The routing rules will match the corresponding cookie name value and the regular expression. If there is a match, the routing will be executed. If there is no match, the
    test will not be executed:
curl http://localhost:9527/payment/lb --cookie "username=xiaoli"
  1. Header Route Predicate
    Insert image description here
    has two parameters: one is the attribute name and a regular expression. If the attribute value matches the regular expression, it will be executed.
  2. Host Route Predicate
    Insert image description here
    Host Route Predicate receives a set of parameters and a list of matching domain names. This template is an ant-delimited template, using . as the delimiter.
    It passes the host address in the parameter as a matching rule.
  3. Method Route Predicate
    Insert image description here
  4. Path Route Predicate
    Insert image description here
  5. Query Route Predicate
    Insert image description here
    supports passing in two parameters, one is the attribute name and the other is the attribute value, and the attribute value can be a regular expression.

custom global filter

import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class GateWayConfig
{
    
    
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder)
    {
    
    
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();

        routes.route("path_route_atguigu",
                r -> r.path("/guonei")
                        .uri("http://news.baidu.com/guonei")).build();

        return routes.build();
    }
}

custom filter

import lombok.extern.slf4j.Slf4j;
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.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Date;
@Component
@Slf4j
public class MyLogGateWayFilter implements GlobalFilter,Ordered
{
    
    

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
    {
    
    
        log.info("***********come in MyLogGateWayFilter:  "+new Date());

        String uname = exchange.getRequest().getQueryParams().getFirst("uname");

        if(uname == null)
        {
    
    
            log.info("*******用户名为null,非法用户,o(╥﹏╥)o");
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }

        return chain.filter(exchange);
    }

    @Override
    public int getOrder()
    {
    
    
        return 0;
    }
}

Guess you like

Origin blog.csdn.net/qq_45742250/article/details/132356692