Java learning record 06Spring Cloud Gateway gateway

Posted by faizanno1 on Sun, 31 Oct 2021 21:38:27 +0100

Gateway gateway

The core of the Spring Cloud Gateway component is a series of filters that can forward (route) requests sent by clients to corresponding services.

Supplementary notes & benefits

  • Gateway replaces a solution from Netflix Zuul
  • Hide the IP / port information of the service
  • Provide a unified API route management method (url management)
  • Gateway core functions: filtering / routing / assertion
  • Gateway is also a micro service and needs to register with Eureka

Core functions

  • Route: route information consists of ID, target URL, a group of assertions and a group of filters (generally, route matching will be judged through assertions)
  • Predicate: define any information in the matching HTTP (such as request header / parameters, etc...)
  • Filter: some business processing can be performed on the request / response

Workflow

explain:

  • The client sends a request. If the request matches the route defined by the gateway program, the request will be sent to the micro service of the gateway for processing. At this time, the processing runs a specific request filter chain

  • The reason why the dotted line of the filter is separated: the request / response logic of the proxy request will be executed (all pre filter logic will be executed first, and then the proxy request; after the proxy request is completed, the post filter logic will be executed to respond)

Example

Code in 01Spring Cloud Edit based on

  1. Create a new Maven project (no skeleton)
    The project name I created is gateway

  2. gateway dependency configuration pom.xml

    <!-- 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>
    
  3. gateway startup class

    @SpringBootApplication
    @EnableDiscoveryClient // Eureka client
    public class GatewayApplication {
        public static void main(String[] args) {
            SpringApplication.run(GatewayApplication.class, args);
        }
    }
    
  4. gateway configuration application.yml

    server :
        port : 10010
    spring :
        application :
            name : api-gateway
        cloud :
            gateway :
                routes :
                    # Routing id (optional)
                    - id : user-service-route
                      # Address of proxy service
    #                 uri: http://localhost:9091 # mode 1 fixed agent
                      uri : lb://User service # mode 2 dynamic agent
                      # Route assertions, mapping paths that can be configured
                      predicates:
                        - Path=/user/**
    eureka :
        client :
            service-url :
                defaultZone : http://localhost:10086/eureka
        instance :
            # Give priority to ip, not host
            prefer-ip-address : true
    

    be careful:

    • The path to fill in the route assertion cannot contain spaces - Path=/user/**

    explain:

    • Proxy path http://localhost:10010/user/1 ==> http://localhost:9091/user/1
    • Proxy routing can be written in two ways, but generally it will not die. Therefore, the second method is applied
    • When the protocol used for uri in routing configuration is lb, gateway will use LoadBalancerClient to parse user service into actual IP and port through eureka, and perform ribbon load balancing
  5. test

    1. Open Eureka, server and gateway services in turn
    2. visit http://localhost:10010/user/1 (the returned data represents success)

filter

It can be seen from the above workflow that the Gateway's routing filter allows you to modify the HTTP of incoming requests / responses, which only works on specific routes

Filter life cycle

There are two kinds of Filter for Spring Cloud Gateway: pre (before invoking the request is executed), post (after the request is executed), and the above workflow can be seen.

Usage scenario

  • Request authentication: before the filter chain calls the filter() method, if no permission is found, Null is returned
  • Exception handling: after the filter chain calls the filter() method, the exception is recorded and returned
  • Statistics of service call duration: before and after the filter chain call to the filter() method, statistics are made according to the duration

Common filter factory

There are many built-in filter factories in the Gateway. We only need to understand the commonly used filters

Filter factory nameexplain
AddRequestHeaderAdd a header to the matching request
RemoveRequestHeaderRemove the header (request header) from the request on the match
AddRequestParameterAdd parameters to the request route on the match
SetStatusSet the response code of the HTTP request
AddResponseHeaderAdd a header (response header) to the response returned from the gateway
StripPrefixRemove the prefix from the request path on the match
PrefixPathPrefix request paths on matching

More detailed reference Official website link

Filter example

AddRequestHeader add request header

For requests that match the rules successfully, the X-Request-Foo:bar request header will be added and passed to the back-end service

spring :
    application :
        name : api-gateway
    cloud :
        gateway :
            routes :
                - id : user-service-route
                  uri : lb://user-service
                  predicates:
                      - Path=/user/**
                  filters:
                  	  # Parameters: request header, value
					  - AddRequestHeader=X-Request-Foo,Bar

Removerequeheader remove request header

The Header can be removed before the request is forwarded to the back-end service

spring :
    application :
        name : api-gateway
    cloud :
        gateway :
            routes :
                - id : user-service-route
                  uri : lb://user-service
                  predicates:
                      - Path=/user/**
                  filters:
                  	  # Parameter: remove request header X-Request-Foo
					  - RemoveRequestHeader=X-Request-Foo

AddRequestParameter request to add a parameter

The MyName=Sans parameter will be attached to the request that matches the rule successfully

spring :
    application :
        name : api-gateway
    cloud :
        gateway :
            routes :
                - id : user-service-route
                  uri : lb://user-service
                  predicates:
                      - Path=/user/**
                  filters:
                  	  # Parameters: name, value (similar to K, V)
					  - AddRequestParameter=MyName,Sans

SetStatus response return code

Used to set the response code of HTTP request; supports integer / enumeration (org.springframework.http.HttpStatus class to view enumeration)

spring :
    application :
        name : api-gateway
    cloud :
        gateway :
            routes :
                - id : user-service-route
                  uri : lb://user-service
                  predicates:
                      - Path=/user/**
                  filters:
					  - SetStatus=401

AddResponseHeader add response header

Add response header to gateway response

spring :
    application :
        name : api-gateway
    cloud :
        gateway :
        	default-filters:
        		- AddResponseHeader=X-Request-Foo,Bar

StripPrefix removes the routing prefix

Remove the prefix of the request address and use it as the proxy address

spring :
    application :
        name : api-gateway
    cloud :
        gateway :
            routes :
                # Routing id (optional)
                - id : user-service-route
                  # Address of proxy service
#                  uri: http://localhost:9091 # mode 1
                  uri : lb://User service # mode 2
                  # Route assertions, mapping paths that can be configured
                  predicates:
                    - Path=/api/user/**
                  filters:
                    - StripPrefix=1
···

For example: http://localhost:10010/api/user/1 ==> http://localhost:9091/user/1 (remove / api)

PrefixPath add route prefix

Add a prefix to the request address and use it as the proxy address

spring :
    application :
        name : api-gateway
    cloud :
        gateway :
            routes :
                # Routing id (optional)
                - id : user-service-route
                  # Address of proxy service
#                  uri: http://localhost:9091 # mode 1
                  uri : lb://User service # mode 2
                  # Route assertions, mapping paths that can be configured
                  predicates:
                    - Path=/**
                  filters:
                    - PrefixPath=/user
···

For example: http://localhost:10010/1 ==> http://localhost:9091/user/1 (add / user)

The test can test and check the attribute changes in the following custom filter factory

Custom local filter

The Spring Cloud Gateway filter factory edits / validates requests during the process of request delivery. (application scenarios generally include authentication, selecting micro services specified in the cluster, etc

Example

explain:

  • The custom filter factory needs to inherit the AbstractGatewayFilterFactory class, override the apply() method, and the filter class name is suffixed with GatewayFilterFactory
  • Test request parameters are displayed on the console
  1. Create a custom local filter (MyParamGatewayFilterFactory I created)

    package com.sans.gateway.filter;
    
    import org.springframework.cloud.gateway.filter.GatewayFilter;
    import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
    import org.springframework.http.server.reactive.ServerHttpRequest;
    import org.springframework.stereotype.Component;
    
    import java.util.Arrays;
    import java.util.List;
    
    @Component
    public class MyParamGatewayFilterFactory extends AbstractGatewayFilterFactory<MyParamGatewayFilterFactory.Config> {
        
        /**Constructor*/
        public MyParamGatewayFilterFactory() {
            super(Config.class);
        }
        /** initialization
         * Read the parameters in the configuration file and assign them to the configuration class
         * */
        @Override
        public List<String> shortcutFieldOrder() {
            //One parameter
            return Arrays.asList("params");
        }
        
        /**Filter logic*/
        @Override
        public GatewayFilter apply(Config config) {
            // Instantiate GatewayFilter.filter()
            //      exchange - Request properties
            //      chain - provides a way to delegate to the next filter
            return (exchange , chain) -> {
                // Front
                ServerHttpRequest request = exchange.getRequest();
                // Execute if the route contains the name parameter
                if (request.getQueryParams().containsKey(config.params)) {
                    request.getQueryParams().get(config.params).forEach((v)->{
                        System.out.printf("Local filter => %s = %s\n",config.params,v);
                    });
                }
        
        /**Read parameters of filter configuration (stored as objects)*/
        public static class Config {
            // Corresponds to the filter parameters configured in the application.yml configuration file
            private String params;
        
            public String getParams() {
                return params;
            }
        
            public void setParams(String params) {
                this.params = params;
            }
        }
        
        
    }
    
  2. Configure application.yml to add custom filters

    spring :
        cloud :
            gateway :
                routes :
                    # Routing id (optional)
                    - id : user-service-route
                      # Address of proxy service
    #                  uri: http://localhost:9091 # mode 1
                      uri : lb://User service # mode 2
                      # Route assertions, mapping paths that can be configured
                      predicates:
                          - Path=/user/**
                      filters:
                          # Add custom filter
                          - MyParam=name
    

    explain:

    • The GatewayFilterFactory suffix can be omitted in the configuration
    • The above corresponding parameter is the List of the specified number of parameters returned by the shortcutFieldOrder() method (I specified above that the List of params is returned)
  3. test

    1. Open Eureka, server and gateway services in turn
    2. visit http://localhost:10010/user/1?name=Sans

    After accessing, the console will print. If the parameter name does not match, it will not print

Custom global filter

Global filter works on all routes without other configuration!!! Generally, it is used for unified permission verification, security verification and other functions

Example

explain:

  • The global filter needs to implement the GlobalFilter interface
  • The filter order needs to implement the value specified by the Ordered interface (the smaller the value, the faster)
  • Test whether the request is authorized. Judge whether the request header of token is included
  1. Create a custom global filter (MyGlobalFilter I created)

    package com.sans.gateway.filter;
    
    import org.apache.commons.lang.StringUtils;
    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;
    
    @Component
    public class MyGlobalFilter implements GlobalFilter, Ordered {
        
        @Override
        public Mono<Void> filter(ServerWebExchange exchange , GatewayFilterChain chain) {
            System.out.println("=================Global filter MyGlobalFilter=================");
            
            String token = exchange.getRequest().getHeaders().getFirst("token");
            if (StringUtils.isBlank(token)) {
                // Set the response status code to unauthorized 401
                exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
                return exchange.getResponse().setComplete();
            }
            
            return chain.filter(exchange);
        }
        
        /**Set filter priority*/
        @Override
        public int getOrder() {
            return 1;
        }
    }
    
  2. Test (because the request header needs to be added to the request)

    1. Open Eureka, server and gateway services in turn
    2. Through the following IDEA built-in HTTP test, there are examples below

    Note: data will be returned if the request succeeds; 401 (unauthorized) will be returned if the request fails

IDEA built in HTTP debugging

  1. Create a test HTTP request draft file

  2. Set request url test

    There are functions such as example viewing and usage

Cross domain configuration

Cross domain: when any one of the protocol / domain name / port requesting the URL is different from the current page URL, it is called cross domain

Current URLRequested URLCross domainreasoncompare
http://www.test.com/http://www.test.com/index.htmlN--
http://www.test.com/https://www.test.com/index.htmlYDifferent agreementhttp/https
http://www.test.com/http://www.baidu.com/YThe primary domain name is differenttest/baidu
http://www.test.com/http://blog.test.com/YSubdomain name is differentwww/blog
http://www.test.com:8080/http://www.test.com:7001/YDifferent port numbers8080/7001

This cross domain problem can be configured in the Gateway gateway server. The configuration is as follows:

spring :
    application :
        name : api-gateway
    cloud :
        gateway :
            globalcors :
                cors-configurations :
                    # Represents the addresses on all access gateway servers
                    '[/**]' :
                    	# Allow access to the specified server address 
#                        allowedOrigins : *     # *Access is supported on behalf of all
                        allowedOrigins :
                            - "http://demo.sans.top"
                        allowedMethods :
                            - GET

The above configuration allows from http://demo.sans.top GET service data from GET request

Official details: CORS Configuration (spring.io)

Load balancing & fuses

The Gateway integrates Ribbon and Hystrix by default (the same is true for the configuration policy). If there are other policy configurations, click the link to learn about the relevant configurations

Difference between Gateway and Feign

GatewayFeign
Interface entryUnified service entranceSingle microservice portal
Interface securityInterface concealment applicationInterface exposure application
Routing processingCan handleInherent. Cannot handle
Application scenarioPermission check and flow controlInternal invocation of microservices is more convenient

Topics: Java Spring Cloud gateway