Zuul包含了对请求的路由和过滤两个最主要的功能:

其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础而过滤器功能则负责对请求的处理过程进行干预,是实现请求校验、服务聚合等功能的基础.

Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他微服务的消息,也即以后的访问微服务都是通过Zuul跳转后获得.

注意:Zuul服务最终还是会注册进Eureka

一、maven依赖

如果想要安全就需要导入security依赖

  1. <dependency>
  2. <groupId>org.springframework.cloud</groupId>
  3. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>org.springframework.cloud</groupId>
  7. <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
  8. </dependency>
  9. <!--<dependency>
  10. <groupId>org.springframework.boot</groupId>
  11. <artifactId>spring-boot-starter-security</artifactId>
  12. </dependency>-->

二、application.properties配置文件

给别名为provider的服务进行代理 ,如下编写配置文件后路径abc就可以代表provider服务的地址了

有几种写法

1.最简单的方法

# 端口
server.port=10900
# 应用别名
spring.application.name=apigateway-zuul
eureka.client.service-url.defaultZone=http://user:123@localhost:8761/eureka/,http://user:123@localhost:8762/eureka/,http://user:123@localhost:8763/eureka/
eureka.instance.prefer-ip-address=true
# 配置zuul路由映射
# 给指定的服务做映射 比如当前是给provider 添加映射地址
zuul.routes.provider=/abc/**
# 不让zuul代理的服务 多个服务以逗号分隔
zuul.ignored-services=consumer

2.通过path映射

# 端口
server.port=10900
# 应用别名
spring.application.name=apigateway-zuul
eureka.client.service-url.defaultZone=http://user:123@localhost:8761/eureka/,http://user:123@localhost:8762/eureka/,http://user:123@localhost:8763/eureka/
eureka.instance.prefer-ip-address=true
# 配置zuul路由映射
# 给指定的服务做映射 比如当前是给provider 添加映射地址
# 给哪个服务做映射 相当于 zuul.routes.provider=/abc/**
zuul.routes.abcd.service-id=provider
zuul.routes.abcd.path=/abc/***
# 不让zuul代理的服务 多个服务以逗号分隔
zuul.ignored-services=consumer

3.通过url映射

# 端口
server.port=10900
# 应用别名
spring.application.name=apigateway-zuul
eureka.client.service-url.defaultZone=http://user:123@localhost:8761/eureka/,http://user:123@localhost:8762/eureka/,http://user:123@localhost:8763/eureka/
eureka.instance.prefer-ip-address=true
# 配置zuul路由映射
# 给指定的服务做映射 比如当前是给provider 添加映射地址
# 以url来配置映射 但是这样就没有负载均衡
zuul.routes.abcd.url=http://localhost:7900
zuul.routes.abcd.path=/abc/***
# 不让zuul代理的服务 多个服务以逗号分隔
zuul.ignored-services=consumer

如果不配置代理路径,访问其他eureka注册的服务的路径就是通过服务名访问,比如/provider

三、启动类

@SpringBootApplication
@EnableZuulProxy
public class ZuulApp {

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

}

四、zuul的fallback

只需要写一个类就行了

/**
 * 定义fallback
 *
 * @author YUDI
 * @date 2020/1/18
 */
@Component
public class MyZuulFallBack implements FallbackProvider {
    /**
     * 给哪一个服务做fallback
     *
     * @return 服务名
     */
    @Override
    public String getRoute() {
        return "provider";
    }

    @Override
    public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
        return new ClientHttpResponse() {
            /**
             * 响应码
             * @return 坏请求
             * @throws IOException 异常
             */
            @Override
            public HttpStatus getStatusCode() throws IOException {
                return HttpStatus.BAD_REQUEST;
            }

            /**
             * 响应码值
             * @return 坏请求的值
             * @throws IOException 异常
             */
            @Override
            public int getRawStatusCode() throws IOException {
                return HttpStatus.BAD_REQUEST.value();
            }

            /**
             * 错误描述
             * @return 字符串
             * @throws IOException 异常
             */
            @Override
            public String getStatusText() throws IOException {
                return HttpStatus.BAD_REQUEST.getReasonPhrase();
            }

            @Override
            public void close() {
            }

            /**
             * 出错时返回的正文
             * @return 字节流
             * @throws IOException 异常
             */
            @Override
            public InputStream getBody() throws IOException {
                return new ByteArrayInputStream((getRoute() + " : 出现错误").getBytes());
            }

            /**
             *
             * @return 响应头
             */
            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_JSON);
                return headers;
            }
        };
    }

}

五、zuul的过滤器

同样只用写一个过滤器

@Component
public class MyZuulFilter extends ZuulFilter {

    /**
     * 类型包含 pre post route error
     * pre 代表在路由代理之前执行
     * route 代表代理的时候执行
     * error 代表在出错的时候执行
     * post 代表在route或error执行完成后执行
     *
     * @return 字符串 pre route error post
     */
    @Override
    public String filterType() {
        return "pre";
    }

    /**
     * filter是一个链式调用 一个filter会调用下面一个filter
     * zuul根据order决定越小的越先执行
     *
     * @return int类型
     */
    @Override
    public int filterOrder() {
        return 1;
    }

    /**
     * 是否使用这个过滤器
     *
     * @return true或false
     */
    @Override
    public boolean shouldFilter() {
        return false;
    }

    /**
     * 过滤器执行的内容
     *
     * @return Object
     * @throws ZuulException 异常
     */
    @Override
    public Object run() throws ZuulException {
        System.out.println("过滤器执行");
        return "过滤器执行";
    }

}

六、zuul的高可用

zuul的高可用非常简单,只用把多个zuul项目注册到eureka项目中即可

Zuul代理 - 图1