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

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. iptables 指南

    iptables 是 Linux 内核集成的防火墙系统, 几乎所有 Linux 发行版都会内置 iptables. iptables 对进出的 IP 数据报进行处理和过滤, 过滤规则(rule)存储在 ...

  2. MatrixTree速成

    前言 MatrixTree定理是用来解决生成树计数问题的有利工具 比如说这道题 MatrixTree定理的算法流程也非常简单 我们记矩阵\(A\)为无向图的度数矩阵 记矩阵\(D\)为无向图的邻接矩阵 ...

  3. 51nod“省选”模测第二场 B 异或约数和(数论分块)

    题意 题目链接 Sol 这题是来搞笑的吧.. 考虑一个数的贡献是\(O(\frac{N}{i})\) 直接数论分块. #include<bits/stdc++.h> #define Pai ...

  4. Android系统的三种分屏显示模式

    Google在Android 7.0中引入了一个新特性——多窗口支持,允许用户一次在屏幕上打开两个应用.在手持设备上,两个应用可以在"分屏"模式中左右并排或上下并排显示.在电视设备 ...

  5. Android 异步框架 RxJava2

    观察者模式的概念 RxJava是android的异步框架,官方介绍是可观测的序列,组成异步基于事件程序的库.特点是观察者模式,基于事件流的链式调用,随着异步操作调度过程复杂的情况下,程序逻辑也变得越来 ...

  6. Netty学习笔记(六) 简单的聊天室功能之WebSocket客户端开发实例

    在之前的Netty相关学习笔记中,学习了如何去实现聊天室的服务段,这里我们来实现聊天室的客户端,聊天室的客户端使用的是Html5和WebSocket实现,下面我们继续学习. 创建客户端 接着第五个笔记 ...

  7. 使用docker部署skywalking

    使用docker部署skywalking Intro 之前在本地搭建过一次 skywalking + elasticsearch ,但是想要迁移到别的机器上使用就很麻烦了,于是 docker 就成了很 ...

  8. Word Count

    Word Count 一.个人Gitee地址:https://gitee.com/godcoder979/(该项目完整代码在这里) 二.项目简介: 该项目是一个统计文件字符.单词.行数等数目的应用程序 ...

  9. ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes

    今天在MySQL 5.6版本的数据库中修改InnoDB表字段长度时遇到了"ERROR 1071 (42000): Specified key was too long; max key le ...

  10. c/c++ 继承与多态 由子类向父类的转换规则

    问题1:子类B可以有3种方式(public, protected, private)继承父类A,用哪种方式继承,用户代码才能把子类B的对象转换成父类A的对象呢? 只用当子类B以public方式继承父类 ...