一个简单的微服务系统如下图:

1.为什么需要Zuul

Zuul很容易实现 负载均衡、智能路由 和 熔断器,可以做身份认证和权限认证,可以实现监控,在高流量状态下,对服务进行降级。

2.路由网关

继续前面文章的搭建,新建一个Spring Boot工程模块。取名为service-zuul.

1.导入依赖

<?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 http://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>1.5.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.example</groupId>
    <artifactId>service-zuul</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <name>service-zuul</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Dalston.SR1</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zuul</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</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>

2.注解 @EnableZuulProxy 开启路由网关

@EnableZuulProxy //开启路由网关
@EnableEurekaClient
@SpringBootApplication
public class ServiceZuulApplication {

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

3.配置 application.yml

server:
  port: 8769
spring:
  application:
    name: service-zuul
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
zuul:
  routes:
    api-a:
      path: /api-a/**
      serviceId: service-feign
    api-b:
      path: /api-b/**
      serviceId: service-ribbon

首先指定服务注册中心的地址为 http://localhost:8761/eureka/,服务的端口为8769,服务名为 service-zuul,以 /api-a/ 开头的请求都转发给 service-feign 服务,以 /api-b/ 开头的请求都转发给 service-ribbon 服务。

依次运行eureka-server、service-hi、service-ribbon、service-feign、service-zuul工程,其中service-hi以8762端口和8763端口启动两个实例。

打开浏览器访问 http://localhost:8769/api-a/hi?name=mark 两次,浏览器显示.

hi mark,i am from port:8763

hi mark,i am from port:8762

这说明zuul起到了路由的作用。如果某服务存在多个实例,Zuul会结合 Ribbon 做负载均衡,将请求均分的部分路由到不同的服务实例。

3.配置过滤器

Zuul不仅只是路由,并且还能过滤,做一些安全验证。继续改造工程,增加一个Filter Bean.

@Component
public class MyFilter extends ZuulFilter {
    Logger log = LoggerFactory.getLogger(getClass());

    /**
     * 过滤器的类型
     * pre:路由之前
     * routing:路由之时
     * post: 路由之后
     * error:发送错误调用
     */
    @Override
    public String filterType() {
        return "pre";
    }

    /**
     * 过滤的顺序
     */
    @Override
    public int filterOrder() {
        return 0;
    }

    /**
     * 写逻辑判断,是否要过滤
     * true:永远过滤
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    /**
     * 过滤器的具体逻辑。可用很复杂,包括查sql,nosql去判断该请求到底有没有权限访问
     */
    @Override
    public Object run() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        log.info(String.format("%s >>> %s", request.getMethod(), request.getRequestURL().toString()));
        Object accessToken = request.getParameter("token");
        if (accessToken == null) {
            log.warn("token is empty");
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
            try {
                ctx.getResponse().getWriter().write("token is empty");
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
        log.info("ok");
        return null;
    }
}

​ 访问http://localhost:8769/api-b/hi?name=mark

​ token is empty

​ 访问http://localhost:8769/api-b/hi?name=mark&token=123 两次

hi mark,i am from port:8763

hi mark,i am from port:8762

4.配置API前戳版本号

在上面 Zuul 工程 application.yml 的基础上增加一条配置 zuul.prefix: /v1,然后重启 Zuul 工程,访问 http://localhost:8769/v1/api-b/hi?name=mark&token=123 即可。

5.配置熔断器

在 Zuul 实现熔断功能很简单,类似实现过滤器的步骤,只需要实现 ZuulFallbackProvider 接口即可。完整代码.

@Component
public class MyFallbackProvider implements ZuulFallbackProvider {
    /**
     * 指定熔断器用于哪些服务
     */
    @Override
    public String getRoute() {
        return "service-feign";
    }

    /**
     * 熔断时的逻执行代码
     * @return
     */
    @Override
    public ClientHttpResponse fallbackResponse() {
        return new ClientHttpResponse() {
            @Override
            public HttpStatus getStatusCode() throws IOException {
                return HttpStatus.OK;
            }

            @Override
            public int getRawStatusCode() throws IOException {
                return 200;
            }

            @Override
            public String getStatusText() throws IOException {
                return "OK";
            }

            @Override
            public void close() {

            }

            @Override
            public InputStream getBody() throws IOException {
                return new ByteArrayInputStream("oooops!error,I'm the fallback.".getBytes());
            }

            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders httpHeaders = new HttpHeaders();
                httpHeaders.setContentType(MediaType.APPLICATION_JSON);
                return httpHeaders;
            }
        };
    }
}

重新启动 service-zuul 工程,并关闭 service-hi 的所有实例,在浏览器上访问 http://localhost:8769/v1/api-a/hi?name=mark&token=123 显示:

oooops!error,I'm the fallback.

如果需要所有的路由服务都加熔断功能,只需要在 getRoute 方法上返回 “*” 的匹配符即可.

    @Override
    public String getRoute() {
        return "*";
    }

6.Zuul的常见使用方式

Zuul 采用的是异步阻塞模型,性能比 Nginx 差,由于 Zuul 和其他 Netflix 组件相互配合、无缝集成,Zuul 很容易就能实现负载均衡、智能路由和熔断器等功能。在大多数情况下,Zuul 都是以集群的形式存在。

一种常见的使用方式是对不同的渠道使用不同的Zuul来进行路由,例如移动端共用一个 Zuul 网关实例,Web端用另一个 Zuul 网关实例,其他的客户端用另一个Zuul实例进行路由。

另外一种就是常见的集群是通过 Nginx 和 Zuul 相互结合来做负载均衡。

参考方志朋《深入理解Spring Cloud与微服务构建》

SpringCloud(5)路由网关Spring Cloud Zuul的更多相关文章

  1. 路由网关--spring cloud zuul

    路由网关--spring boot Zuul 1.为什么需要Zuul? Zuul Ribbon 以及 Eureka 相结合,可以实现智能路由和负载均衡的功能, Zuul 能够将请求流量按某种策略分发到 ...

  2. spring boot 2.0.3+spring cloud (Finchley)5、路由网关Spring Cloud Zuul

    Zuul作为微服务系统的网关组件,用于构建边界服务,致力于动态路由.过滤.监控.弹性伸缩和安全. 为什么需要Zuul Zuul.Ribbon以及Eureka结合可以实现智能路由和负载均衡的功能:网关将 ...

  3. Spring Cloud 微服务二:API网关spring cloud zuul

    前言:本章将继续上一章Spring Cloud微服务,本章主要内容是API 网关,相关代码将延续上一章,如需了解请参考:Spring Cloud 微服务一:Consul注册中心 Spring clou ...

  4. 服务网关Spring Cloud Zuul

    Spring Cloud Zuul 开发环境 idea 2019.1.2 jdk1.8.0_201 Spring Boot 2.1.9.RELEASE Spring Cloud Greenwich S ...

  5. Spring Cloud Zuul 网关使用与 OAuth2.0 认证授权服务

    API 网关的出现的原因是微服务架构的出现,不同的微服务一般会有不同的服务地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各个微服务通信,会有以下的问题: 客户端会 ...

  6. Spring Cloud 微服务三: API网关Spring cloud gateway

    前言:前面介绍了一款API网关组件zuul,不过发现spring cloud自己开发了一个新网关gateway,貌似要取代zuul,spring官网上也已经没有zuul的组件了(虽然在仓库中可以更新到 ...

  7. spring cloud: zuul: 微网关-简单使用与路由配置

    spring cloud: zuul: 微网关-简单使用与路由配置 首先引入依赖 <dependency> <groupId>org.springframework.cloud ...

  8. Spring Cloud Zuul API服务网关之请求路由

    目录 一.Zuul 介绍 二.构建Spring Cloud Zuul网关 构建网关 请求路由 请求过滤 三.路由详解 一.Zuul 介绍 ​ 通过前几篇文章的介绍,我们了解了Spring Cloud ...

  9. Spring Cloud Zuul网关 Filter、熔断、重试、高可用的使用方式。

    时间过的很快,写springcloud(十):服务网关zuul初级篇还在半年前,现在已经是2018年了,我们继续探讨Zuul更高级的使用方式. 上篇文章主要介绍了Zuul网关使用模式,以及自动转发机制 ...

随机推荐

  1. Redis in python

    什么是Redis 数据库类型分为两种,关系型和非关系型,Redis是一个非常重要的非关系型数据库. 既然是数据库,就是存储数据的一个空间,或者说是一个软件,非关系就是不再按照一对一多对多等结构进行外键 ...

  2. 折腾Java设计模式之策略模式

    博客原文地址 简介 在策略模式(Strategy Pattern)中,一个类的行为或其算法可以在运行时更改.这种类型的设计模式属于行为型模式.简单理解就是一组算法,可以互换,再简单点策略就是封装算法. ...

  3. 如何高效地遍历 MongoDB 超大集合?

    GitHub 仓库:Fundebug/loop-mongodb-big-collection 本文使用的编程语言是 Node.js,连接 MongoDB 的模块用的是mongoose.但是,本文介绍的 ...

  4. es6 Module语法

    export 命令 1.概念 export用于定义要输出的变量(let.var.const.function.class),定义的变量与值是动态绑定关系. 2.命令格式 1. export 变量定义 ...

  5. 前端入门16-JavaScript进阶之EC和VO

    声明 本系列文章内容全部梳理自以下几个来源: <JavaScript权威指南> MDN web docs Github:smyhvae/web Github:goddyZhao/Trans ...

  6. Vue项目用了脚手架vue-cli3.0,会报错You are using the runtime-only build of Vue where the template compiler is not available.....

    摘自: https://blog.csdn.net/wxl1555/article/details/83187647 报错信息如下图: 报错原因是:vue有两种形式的代码:一种是compiler(模版 ...

  7. maven 聚合

    聚合很简单, 在父 pom 中写出子 pom 文件的路径即可 <name>parent Maven Webapp</name> <!-- FIXME change it ...

  8. image_channel_data_type含义

    在穿件image对象的时候,需要传入一个cl_image_format参数,该参数结果包含image_channel_order和image_channel_data_type两个成员.前一个成员表示 ...

  9. 南京邮电大学java程序设计作业在线编程第七次作业

    王利国的"Java语言程序设计第7次作业(2018)"详细 主页 我的作业列表 作业结果详细 总分:100 选择题得分:60  1. 下列叙述中,错误的是( ). A.Java中, ...

  10. 一幅图,看懂中国CMMI

    以下数据由Fancier凡奉信息根据历年CMMI Institute公布的CMMI评估结果的汇总整理.数据跨度2008-2017年,包含对中国CMMI与全球CMMI的不同等级.版本的统计.