1. Zuul profile

API gateway provides a unified access for services in microservices architecture. Clients access related services through API gateway. The DEFINITION of an API gateway is similar to the facade pattern in design pattern, which is equivalent to the facade in the entire microservices architecture through which all client access is routed and filtered. It realizes the functions of request routing, load balancing, check filtering, service fault tolerance, service aggregation and so on.

2. Create the Spring Cloud Zuul project

2.1 Adding related dependencies to poM


      
<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>spring-cloud-demo</artifactId>
        <groupId>com.hxmec</groupId>
        <version>1.0 the SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>spring-cloud-zuul</artifactId>

    <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-netflix-zuul</artifactId>
        </dependency>
    </dependencies>


</project>
Copy the code

2.2 Adding a Configuration File

The bootstrap.yml configuration is as follows

server:
  port: 9200
spring:
  application:
    name: zuul-proxy
eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://localhost:8888/eureka/
Copy the code

Application. Yml configuration is as follows:

zuul:
  routes: Configure a route for the service
    eureka-client-provider:
      path: /provider/**
    eureka-client-consumer:
      path: /consumer/**
Copy the code

2.3 Creating the startup class ZuulApplication

The startup class code is as follows:

@EnableZuulProxy
@EnableDiscoveryClient
@SpringBootApplication
public class ZuulApplication {

    public static void main(String[] args) { SpringApplication.run(ZuulApplication.class, args); }}Copy the code

2.4 Start the program and test it

Start the spring-Cloud-Eureka-Server, spring-Cloud-Eureka-client-provider, Spring-Cloud-Eureka-client-consumer and gateway Zuul projects created in the paper before.

The test address is as follows:

  • http://localhost:9200/provider/demo/hello
  • http://localhost:9200/consumer/test/callHello

3. Common functions of Zuul

3.1 Configuring Routing Rules

We can configure routing rules by modifying the configuration in application.yml, where we route requests matching /provider/** to the Eureka-client-provider service. Requests matching /consumer/** are routed to eureka-client-consumer.Copy the code

The configuration is as follows:

zuul:
  # Disable default route configuration
  ignored-services: eureka-client-provider,eureka-client-consumer
  routes: Configure a route for the service
    eureka-client-provider:
      path: /provider/**
    eureka-client-consumer:
      path: /consumer/**
Copy the code

Visit http://localhost:9200/provider/demo/hello routing to eureka – the client – the provider; Visit http://localhost:9200/consumer/test/callHello can route to the same eureka – the client – the consumer.

3.2 Configuring access Prefixes

Configuration is as follows

zuul:
  Configure the unified access prefix
  prefix: /zuul
  routes: Configure a route for the service
    eureka-client-provider:
      path: /provider/**
    eureka-client-consumer:
      path: /consumer/**
Copy the code

All requests unified prefix need plus/zuul visit http://localhost:9200/zuul/provider/demo/hello routing to eureka – the client – the provider;

3.3 Header Filtering and Redirection Adding a Host

  • By default, Zuul filters out some sensitive headers when requesting routes. The following configuration prevents loss of cookies and Authorization during routing:
zuul:
  sensitive-headers: Cookie,Set-Cookie,Authorization # configure filter sensitive request headers. Set this parameter to null
Copy the code
  • Zuul does not set the initial host header when requesting a route.
zuul:
  add-host-header: true # Redirection set to true will add the host header
Copy the code

3.4 Viewing Routing Information

You can use the SpringBoot Actuator to view routing information in Zuul.

  • Add dependencies to pom.xml:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Copy the code
  • Added enabling the endpoint configuration of viewing routes
# Endpoint of the route
management:
  endpoints:
    web:
      exposure:
        include: 'routes'
Copy the code
  • Simply visit http://localhost:9200/actuator/routes to see by routing information

  • By visiting http://localhost:9200/actuator/routes/details to check the detailed routing information

4. The filter

Routing and filtering are two core functions of Zuul. Routing is responsible for forwarding external requests to specific service instances and is the basis of unified access, while filtering is responsible for additional processing of the request process and is the basis of request verification and filtering and service aggregation.

4.1 Filter Types

Zuul filters have the following types:

  • Pre: performs functions such as permission verification and log printing before the request is routed to the target service.
  • Routing: Performed when the request is routed to the target service, which is where the original HTTP request is built and sent using Apache HttpClient or Netflix Ribbon;
  • Post: After the request is routed to the target service, such as adding header information to the response of the target service, collecting statistics, etc.
  • Error: The request is executed when an error occurs at another stage.

4.2 Filter life cycle

The Filter has four life cycles, namely “PRE”, “ROUTING”, “POST”, and “ERROR”. The whole life cycle can be shown in the following figure

Zuul implements most of its functionality through filters that correspond to the typical lifecycle of a request.

  • PRE: This filter is invoked before the request is routed. We can use this filter to authenticate, select requested microservices in the cluster, log debugging information, and so on.
  • ROUTING: This filter routes the request to the microservice. This filter is used to build requests sent to microservices and request microservices using Apache HttpClient or Netfilx Ribbon.
  • POST: This filter is executed after routing to the microservice. Such filters can be used to add standard HTTP headers to responses, collect statistics and metrics, send responses from microservices to clients, and so on.
  • ERROR: This filter is executed when errors occur in other phases.

4.3 Customizing Filters

In Zuul Gateway, we need to define a class that inherits the ZuulFilter abstract class and implements the four corresponding abstract methods.

In the following example, we define a custom AccessTokenFilter to verify that the request has accessToken parameters:

@Component
@Slf4j
public class AccessTokenFilter extends ZuulFilter {

    /** * Filter type pre means intercept before request *@return* /
    @Override
    public String filterType(a) {
        return "pre";
    }

    /** * Filter execution order. When a request has multiple filters at one stage, you need to execute * in sequence based on the return value of this method@return* /
    @Override
    public int filterOrder(a) {
        return 0;
    }

    /** * Check whether the filter takes effect *@return* /
    @Override
    public boolean shouldFilter(a) {
        return true;
    }

    @Override
    public Object run(a) throws ZuulException {
        // Get the context
        RequestContext currentContext = RequestContext.getCurrentContext();
        HttpServletRequest request = currentContext.getRequest();
        String accessToken = request.getParameter("accessToken");
        if (StringUtils.isEmpty(accessToken)) {
            //setSendZuulResponse(false) causes Zuul to filter the request without routing it
            currentContext.setSendZuulResponse(false);
            // Set the error code returned
            currentContext.setResponseStatusCode(401);
            currentContext.setResponseBody("AccessToken is null");
            return null;
        }
        log.info("Get AccessToken as {}",accessToken);
        // Otherwise, execute the service logic.....
        return null; }}Copy the code

Verify that the Zuul service is valid after being restarted

In the filter code implemented above, we implement our custom filter by inheriting the ZuulFilter abstract class and rewriting the following four methods. The four methods define:

  • FilterType () : The type of filter that determines in which lifecycle of the request the filter is executed. This is defined as pre, which means that the request will be executed before it is routed.
  • FilterOrder () : filter execution order. When requests have multiple filters in a phase, they need to be executed sequentially based on the value returned by this method. The value is specified by a number. A larger number indicates a lower priority.
  • ShouldFilter () : Check whether this filter needs to be executed. Here we return true directly, so the filter will apply to all requests. In practice, we can use this function to specify the effective range of the filter.
  • Run () : specifies the logic of the filter. . Here we through currentContext setSendZuulResponse (false) make Zuul filtering the request, does not carry on the route, Then through currentContext. SetResponseStatusCode (401) set up the return error code, of course we can also further optimize our return, Such as through currentContext. SetResponseBody (body) to return to the body content editing, etc.

4.4 Core Filter

Some default filters are provided in Zuul

type The order The filter function
pre – 3 ServletDetectionFilter The tag handles the type of Servlet
pre 2 – Servlet30WrapperFilter Wrap the HttpServletRequest request
pre – 1 FormBodyWrapperFilter Wrapping request body
pre 5 PreDecorationFilter The current request is preprocessed for subsequent operations.
pre 1 DebugFilter Debugging flag
route 10 RibbonRoutingFilter ServiceId Forwards the request
route 500 SendForwardFilter Forward request forwarding
route 100 SimpleHostRoutingFilter Url Request forwarding
post 900 LocationRewriteFilter Rewrite the Location header to Zuul’s URL
post 0 SendErrorFilter Handle request responses with errors
post 1000 SendResponseFilter Process normal request responses

4.5 Ribbon and Hystrix support

Zuul already has load balancing and service fault tolerance capabilities because it integrates the Ribbon and Hystrix. You can configure Zuul with the Ribbon and Hystrix.

  • You can use the Hystrix configuration to set the timeout period for HystrixCommand execution during route forwarding:
hystrix:
  command: # used to control HystrixCommand behavior
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 1000 HystrixCommand: HystrixCommand: HystrixCommand: HystrixCommand: HystrixCommand: HystrixCommand
Copy the code
  • You can use the Ribbon configuration to set the timeout for connection requests and processing in routing forwarding:
ribbon: # global configuration
  ConnectTimeout: 1000 Service request connection timeout (ms)
  ReadTimeout: 3000 Service request processing timeout (ms)
Copy the code

4.6 Using Zuul to Limit Traffic

Add dependencies:

<dependency>
    <groupId>com.marcosbarbero.cloud</groupId>
    <artifactId>spring-cloud-zuul-ratelimit</artifactId>
    <version>${latest-version}</version>
</dependency>
Copy the code

Redis is used as the data store in this article. Other storage references are: github.com/marcosbarbe…

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
Copy the code

Spring-cloud-zuul-ratelimit is an extension of the distributed traffic limiting policy that zuul and Spring-cloud-Zuul-ratelimit integrate to provide distributed traffic limiting policy. You only need to configure a few lines in YML to enable the application to support traffic limiting:

ratelimit:
  enabled: true
  repository: REDIS Use redis for storage, always capitalize!
  policies:
    eureka-client-provider: # limit traffic for the above service
      limit: 100 # How many requests per second
      quota: 20 #quota specifies the total time allowed per request.
      refreshInterval: 60 # Time to refresh the time window, default (seconds)
      type:
        - ORIGIN URL by request path, ORIGIN by client IP address, USER by login USER name, including anonymous USER
Copy the code

Ratelimit supports the following flow limiting granularity:

  • Service granularity (default, traffic limiting for the current service module)
  • User granularity (see summary at the end of this article for details
  • ORIGIN granularity (ORIGIN requested by the user as granularity control)
  • Interface granularity (request the address of the interface as granularity control)
  • The above granularity is freely combined and can support a variety of situations
  • If that’s not enough, customize the RateLimitKeyGenerator implementation.

Supported storage modes:

  • InMemoryRateLimiter – Uses ConcurrentHashMap as the data store
  • ConsulRateLimiter – Use Consul for data storage
  • RedisRateLimiter – Uses Redis as the data store
  • SpringDataRateLimiter – Uses the database as the data store

5. Test project address

Github.com/ty197287300…