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

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. Spring Boot(五):Spring Boot Jpa 的使用

    在上篇文章Spring Boot(二):Web 综合开发中简单介绍了一下 Spring Boot Jpa 的基础性使用,这篇文章将更加全面的介绍 Spring Boot Jpa 常见用法以及注意事项. ...

  2. .Net语言 APP开发平台——Smobiler学习日志:如何快速实现Timer计时功能

    最前面的话:Smobiler是一个在VS环境中使用.Net语言来开发APP的开发平台,也许比Xamarin更方便 一.目标样式 我们要实现上图中的效果,需要如下的操作: 1.从工具栏上的”Smobil ...

  3. Asp.net的DataGrid实现列冻结(C#)

    # Asp.net的DataGrid实现列冻结(C#) 一.写在前面 列冻结即在拖动横向滚动条时,冻结的列会随着滚动条移动,使得该列不会因为拖动滚动条而被隐藏,呈现出仿佛冻结的效果.列冻结与表头冻结是 ...

  4. web中的——作者也不知道这里面写的啥

    1.使用超链接<a href="/Default/Index">添加</a><a href="#">返回显示信息</a ...

  5. file_get_contents('php://input') 和POST的区别

    之前记得写过这2者的区别,今天看群里有个朋友也提出了怪异的问题,说是“file_get_contents('php://input')获取不到curl post请求的数据的问题”?其实这并不是所谓的& ...

  6. 使用nssm部署windows服务启动应用

    swoole和workerman他们都可以实现即时通信的功能,这里我简单的就workman作为windows服务器启动为例说哈吧.直接进入正题: 下载这个聊天室项目 workerman聊天室 http ...

  7. 31.C++-虚函数之构造函数与析构函数分析

    1.构造函数不能为虚函数 当我们将构造函数定义为虚函数时,会直接报错: 首先回忆下以前学的virtual虚函数概念: 如果类定义了虚函数,创建对象时,则会分配内存空间,并且为该父类以及其所有子类的内存 ...

  8. licecap软件——简单做出app的效果gif图

    最近想在博客或者是git上放gif效果图,找了许久,终于是找到了这款软件,不到500Kb大小,使用简单 软件名为licecap,直接百度上搜索即可 使用的话,打开软件,就会出现一个窗口 之后,可以改变 ...

  9. 利用jQuery动态设置单选框的选中

    一.需要实现的效果 这里使用jQuery来实现.需要实现的效果如下:当下拉条改变时,单选框选中的值随之变化. <!DOCTYPE html> <html> <head&g ...

  10. Eureka相关知识点

    本文讲述的是 Eureka server, 服务提供者.消费者的一些概念和配置说明. Eureka Server 服务注册中心 Eureka的高可用设计 Eureka侧重点是AP,高可用;Eureka ...