Teach you how to build SpringCloud project (13) Integrate Gateway new generation service gateway

What are microservices? A series will be seen at a glance!

1. Teach you how to build a SpringCloud project (1) Detailed explanation with pictures and texts, fool-like operation

2. Teach you how to build a SpringCloud project (2) Producers and consumers

3. Teach you how to build a SpringCloud project (3) Integrate the Eureka service registration center

4. Teach you how to build the SpringCloud project (4) Eureka cluster version construction

5. Teach you how to build the SpringCloud project (5) Build the producer cluster version

6. Teach you how to build a SpringCloud project (6) Eureka realizes service discovery

7. Teach you how to build a SpringCloud project (7) Integrate the Consul service registration center

8. Teach you how to build a SpringCloud project (8) Integrated Ribbon load balancer

9. Teach you how to build a SpringCloud project (9) Integrate OpenFeign service interface calls

10. Teach you how to build a SpringCloud project (10) Integrate Hystrix service downgrade

11. Teach you to build a SpringCloud project (11) Integrating Hystrix's service fuse

12. Teach you how to build a SpringCloud project (12) Integrate Hystrix's graphical Dashboard real-time monitoring

13. Teach you how to build a SpringCloud project (13) Integrate a new generation of Gateway

14. Teach you how to build a SpringCloud project (14) Integrated Config Distributed Configuration Center

15. Teach you how to build a SpringCloud project (15) Integrated Bus message bus

16. Teach you how to build a SpringCloud project (16) Integrated Stream message driver

17. Teach you how to build a SpringCloud project (17) Integrating Sleuth distributed link tracking

Continue to update, welcome to like and follow!

Introduction to Gateway

1. What is an API Gateway?

As an API framework, it is used to protect, enhance and control access to API services. The API gateway is a system before the application or service (providing REST API interface service), which is used to manage authorization, access control and traffic restriction, etc., so that the REST API interface service is protected by the API gateway and transparent to all callers . As a result, business systems hidden behind the API gateway can focus on creating and managing services instead of dealing with these strategic infrastructures.

2. What functions does the API gateway have?

insert image description here

3. What are the classifications and functions of API gateways?

insert image description here

4. What is Gateway

Spring Cloud Gateway is an official gateway developed by Spring based on technologies such as Spring 5.0, Spring Boot 2.0 and Project Reactor. Spring Cloud Gateway aims to provide a simple and effective unified API routing management method for microservice architecture. As the gateway in the Spring Cloud ecosystem, Spring Cloud Gateway aims to replace ZUUL. It not only provides a unified routing method, but also provides basic functions of the gateway based on the Filter chain, such as: security, monitoring/burying, and current limiting wait.

5. Why use Gateway

Spring Cloud Gateway can be regarded as an upgraded version and replacement of Zuul 1.x. It uses Netty to implement asynchronous IO earlier than Zuul 2, thus realizing a simple, more efficient than Zuul 1.x, and close to Spring Cloud. Compatible API Gateway.

Spring Cloud Gateway clearly distinguishes between Router and Filter, and a great feature is that it has a lot of built-in out-of-the-box functions, and all of them can be used through SpringBoot configuration or manual coding chain calls.
For example, there are 10 built-in routers, so that we can configure them directly and do routing according to Header, Path, Host, or Query as we like.

For example, general Filter and global Filter are distinguished, 20 kinds of Filters and 9 kinds of global Filters are built in, and all of them can be used directly. Of course custom Filter is also very convenient.

6. The most important concepts

  1. Route (routing): This is the basic building block of a gateway, which is defined by an ID, a URI, a set of assertions, and a set of filters. If the assertion is true, the route matches.

  2. Predicate (assertion): The input class is a ServerWebExchange. We can use this to match anything from an HTTP request, such as headers. Routing occurs if the request matches the assertion.

  3. Filter (filter): An instance of GatewayFilter in the Spring framework. Using a filter, the request can be modified before or after it is routed.

7. Workflow

insert image description here

The client sends a request to Spring Cloud Gateway, then finds the route that matches the request in Gateway Hander Mapping, and sends it to Gateway Web Handler.

The Handler sends the request to our actual service business logic through the specified filter chain, and then returns. Filters are separated by dotted lines because filters may execute business logic before ("pre") or after ("post") the proxy request.

Filter in the "pre" type can perform parameter verification, authority verification, traffic monitoring, protocol conversion, etc. In the "post" type filter, you can modify the response content, response header, log output, traffic monitoring, etc., which play a very important role.

The main core is routing forwarding + execution filter chain

2. Getting Started Configuration

Create a new module, the service name is cloud-gateway-gateway9527, and modify the pom.xml file, mainly adding the dependency of gateway. Mining tips, do not introduce web dependencies, otherwise an error will be reported and the project will not start. As shown below:

<?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>mcroservice</artifactId>
        <groupId>com.study.springcloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
 
    <artifactId>cloud-gateway-gateway9527</artifactId>
    <dependencies>
        <!--gateway-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!-- eureka-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    <!--  通用包-->
        <dependency>
            <groupId>com.study.springcloud</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>${project.version}</version>
        </dependency>
 
        <!--监控-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
 
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
 
    </dependencies>
 
</project>

Create a new yml configuration file, as shown below:

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

Create a new main startup class, as shown below:

package com.buba.springcloud.gateway;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
 
@SpringBootApplication
@EnableEurekaClient
public class GatewayMain {
    
    
    public static void main(String[] args) {
    
    
        SpringApplication.run(GatewayMain.class,args);
    }
}

Then start the Eureka7001 service and the gateway service of our new Gateway to see if the gateway service is successfully registered to the Eureka registration center?

insert image description here

It can be seen that the gateway Gateway has successfully registered with the registration center, so how does the gateway do the mapping? Let's take the cloud-provide-payment producer service as an example to map it. Open the PaymentControler control layer, and demonstrate the two methods of get and lb, because our previous visits are http://localhost:8001/payment/get/1, but when we visit, we use our port 8001, It is exposed to the outside, which is not safe, but we do not want to expose the real 8001 port number, and hope to wrap a layer of our Gateway port 9527 outside the 8001 outside, which requires new routing configuration in the yml configuration. As shown below:

server:
  port: 9527
 
spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      routes:
        - id: payment_route # 路由的id,没有规定规则但要求唯一,建议配合服务名
         #匹配后提供服务的路由地址
          uri: http://localhost:8001
          predicates:
            - Path=/payment/get/** # 断言,路径相匹配的进行路由
        - id: payment_route2
          uri: http://localhost:8001
          predicates:
            Path=/payment/lb/** #断言,路径相匹配的进行路由
 
eureka:
  instance:
    hostname: cloud-gateway-service
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/

Then we visit http://localhost:9527/payment/get/1, and we can access it successfully, indicating that the routing and assertion of our gateway are successfully configured! As shown below:

insert image description here

What we are configuring now is YML configuration, and another configuration solution is through hard coding. It is the bean injected into the RouteLocator in the code to solve the problem of too many YML file configurations and too large files. Then start licking! We only need to demonstrate how to access the website of Baidu News on the external network through the 9527 gateway.

Create a new config configuration file, as shown below:

package com.buba.springcloud.gateway.config;
 
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;
 
/**
 * 配置了一个id为routr-name的路由规则
 * 当访问地址http://localhost:9527/guonei时会自动转发到http://news.baidu.com/guonei
 * */
@Configuration
public class GateWayConfig
{
    
    
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){
    
    
        RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
        routes.route("patn_route_buba",r -> r.path("/guonei").uri("http://news.baidu.com/guonei")).build();
        return routes.build();
    }
}

After the configuration is complete, restart the service, we visit http://localhost:9527/guonei, and it can be successfully forwarded to the following interface, which shows that our GateWay performs routing mapping configuration by encoding.

insert image description here

3. Realize dynamic routing

Looking at our YML configuration file, we configure http://localhost:8001 is hard-coded, but in our microservices, it is impossible for the producer service to have a machine, so it is necessary to configure load balancing.

insert image description here

By default, the Gateway will create a dynamic route based on the service list registered by the registry, and use the microservice name on the registry to create a dynamic route for forwarding, thereby realizing the function of dynamic routing. Then we need to modify the YML configuration file of Gateway, enable the function of dynamically creating routes from the registration center, use the microservice name for routing, and change the route address of the service provider after matching to the service name of the producer. The specific configuration is as follows:

server:
  port: 9527
spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true # 开启从注册中心动态创建路由的功能,利用微服务名称j进行路由
      routes:
        - id: payment_route # 路由的id,没有规定规则但要求唯一,建议配合服务名
          #匹配后提供服务的路由地址
          #uri: http://localhost:8001
          uri: lb://MCROSERVICE-PAYMENT
          predicates:
            - Path=/payment/get/** # 断言,路径相匹配的进行路由
        - id: payment_route2
          #uri: http://localhost:8001
          uri: lb://MCROSERVICE-PAYMENT
          predicates:
            Path=/payment/lb/** #断言,路径相匹配的进行路由
eureka:
  instance:
    hostname: cloud-gateway-service
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/

In order to test load balancing, we need to start Eureka7001, start the producer services 8001 and 8002, start the Gateway service, and remember to add the lb method of the return port to the 8002 service. Successfully achieved load balancing. The test is as follows:

insert image description here

4. Commonly used Predicate assertions

We start our cloud-gateway-gateway9527 service, and we can see that the console has the following interface:
insert image description here

Spring Cloud Gateway uses route matching as part of the basic Spring WebFlux HandlerMapping framework, which includes many built-in RoutePredicateFactories, all of which match different attributes of HTTP requests. Combine multiple Route Predicate factories. When Spring Cloud Gateway creates a Route object, it uses RoutePredicateFactory to create a Predicate object. The Predicate object can be assigned to Route. Spring Cloud Gateway contains many built-in Route Predicate Factoriess. All of these predicates match different attributes of HTTP. Multiple predicate factories can be combined and passed a logical and.

Then we can also see the routing configuration in our YML configuration file. We use path, that is, the requested Path (path) matches the configuration value. As shown below:

insert image description here

Our commonly used routing configuration is to implement a set of matching rules, so that the request can find the corresponding Route for processing. As shown below:

insert image description here

Let's take an example of After, and the others are similar. Let's take a look at how the official website is configured, as shown in the figure below:
insert image description here

We can see a series of time in the red area. The official website uses foreign time, so how can we use the current time? Use the following class to get our current domestic time. The default is Shanghai. As shown below:

package com.buba.test;
 
import java.time.ZonedDateTime;
 
public class T2 {
    
    
    public static void main(String[] args) {
    
    
        ZonedDateTime time =  ZonedDateTime.now();//使用默认时间
        System.out.println(time);
 
 
    }
}

After getting the time, we configure the YML file, we only configure the payment/get method, as shown in the figure below:

server:
  port: 9527
spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true # 开启从注册中心动态创建路由的功能,利用微服务名称j进行路由
      routes:
        - id: payment_route # 路由的id,没有规定规则但要求唯一,建议配合服务名
          #匹配后提供服务的路由地址
          #uri: http://localhost:8001
          uri: lb://MCROSERVICE-PAYMENT
          predicates:
            - Path=/payment/get/** # 断言,路径相匹配的进行路由
            - After=2020-09-08T21:11:46.662+08:00[Asia/Shanghai] #断言在当前时间之后才可以访问
        - id: payment_route2
          #uri: http://localhost:8001
          uri: lb://MCROSERVICE-PAYMENT
          predicates:
            Path=/payment/lb/** #断言,路径相匹配的进行路由
eureka:
  instance:
    hostname: cloud-gateway-service
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/

Then let's test first, whether the access is successful now, because the current time must be later than the configured time, as shown in the following figure:
insert image description here

Let's modify the time, push the time back by one day, and then test the payment/get method, as shown in the figure below:

insert image description here

You can see that after the configuration, you can’t access it. Like this After, we can use it when we launch new functions. For example, if your company goes online at 10:00 p.m., you can go online in advance, and then wait until the set time to take effect. Then let's test the payment/lb method without After assertion to see if the access can be successful, as shown in the figure below:

insert image description here

It can be seen that the successful access shows that our configuration is correct. You can configure the 11 assertions according to your own needs.

Five, the use of Filter

Filter is one of the three cores of Gateway. Route filters can be used to modify incoming HTTP requests and returned HTTP responses. Route filters can only be used by specifying routes. Gateway has a variety of built-in routing filters, all of which are generated by the GatewayFilter project class.

The role of Filter

When we have many services, such as user-service, goods-service, sales-service and other services in the figure below, when the client requests the API of each service, each service needs to do the same thing, such as authentication, Current limiting, log output, etc.

insert image description here

For such repetitive work, is there a way to do better, the answer is yes. Add a global access control, current limiting, and log output Api Gateway service on the upper layer of the microservice, and then forward the request to the specific business service layer. This Api Gateway service acts as a service boundary. External requests to access the system must first pass through the gateway layer.

insert image description here

Filter life cycle

Spring Cloud Gateway is similar to zuul, with only pre and post life cycles. Before routing processing, it needs to be processed by a "pre" type filter, and after the processing returns a response, it can be processed by a "post" type filter. The "pre" type filter can perform parameter verification, authority verification, traffic monitoring, log output, protocol conversion, etc., and the "post" type filter can perform response content, response header modification, and log output , traffic monitoring, etc.

For example, the user-service in the above figure, after receiving the response from the business service, is processed by a filter of the "post" type, and finally returns the response to the client.
insert image description here

Different from zuul, in addition to filters divided into "pre" and "post", in Spring Cloud Gateway, filters can be divided into two other types from the scope of action, one is the gateway for a single route filter, which is written in the configuration file similar to predict; the other is the global gateway filer for all routes. Now explain these two filters from the dimension of scope division.

The Filter types of Spring Cloud Gateway are divided into GatewayFilter (single) and GlobalFilter (global)

Spring Cloud Gateway根据作用范围划分为GatewayFilter和GlobalFilter,二者区别如下:

GatewayFilter : 需要通过spring.cloud.routes.filters 配置在具体路由下,只作用在当前路由上或通过spring.cloud.default-filters配置在全局,作用在所有路由上。

GlobalFilter : 全局过滤器,不需要在配置文件中配置,作用在所有的路由上,最终通过GatewayFilterAdapter包装成GatewayFilterChain可识别的过滤器,它为请求业务以及路由的URI转换为真实业务服务的请求地址的核心过滤器,不需要配置,系统初始化时加载,并作用在每个路由上。

Introduction to GatewayFilter

The GatewayFilter factory is similar to the Predicate factory introduced in the previous article. It is configured in the configuration file application.yml. It follows the idea that the convention is greater than the configuration. You only need to configure the name of the GatewayFilter Factory in the configuration file instead of writing all the class names. For example, AddRequestHeaderGatewayFilterFactory only needs to write AddRequestHeader in the configuration file, not all class names. The GatewayFilter Factory configured in the configuration file will eventually be processed by the corresponding filter factory class.

The list of built-in filter factories in Spring Cloud Gateway is as follows:

insert image description here

Each filter factory gives a detailed use case in the official document. There are 30 versions now. Click to view the official website. If you are not clear, you can also see each filter in org.springframework.cloud.gateway.filter.factory The source code of the device factory.在我们实际的开发过程中,一般GatewayFilter是无法满足的,就需要我们自定义过滤器。

Then let's start customizing the filter ourselves!

The main thing is to implement these two interfaces GlobalFilter, Ordered, and then implement specific business logic, as shown in the figure below:

package com.buba.springcloud.gateway.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 MyLogGatewatFilter implements GlobalFilter, Ordered {
    
    
    //你要访问我时候需要一个指定的用户名才能进行访问,
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    
    
        log.info("************come in MyLogGatewatFilter "+ new Date());
        //判断是否携带uname的key
        String uname = exchange.getRequest().getQueryParams().getFirst("uname");
        //非法用户请离开
        if(uname==null){
    
    
            log.info("************用户名为null,非法用户");
            exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
            return exchange.getResponse().setComplete();
        }
        //合法用户进行下一个过滤链进行过滤验证
        return chain.filter(exchange);
    }
    //这个0数字代表加载过滤器的顺序,就是越小优先级越高,因为是全局的,所以必须是第一位的。
    @Override
    public int getOrder() {
    
    
        return 0;
    }
}

This filter is mainly the path to be accessed. It needs to carry the parameter uname. If it does not carry itself, the verification will be invalid, an error will be reported, and access will not be possible. Only when the order is written and legal can the access be successful. We visit http://localhost: 9527/payment/get/1?uname=zs to test, the success is as follows:
insert image description here

Then access without parameters, the failure is as shown in the figure below:

insert image description here

Introduction to GlobalFilter

The GlobalFilter built into the Spring Cloud Gateway framework is as follows:

insert image description here

Each GlobalFilter in the above figure acts on each router, which can meet most requirements. But if you encounter business customization, you may need to write a GlobalFilter that meets your needs. In the following case, we will describe how to write our own GlobalFilter. This GlobalFilter will verify whether the request parameter "token" is included in the request. If the request parameter "token" is not included, the route will not be forwarded, otherwise the normal logic will be executed. code show as below:

public class TokenFilter implements GlobalFilter, Ordered {
    
    
 
    Logger logger=LoggerFactory.getLogger( TokenFilter.class );
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    
    
        String token = exchange.getRequest().getQueryParams().getFirst("token");
        if (token == null || token.isEmpty()) {
    
    
            logger.info( "token is empty..." );
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }
 
    @Override
    public int getOrder() {
    
    
        return -100;
    }
}
 

The above TokenFilter needs to implement the GlobalFilter and Ordered interfaces, which is very similar to implementing GatewayFilter. Then get the ServerHttpRequest according to the ServerWebExchange, and then according to whether the ServerHttpRequest contains a parameter token, if not, complete the request and terminate the forwarding, otherwise execute the normal logic.

Then you need to inject TokenFilter into the Spring Ioc container in the startup class of the project, the code is as follows:

@Bean
public TokenFilter tokenFilter(){
    
    
        return new TokenFilter();
}

To start the project, use the curl command to request:

 curl localhost:8081/customer/123

It can be seen that the request is not forwarded, the request is terminated, and the following log is printed on the console:

2018-11-16 15:30:13.543  INFO 19372 --- [ctor-http-nio-2] gateway.TokenFilter                      : token is empty...

The log above shows that the request has entered the logic of not passing "token".

We have finished learning Spring Cloud Gateway here, so easy!

insert image description here

In the next article, we will learn about the Spring Cloud Config distributed configuration center. The article will continue to be updated. Welcome to pay attention!

Guess you like

Origin blog.csdn.net/weixin_39570655/article/details/131830964