Springclub06 zuul API gateway

Time:2021-1-13

1. Unified call entry

Zuul API gateway provides a unified external access interface for microservice applications. Zuul also provides a filter to provide unified request verification for all micro services.

1.1 new SP11 zuul project

Springclub06 zuul API gateway

1.2 add dependency

Springclub06 zuul API gateway

1.2.1 pom.xml

  • Need to add SP01 commons dependency
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>cn.tedu</groupId>
    <artifactId>sp11-zuul</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>sp11-zuul</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.RELEASE</spring-cloud.version>
    </properties>

    <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>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>cn.tedu</groupId>
            <artifactId>sp01-commons</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

1.3 modification application.yml file

  • Zuul routing configuration can be omitted, and the service ID is used as the access path by default
spring:
  application:
    name: zuul
    
server:
  port: 3001
  
eureka:
  client:
    service-url:
      defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eureka

zuul:
  routes:
    item-service: /item-service/**
    user-service: /user-service/**
    order-service: /order-service/**

1.4 main program addition@EnableZuulProxyannotation

package cn.tedu.sp11;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@EnableZuulProxy
@EnableDiscoveryClient
@SpringBootApplication
public class Sp11ZuulApplication {
    public static void main(String[] args) {
        SpringApplication.run(Sp11ZuulApplication.class, args);
    }
}

1.5 start up project

Springclub06 zuul API gateway

2. Unified authority verification

The gateway adds a permission judgment code. The background service does not need to judge the permission any more. It only focuses on the business. Zuul can provide a filter, inherit the filter, and add permission judgment in the subclass

2.1 define filter, inherit zuulfilter and add @ Component annotation

New filter class in SP11 zuul project

package com.tedu.sp11.filter;
import cn.tedu.web.util.JsonResult;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.commons.lang.StringUtils;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
@Component
public class AccessFilter extends ZuulFilter {
    //Filter types: pre, post, routing, error
 @Override
 public String filterType() {
        //Return "pre"; // prefilter
 return FilterConstants.PRE_TYPE;
    }
    //Position of filter insertion
 @Override
 public int filterOrder() {
        Return 6; // put it in the sixth position
 }
    //Judge the user request and execute the filtering code
 @Override
 public boolean shouldFilter() {
        //Only the item service call is filtered. If user service and order service are called, the filtering code is not executed
 //Gets the ID of the calling service
 RequestContext context=RequestContext.getCurrentContext();
        String serviceId= (String) context.get(FilterConstants.SERVICE_ID_KEY);
        return "item-service".equalsIgnoreCase(serviceId);
    }
    //Filter code
 @Override
 public Object run() throws ZuulException {
        //Get the request object
 RequestContext context=RequestContext.getCurrentContext();
        HttpServletRequest request=context.getRequest();
        //Token parameter received
 String token=request.getParameter("token");
        //If not, block access and return the response directly to the client
 if (StringUtils.isBlank(token)){
            //Prevent further access
 context.setSendZuulResponse(false);
            //Return the response jsonresult to the client{ code:401 , msg:not ,login, data:null } String json= JsonResult.err ().code( JsonResult.NOT_ LOGIN).msg("not login").toString();
            context.addZuulResponseHeader("Content-Type","application/json;charset=UTF-8" );
            context.setResponseBody(json);
        }
        Return null; // the return value has no effect
 }
}

2.2 access test

3. Zuul integrated ribbon

3.1 zuul + ribbon load balancing

Zuul has integrated ribbon, and load balancing has been realized by default

3.2 zuul + ribbon retrying

3.2.1 pom.xml Add spring retry dependency

  • Spring retry dependency required
<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
</dependency>

3.2.2 configure zuul to start retrying, and configure ribbon retrying parameters

  • It needs to be turned on and tried again. It is not turned on by default zuul:retryable : true
spring:
  application:
    name: zuul
    
server:
  port: 3001
  
eureka:
  client:
    service-url:
      defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eureka

zuul:
  retryable: true

#  routes:
#    item-service: /item-service/**
#    user-service: /user-service/**
#    order-service: /order-service/**
    
ribbon:
  ConnectTimeout: 1000
  ReadTimeout: 1000
  MaxAutoRetriesNextServer: 1
  MaxAutoRetries: 1

4. Zuul integrates hystrix

0 configuration, hystrix has been enabled

4.1 zuul + hystrix

4.1.1 create degraded class

  • Getroute() method specifies the service ID to apply this degraded class. Asterisk or null value can be used to configure all services
ItemServiceFallback
package com.tedu.sp11.fallback;
import cn.tedu.web.util.JsonResult;
import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
@Component
public class ItemFB implements FallbackProvider {
    //Returns a service ID to demote the specified service
 //Return "*" or null, and apply the degraded class to all services
 @Override
 public String getRoute() {
        return "item-service";
    }
    //Demote the response and return a response object that encapsulates the response data
 @Override
 public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
        return new ClientHttpResponse() {
            @Override
 public HttpStatus getStatusCode() throws IOException {
                return HttpStatus.OK;
            }
            @Override
 public int getRawStatusCode() throws IOException {
                return HttpStatus.OK.value();
            }
            @Override
 public String getStatusText() throws IOException {
                return HttpStatus.OK.getReasonPhrase();
            }
            @Override
 public void close() {
            }
            @Override
 public InputStream getBody() throws IOException {
                //JsonResult{ code:401 , MSG: failed to call commodity, data:null }
 String json =  JsonResult.err (). MSG ("call commodity failed"). Tostring();
                return new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8));
            }
            @Override
 public HttpHeaders getHeaders() {
                //content-Type:application/json;charset=UTF-8
 HttpHeaders headers = new HttpHeaders();
                headers.add("content-Type", "application/json;charset=UTF-8");
                return headers;
            }
        };
    }
}
OrderServiceFallback
package com.tedu.sp11.fallback;
import cn.tedu.web.util.JsonResult;
import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
@Component
public class OrderFB implements FallbackProvider {
    //Returns a service ID to demote the specified service
 //Return "*" or null, and apply the degraded class to all services
 @Override
 public String getRoute() {
        return "order-service";
    }
    //Demote the response and return a response object that encapsulates the response data
 @Override
 public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
        return new ClientHttpResponse() {
            @Override
 public HttpStatus getStatusCode() throws IOException {
                return HttpStatus.OK;
            }
            @Override
 public int getRawStatusCode() throws IOException {
                return HttpStatus.OK.value();
            }
            @Override
 public String getStatusText() throws IOException {
                return HttpStatus.OK.getReasonPhrase();
            }
            @Override
 public void close() {
            }
            @Override
 public InputStream getBody() throws IOException {
                //JsonResult{ code:401 , MSG: failed to call commodity, data:null }
 String json =  JsonResult.err (). MSG ("call order service failed"). Tostring();
                return new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8));
            }
            @Override
 public HttpHeaders getHeaders() {
                //content-Type:application/json;charset=UTF-8
 HttpHeaders headers = new HttpHeaders();
                headers.add("content-Type", "application/json;charset=UTF-8");
                return headers;
            }
        };
    }
}

4.2 reduce the hystrix timeout to test degradation

spring:
  application:
    name: zuul
    
server:
  port: 3001
  
eureka:
  client:
    service-url:
      defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eureka

zuul:
  retryable: true
    
ribbon:
  ConnectTimeout: 1000
  ReadTimeout: 2000
  MaxAutoRetriesNextServer: 1
  MaxAutoRetries: 1
  
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 500

4.3 start the service and test the degradation

http://localhost:3001/item-service/35
Springclub06 zuul API gateway

5. Zuul + hystrix data monitoring

5.1 exposure hystrix.stream Monitor endpoints

  • Zuul already contains the actor dependency
management:
  endpoints:
    web:
      exposure:
        include: hystrix.stream

5.2 start monitoring

Start SP08 hystrix dashboard, fill in zuul’s monitoring endpoint path, and start monitoring
http://localhost:4001/hystrix
Fill in monitoring endpoint:
http://localhost:3001/actuator/hystrix.stream
Springclub06 zuul API gateway
It is necessary to access the background service through zuul gateway to monitor the data

6. Zuul + turbo aggregation monitoring

6.1 modify the turbo project to aggregate zuul service instances

 spring:
  application:
    name: turbin
    
server:
  port: 5001
  
eureka:
  client:
    service-url:
      defaultZone: http://eureka1:2001/eureka, http://eureka2:2002/eureka
      
turbine:
  app-config: order-service, zuul
  cluster-name-expression: new String("default")
  • Using the hystrix dashboard to monitor the turbo monitoring endpoint, which aggregates the monitoring data of order service and Zull gateway service
    http://localhost:5001/turbine.stream

Springclub06 zuul API gateway

6.2 fusing test

ab -n 20000 -c 50 http://localhost:3001/order-service/123abc

Springclub06 zuul API gateway

7. Zuul cookie filtering

Zuul filters sensitive HTTP protocol headers. By default, it filters the following protocol headers:

  • Cookie
  • Set-Cookie
  • Authorization

You can set zuul not to filter these protocol headers

zuul:
  sensitive-headers:

8. The difference between zuul and feign

  • Call remote service
  • Integrated ribbon
  • Integrating hystrix
  • Zuul gateway, as an independent service, is deployed at the front of the system

    • Enable retry is not recommended
    • If you try again at the front, you will double the access pressure of all servers in the background
  • Feign – call between services within the business micro service system

    • Enabling hystrix is not recommended
    • It can cause chaos

Recommended Today

Introduction to vernacular spring cloud

First of all, let me show you a picture. If you don’t understand this picture very well, I hope you will suddenly realize it after reading my article. What is spring cloud Building a distributed system doesn’t need to be complex and error prone. Spring cloud provides a simple and easy to accept programming model […]