SpringCloud microservice Xiaobai can also take (Hoxton.SR8) (7) Gateway|Service Gateway

Simple to get started, copy directly, you can build microservices (Hoxton.SR8) 2020.8.28 released, SpringCloud build articles are being sorted out, don’t miss out on dry goods

Summary

Spring Cloud Gateway provides API gateway support for SpringBoot applications, with powerful intelligent routing and filter functions. Gateway is an API gateway service built on 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 and provide some powerful filter functions, such as: fuse, current limit, retry, etc.

Spring Cloud Gateway has the following features:

  • Based on Spring Framework 5, Project Reactor and Spring Boot 2.0;
  • Dynamic routing: can match any request attribute;
  • Predicate (assertion) and Filter (filter) can be specified for routing;
  • Integrated Hystrix circuit breaker function;
  • Integrate Spring Cloud service discovery function;
  • Easy to write Predicate (assertion) and Filter (filter);
  • Request current limiting function;
  • Support path rewriting.

Configuration composition

  • Route: Route is the basic module for building a gateway. It consists of ID, target URI, a series of assertions and filters. If the assertion is true, it will match the route;
  • Predicate (assertion): Refers to the Function Predicate of Java 8. The input type is ServerWebExchange in the Spring framework. This allows developers to match all content in the HTTP request, such as request headers or request parameters. If the request matches the assertion, it is routed;
  • Filter (filter): Refers to an instance of GatewayFilter in the Spring framework. With filters, the request can be modified before and after the request is routed.

1. Create an api-gateway module

 

  

2 Use gateway alone

2.1 New gateway dependency in pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>cloud-hoxton-sr8</artifactId>
        <groupId>com.zqh.www</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>api-gateway</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

2.2 Startup

package com.zqh.www;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.env.Environment;

@SpringBootApplication
public class ApiGatewayApplication {

    private final static Logger logger = LoggerFactory.getLogger(ApiGatewayApplication.class);

    public static void main(String[] args) {
        Environment env = SpringApplication.run(ApiGatewayApplication.class, args).getEnvironment();
        logger.info(
                "\n----------------------------------------------------------\n\t"
                        + "Application '{}' is running! Access URLs:\n\t"
                        + "Local: \t\thttp://localhost:{}{}"
                        + "\n----------------------------------------------------------",
                env.getProperty("spring.application.name"), env.getProperty("server.port"),
                env.getProperty("server.servlet.context-path") != null ? env.getProperty("server.servlet.context-path") : "");
    }
}

2.3 ed

server:
  port: 8093

service-url:
  user-service: http://localhost:8084

spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        # 路由的ID
        - id: user-service
          # 匹配后路由地址
          uri: ${service-url.user-service}
          predicates:
            # 发送指定路径的请求会匹配该路由。
            - Path=/api/user/*
#            # 发送指定方法的请求会匹配该路由。
#            - Method=GET
#            # 在指定时间之后的请求会匹配该路由。
#            - After=2020-10-20T12:00:00+08:00[Asia/Shanghai]
#            # 在指定时间之前的请求会匹配该路由。
#            - Before=2020-10-20T12:00:00+08:00[Asia/Shanghai]
#            # 在指定时间区间内的请求会匹配该路由。
#            - Between=2020-10-20T12:00:00+08:00[Asia/Shanghai], 2020-10-30T12:00:00+08:00[Asia/Shanghai]
#            # 带有指定Cookie的请求会匹配该路由
#            - Cookie=username,jourwon
#            # 带有指定请求头的请求会匹配该路由。
#            - Header=auth
#            #带有指定Host的请求会匹配该路由。
#            - Host=www.zqh.com
#            # 从指定远程地址发起的请求可以匹配该路由。
#            - RemoteAddr=192.168.1.1/24
          filters:
#            - AddRequestParameter=username,z
#            - StripPrefix=1
#            - PrefixPath=/api

logging:
  level:
    org.springframework.cloud.gateway: debug

2.4 predicates-test cases

Note: If there are multiple conditions, all the conditions must be met to match the relevant route

2.4.1 predicates - Path

Description: Send a request that matches the path or will match the route.
yml configuration:-Path=/api/user/*
Interface request: http://localhost:8093/api/user/getUserList is
equivalent to: http://localhost:8084/api/user/ getUserList

2.4.2 predicates - Method

Description: Sending a request for the specified method will match the route.
Interface request: http://localhost:8093/api/user/getUserList

  

2.4.3 predicates - After

Description: Requests after the specified time will match the route.
Interface request: http://localhost:8093/api/user/getUserList

  

2.4.4 predicates - Before

Description: Requests before the specified time will match this route.

2.4.5 predicates - Between

Description: Requests within the specified time interval will match this route.

2.4.6 predicates - Cookie

Description: The request with the specified cookie will match the route.
Configuration:

predicates:
    # 带有指定Cookie的请求会匹配该路由
    - Cookie=username,z

Interface request:

2.4.7 predicates - Header

Description: A request with the specified request header will match the route.
Settings:

predicates:
    # 带有指定请求头的请求会匹配该路由。
    - Header=auth

Interface request:
 

2.4.8 predicates - Host

Description: Requests with the specified Host will match the route.
Settings:

predicates:
    #带有指定Host的请求会匹配该路由。
    - Host=www.zqh.com

2.4.9 predicates - RemoteAddr

Description: Requests from the specified path will match the route.
Settings:

predicates:
    #从指定远程地址发起的请求可以匹配该路由。
    - RemoteAddr=192.168.0.100

2.5 filters-test case

2.5.1 filters - AddRequestParameter

Description: Add request parameters to GET request
Configuration:

service-url:
  user-service: http://localhost:8084
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        # 路由的ID
        - id: user-service
          # 匹配后路由地址
          uri: ${service-url.user-service}
          predicates:
            # 发送指定路径的请求会匹配该路由。
            - Path=/api/user/*
          filters:
            - AddRequestParameter=username,z

Request: http://localhost:8093/api/user/getUserList is
equivalent to: http://localhost:8084 /api/user/getUserList ?username=z

2.5.2 filters - StripPrefix

Description: The path of the request at the beginning will remove the specified number of bits.
Configuration:

service-url:
  user-service: http://localhost:8084
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        # 路由的ID
        - id: user-service
          # 匹配后路由地址
          uri: ${service-url.user-service}
          predicates:
            # 发送指定路径的请求会匹配该路由。
            - Path=/api/user/*
          filters:
            - StripPrefix=1

Request: http://localhost:8093/api/user/getUserList is
equivalent to: http://localhost:8084 /user/getUserList

2.5.3 filters - PrefixPath

Description: Add the specified path prefix to all GET requests
Configuration:

service-url:
  user-service: http://localhost:8084
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        # 路由的ID
        - id: user-service
          # 匹配后路由地址
          uri: ${service-url.user-service}
          predicates:
            # 发送指定路径的请求会匹配该路由。
            - Path=/user/*
          filters:
            - PrefixPath=/api

Request: http://localhost:8093/user/getUserList is
equivalent to: http://localhost:8084 /api /user/getUserList

2.5.3 filters - hystrix

Description: Hystrix filter allows you to add the circuit breaker function to the gateway routing to protect your services from cascading failures and provide service degradation processing.
pom.xml:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

 fr:

service-url:
  user-service: http://localhost:8084
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        # 路由的ID
        - id: user-service
          # 匹配后路由地址
          uri: ${service-url.user-service}
          predicates:
            # 发送指定路径的请求会匹配该路由。
            - Path=/api/user/*
          filters:
            - name: Hystrix
              args:
                name: fallbackcmd
                #转发路径
                fallback-uri: forward:/fallback

controller:

package com.zqh.www.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@RestController
public class FallbackController {

    @GetMapping("/fallback")
    public Object fallback() {
        Map<String, Object> result = new HashMap<>();
        result.put("data", null);
        result.put("message", "Get request fallback!");
        result.put("code", 500);
        return result;
    }
}

 Test:
Normal condition: Service exception: (Close user-service service to simulate service disconnection)

     

2.5.3 filters - RequestRateLimiter

Description: The RequestRateLimiter filter can be used for current limiting. The RateLimiter implementation is used to determine whether the current request is allowed to proceed. If the request is too large, the HTTP 429-status will be returned by default.
pom.xml:

 <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>

fr:

service-url:
  user-service: http://localhost:8084

spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        # 路由的ID
        - id: user-service
          # 匹配后路由地址
          uri: ${service-url.user-service}
          predicates:
            # 发送指定路径的请求会匹配该路由。
            - Path=/api/user/*
          filters:
            - name: RequestRateLimiter
              args:
                # 每秒允许处理的请求数量
                redis-rate-limiter.replenishRate: 1
                # 每秒最大处理的请求数量
                redis-rate-limiter.burstCapacity: 2
                # 限流策略,对应策略的Bean
                key-resolver: "#{@ipKeyResolver}"

config:

package com.zqh.www.config;

import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;

import java.util.Objects;

@Configuration
public class RedisRateLimiterConfig {

    // 如果你是采用第二个的策略,那么第一个策略的@Bean记得要注释掉,否则他会报找到2个参数
    //    @Bean
    public KeyResolver userKeyResolver() {
        return exchange -> Mono.just(Objects.requireNonNull(exchange.getRequest().getQueryParams().getFirst("username")));
    }

    @Bean
    public KeyResolver ipKeyResolver() {
        return exchange -> Mono.just(Objects.requireNonNull(exchange.getRequest().getRemoteAddress()).getHostName());
    }
}

Test:
Normal situation: Abnormal situation: Return 429 in case of quick request
  

2.5.4 filters - Retry

Description: The filter for retrying routing requests can determine whether to retry based on the HTTP status code returned by the routing request.

yml :

service-url:
  user-service: http://localhost:8084
spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      routes:
        # 路由的ID
        - id: user-service
          # 匹配后路由地址
          uri: ${service-url.user-service}
          predicates:
            # 发送指定路径的请求会匹配该路由。
            - Path=/api/user/*
          filters:
            - name: Retry
              args:
                #需要进行重试的次数
                retries: 1
                #返回哪个状态码需要进行重试,返回状态码为5XX进行重试
                statuses: BAD_GATEWAY 
                backoff:
                  firstBackoff: 10ms
                  maxBackoff: 50ms
                  factor: 2
                  basedOnPreviousValue: false

Test:
Normal: Exception: (adding a null pointer to the service provider), 2 errors will be output, which means 1 retry
   

3. Microservices use gateway

3.1 pom.xm dependency

<dependencies>
        <!-- 配合注册中心使用 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
        </dependency>
    </dependencies>

3.2 Startup

package com.zqh.www;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.core.env.Environment;

/**
 * 开启服务发现客户端
 *
 * @EnableEurekaClient只适用于Eureka作为注册中心,@EnableDiscoveryClient 可以是其他注册中心。
 */
// 如果你是启动的是alone的配置,请注释@EnableDiscoveryClient,并且注释 pom.xml 里面的 eureka-client 依赖,不然会出现链接错误
@EnableDiscoveryClient
@SpringBootApplication
public class ApiGatewayApplication {

    private final static Logger logger = LoggerFactory.getLogger(ApiGatewayApplication.class);

    public static void main(String[] args) {
        Environment env = SpringApplication.run(ApiGatewayApplication.class, args).getEnvironment();
        logger.info(
                "\n----------------------------------------------------------\n\t"
                        + "Application '{}' is running! Access URLs:\n\t"
                        + "Local: \t\thttp://localhost:{}{}"
                        + "\n----------------------------------------------------------",
                env.getProperty("spring.application.name"), env.getProperty("server.port"),
                env.getProperty("server.servlet.context-path") != null ? env.getProperty("server.servlet.context-path") : "");
    }
}

3.3 margins

server:
  port: 8093

eureka:
  client:
    service-url:
      #注册地址
      defaultZone: http://root:root@localhost:8081/eureka/
  #显示服务器IP加端口
  instance:
    hostname: localhost
    prefer-ip-address: true
    instance-id: ${spring.cloud.client.ip-address}:${server.port}

spring:
  application:
    name: api-gateway
  cloud:
    gateway:
      discovery:
        locator:
          #开启从注册中心动态创建路由的功能
          enabled: true
          #使用小写服务名
          lower-case-service-id: true
      routes:
        # 路由的ID
        - id: user-service
          # 在结合注册中心使用过滤器的时候,uri的协议为lb,这样才能启用Gateway的负载均衡功能。
          uri: lb://user-service
          predicates:
            # 发送指定路径的请求会匹配该路由。
            - Path=/api/user/*
#            # 发送指定方法的请求会匹配该路由。
#            - Method=GET
#            # 在指定时间之后的请求会匹配该路由。
#            - After=2020-10-20T18:00:00+08:00[Asia/Shanghai]
#            # 在指定时间之前的请求会匹配该路由。
#            - Before=2020-10-20T12:00:00+08:00[Asia/Shanghai]
#            # 在指定时间区间内的请求会匹配该路由。
#            - Between=2020-10-20T12:00:00+08:00[Asia/Shanghai], 2020-10-30T12:00:00+08:00[Asia/Shanghai]
#            # 带有指定Cookie的请求会匹配该路由
#            - Cookie=username,z
#            # 带有指定请求头的请求会匹配该路由。
#            - Header=auth
#            #带有指定Host的请求会匹配该路由。
#            - Host=www.zqh.com
#            # 从指定远程地址发起的请求可以匹配该路由。
#            - RemoteAddr=192.168.1.1/24
          filters:
            - name: Retry
              args:
                #需要进行重试的次数
                retries: 3
                #返回哪个状态码需要进行重试,返回状态码为5XX进行重试
                statuses: BAD_GATEWAY
                backoff:
                  firstBackoff: 10ms
                  maxBackoff: 50ms
                  factor: 2
                  basedOnPreviousValue: false
#            - name: RequestRateLimiter
#              args:
#                # 每秒允许处理的请求数量
#                redis-rate-limiter.replenishRate: 1
#                # 每秒最大处理的请求数量
#                redis-rate-limiter.burstCapacity: 2
#                # 限流策略,对应策略的Bean
#                key-resolver: "#{@ipKeyResolver}"
#            - name: Hystrix
#              args:
#                name: fallbackcmd
#                #转发路径
#                fallback-uri: forward:/fallback
#            - AddRequestParameter=username,z
#            - StripPrefix=1
#            - PrefixPath=/api

logging:
  level:
    org.springframework.cloud.gateway: debug

3.4 Test

4.gitee address

Source code reference

Guess you like

Origin blog.csdn.net/itjavaee/article/details/109119266