Spring Cloud Framework Learning-Spring Cloud Zuul

1. Basic introduction

Since the address of each microservice may change, it is impossible to directly announce the address of these services. Based on the design of security, high cohesion and low coupling, it is necessary for us to separate the internal system from the external system. A component dedicated to handling external requests is required, which is the service gateway. The definition of the API gateway is similar to the Facade pattern in the object-oriented design pattern. Like the facade of the entire microservice architecture system, all external client access needs to be scheduled and filtered through it. The API gateway needs to implement functions such as request routing, load balancing, verification filtering, fuse mechanism when request forwarding, and service aggregation.

In Spring Cloud, there are two main implementations of API Gateway: Zuul and Spring Cloud Gateway. Spring Cloud Zuul is an API gateway component implemented based on Neflix Zuul. Features that Zuul has:

  • As a unified entrance of the system, it shields the details of each microservice in the system
  • Implement interface permission verification
  • monitor
  • dynamic routing
  • load balancing
  • Static resource handling

The functions in Zuul are basically implemented based on filters. There are several different types of filters, namely:

  • pre: can be called before the request is routed
  • routing: called when routing requests
  • post: called after the routing and error filters
  • error: Called when an error is sent while processing the request

2. Example of use

2.1 Basic use

Use the Eureka service and Provider service created in the previous article. Spring Cloud Framework Learning - Registration Center Spring Cloud Eureka

Create a new Spring Boot project named Zuul, use Spring Boot version 2.2.4, add the following dependencies to 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 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.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>


    <groupId>top.javahai.spring.cloud</groupId>
    <artifactId>zuul</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>zuul</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR6</spring-cloud.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <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>
        </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>

Add the annotation @EnableZuulProxy to the startup class to enable Zuul's API gateway proxy:

@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {
    
    

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

Configure the basic information of the current Zuul service in application.properties

#服务名
spring.application.name=zuul
#服务端口号
server.port=2020
#注册中心url地址
eureka.client.service-url.defaultZone=http://localhost:1111/eureka

Start the registration center, provider service and zuul service, check whether the service is started successfully on the registration center management interface,
insert image description here
and then request the address: http://localhost:2020/v1/provider/hello , and the provider service can be accessed through the Zuul proxy.
insert image description here

2.2 Routing and Forwarding Configuration

Configure routing rules in application.properties

zuul.routes.provider.path=/provider-test/**
zuul.routes.provider.service-id=provider

Through the above configuration, requests that meet the matching rule of /provider-test/** are defined and will be forwarded to the provider service for processing.
insert image description here

The above two lines of configuration for configuring routing rules can also be simplified into one line of configuration

zuul.routes.provider=/provider-test/**

Through the following configurations, requests that meet the rules can be routed and forwarded to specific URLs. Where api-test-url is the route name,The routing names of a set of path and url mapping relationships must be the same

zuul.routes.api-test-url.path=/api-test/**
zuul.routes.api-test-url.url=http://localhost:8080/

2.3 Request filtering configuration

When each client user requests the interface provided by the microservice application, their access rights are often limited, and the system will not open all the microservice interfaces to them. This requires uniform implementation of the requested permission verification in the gateway. In Zuul, we only need to inherit the ZuulFilter abstract class and implement the four abstract methods defined by it to complete the interception and filtering of requests.

The following implements a simple Zuul filter to check whether there are username and password parameters in the HttpServletRequest and whether they meet the requirements before request filtering. If it is satisfied, it will be routed, otherwise it will deny access and return a 401 error.

//注册到Spring容器中
@Component
public class PermissionFilter extends ZuulFilter {
    
    
    /**
     * 过滤器类型,它决定过滤器在请求的哪个生命周期中执行。
     * 权限判断一般是pre,pre代表在请求被路由之前执行
     * @return
     */
    @Override
    public String filterType() {
    
    
        return "pre";
    }

    /**
     * 过滤器的执行顺序。当请求一个阶段存在多个过滤器时,需要根据该方法返回的值来依次执行
     * @return
     */
    @Override
    public int filterOrder() {
    
    
        return 0;
    }

    /**
     * 判断该过滤器是否需要执行。可以通过该方法来指定过滤器的有效范围
     * @return
     */
    @Override
    public boolean shouldFilter() {
    
    
        return true;
    }

    /**
     * 核心过滤逻辑
     * @return
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {
    
    
        RequestContext ctx = RequestContext.getCurrentContext();
        //获取当前请求
        HttpServletRequest request = ctx.getRequest();
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        //如果请求条件不满足的话,直接从这里给出响应
        if (!"admin".equals(username) || !"123".equals(password)) {
    
    
            //设置不进行路由
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
            ctx.addZuulResponseHeader("content-type","text/html;charset=utf-8");
            ctx.setResponseBody("非法访问");
        }
        return null;
    }
}

Restart Zuul and then send the request with username and password parameters, otherwise the request will not pass.
insert image description here
Send request with username and password parameters
insert image description here

3. More configuration

3.1 Ignoring paths

By default, after Zuul is registered on Eureka, all registered services on Eureka will be automatically proxied. If you don't want to
act as a proxy for a certain service, you can ignore the service and configure it as follows:

zuul.ignored-services=provider

The above configuration indicates that the provider service is ignored, and the provider service will not be automatically proxied at this time.

Ignore a class of addresses:

zuul.ignored-patterns=/**/hello/**

This means that if the request path contains hello, it will not be a proxy

3.2 Set routing prefix

We can globally add prefix information to routing rules through the zuul.prefix parameter, and add a prefix configuration example to routing:

zuul.prefix=/v1

In this way, all request addresses need to be prefixed with /v1
insert image description here

3.3 Path matching rules

The path matching expression is defined in the Ant style, and the Ant style path expression has a total of three wildcards. They are:

wildcard illustrate
matches any single character
* Matches any number of characters, does not support multi-level directories (for example, /user-service/* cannot match /user-service/a/b)
** Match any number of characters, support multi-level directories

3.4 Hystrix and Ribbon configuration

#设置API网关中路由转发请求的hystrixCommand执行超时时间,单位为毫秒
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=
#设置路由转发请求的时候,创建请求连接的超时时间
ribbon.ConnectTimeOut=
#设置路由转发请求的超时时间
ribbon.ReadTimeout=

Reference:
1. "Spring Cloud Microservice Actual Combat"

Guess you like

Origin blog.csdn.net/huangjhai/article/details/127154505