Spring Cloud框架学习-Spring Cloud Zuul

大数据35

1. 基本介绍

由于每一个微服务的地址都有可能发生变化,无法直接对外公布这些服务地址,基于安全以及高内聚低耦合等设计,我们有必要将内部系统和外部系统做一个切割。需要一个专门用来处理外部请求的组件,就是服务网关。API网关的的定义类似于面向对象设计模式中的Facade模式,像是整个微服务架构系统的门面一样,所有的外部客户端访问都需要经过它来调度和过滤。API网关需要实现请求路由,负载均衡,校验过滤,请求转发时的熔断机制,服务的聚合等功能。

Spring Cloud 中,API网关主要有两种实现方案:Zuul和Spring Cloud Gateway。Spring Cloud Zuul是基于Neflix Zuul实现的API网关组件。Zuul 具备的功能:

  • 作为系统的统一入口,屏蔽系统内部各个微服务的细节
  • 实现接口权限校验
  • 监控
  • 动态路由
  • 负载均衡
  • 静态资源处理

Zuul 中的功能基本上都是基于过滤器来实现,它的过滤器有几种不同的类型,分别是:

  • pre:可以在请求被路由之前调用
  • routing:在路由请求时被调用
  • post:在routing和error过滤器之后被调用
  • error:处理请求时发送错误时被调用

2. 使用示例

2.1 基本使用

沿用之前文章所创建的Eureka服务和Provider服务。Spring Cloud框架学习-注册中心Spring Cloud Eureka

新创建名为Zuul的Spring Boot项目,使用Spring Boot版本2.2.4,pom.xml添加如下依赖:


<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.0modelVersion>
    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.2.6.RELEASEversion>
        <relativePath/>
    parent>

    <groupId>top.javahai.spring.cloudgroupId>
    <artifactId>zuulartifactId>
    <version>0.0.1-SNAPSHOTversion>
    <name>zuulname>
    <description>Demo project for Spring Bootdescription>
    <properties>
        <java.version>1.8java.version>
        <spring-cloud.version>Hoxton.SR6spring-cloud.version>
    properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
        dependency>

        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-netflix-zuulartifactId>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
    dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-dependenciesartifactId>
                <version>${spring-cloud.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>
        dependencies>
    dependencyManagement>

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

在启动类上添加注解@EnableZuulProxy开启Zuul的API网关代理:

@SpringBootApplication
@EnableZuulProxy
public class ZuulApplication {

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

在application.properties中配置当前Zuul服务的基础信息


spring.application.name=zuul

server.port=2020

eureka.client.service-url.defaultZone=http://localhost:1111/eureka

启动注册中心,provider服务和zuul服务,在注册中心管理界面查看服务是否启动成功
Spring Cloud框架学习-Spring Cloud Zuul
然后请求地址:http://localhost:2020/v1/provider/hello,通过Zuul的代理可以访问到provider服务。
Spring Cloud框架学习-Spring Cloud Zuul

; 2.2 路由转发配置

在application.properties中配置路由规则

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

通过上面的配置定义了满足/provider-test/**这个匹配规则的请求,将会转发到provider服务上处理。
Spring Cloud框架学习-Spring Cloud Zuul

上面配置路由规则的两行配置还可以简化成一行配置

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

通过以下配置可以实现满足规则的请求路由转发到具体的URL上。其中api-test-url为路由名,一组path和url映射关系的路由名必须相同。

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

2.3 请求过滤配置

每个客户端用户请求微服务应用提供的接口时,它们的访问权限往往都有一定的限制,系统不会将所有的微服务接口都对它们开放。这就需要要网关中统一实现请求的权限校验。在Zuul中我们只需要继承ZuulFilter抽象类并实现它定义的4个抽象方法就可以完成对请求的拦截和过滤了。

下面实现一个简单的Zuul过滤器,实现在请求过滤之前检查HttpServletRequest中是否有username和password参数且是否满足要求。如满足则进行路由,否则就拒绝访问,返回401错误。


@Component
public class PermissionFilter extends ZuulFilter {

    @Override
    public String filterType() {
        return "pre";
    }

    @Override
    public int filterOrder() {
        return 0;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @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;
    }
}

重启Zuul接下来发送请求就必须带上username 和 password 参数,否则请求不通过。
Spring Cloud框架学习-Spring Cloud Zuul
带上username 和 password 参数发送请求
Spring Cloud框架学习-Spring Cloud Zuul

3. 更多配置

3.1 忽略路径

默认情况下,Zuul 注册到 Eureka 上之后,Eureka 上的所有注册服务都会被自动代理。如果不想给某
一个服务做代理,可以忽略该服务,配置如下:

zuul.ignored-services=provider

上面这个配置表示忽略 provider 服务,此时就不会自动代理 provider 服务了

忽略某一类地址:

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

这个表示请求路径中如果包含 hello,则不做代理

3.2 设置路由前缀

我们可以通过zuul.prefix参数全局地为路由规则增加前缀信息,给路由添加前缀的配置示例:

zuul.prefix=/v1

这样所有的请求地址都需要添加前缀/v1
Spring Cloud框架学习-Spring Cloud Zuul

3.3 路径匹配规则

路径匹配的表达式采用了Ant风格定义,Ant风格的路径表达式一共有三种通配符。分别是:

通配符说明?匹配任意单个字符匹配任意数量的字符,不支持多级目录(例如/user-service/无法匹配/user-service/a/b)**匹配任意数量的字符,支持多级目录

3.4 Hystrix和Ribbon配置


hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=

ribbon.ConnectTimeOut=

ribbon.ReadTimeout=

参考:
1.《Spring Cloud微服务实战》

Original: https://blog.csdn.net/huangjhai/article/details/127154505
Author: Code0cean
Title: Spring Cloud框架学习-Spring Cloud Zuul