Spring Cloud Zuul

开发环境

  • idea 2019.1.2
  • jdk1.8.0_201
  • Spring Boot 2.1.9.RELEASE
  • Spring Cloud Greenwich SR3

Zuul介绍

Zuul是Netflix开发的一款提供动态路由、监控、弹性、安全的网关服务,他可以和Eureka,Ribbon,Hystrix等组件配合使用。还可以通过创建过滤器对校验过滤提供支持,使微服务应用更专注于业务逻辑的开发。

使用Zuul网关服务带来的好处是统一向外系统提供REST API,并额外提供了权限控制、负载均衡等功能,并且这些功能是从原先的服务中抽离出来并单独存在的。

Zuul提供了不同类型的filter用于处理请求,这些filter可以让我们实现以下功能

  • 权限控制和安全性:可以识别认证需要的信息和拒绝不满足条件的请求
  • 监控:监控请求信息
  • 动态路由:根据需要动态地路由请求到后台的不同服务集群
  • 压力测试:逐渐增大到集群的流量,以便进行性能评估
  • 负载均衡:为每种类型的请求分配容量并丢弃超过限额的请求
  • 限流
  • 黑白名单过滤
  • 静态资源处理:直接在zuul处理静态资源的响应而不需要转发这些请求到内部集群中

过滤器

ZuulFilter是一个基础的抽象类,定义了一些抽象方法

  • filterType方法: filter的类型,有”pre”, “route”, “post”, “error”, “static”

    • pre:在请求被路由之前执行
    • route:在请求被路由时执行
    • post:在请求被路由之后执行
    • error:在请求发生错误时执行
    • static:特殊的 Filter 具体的可以看 StaticResponseFilter,它允许从 Zuul 本身生成响应,而不是将请求转发到源
  • filterOrder方法:优先级,级别越高,越快被执行(数值越小表示级别越高)

  • shouldFilter方法:开关,如果是true,run方法会执行,否则不会执行

  • run方法:filter执行的逻辑操作

代码实现

1.创建服务注册中心

创建 zuul-eureka-server 项目,引入eureka-server依赖,项目完整源码可以查看:Spring Cloud Zuul 示例源码

以下贴几段关键代码

pom添加依赖

        <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

启动类增加 @EnableEurekaServer 注解

@EnableEurekaServer
@SpringBootApplication
public class ZuulEurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(ZuulEurekaServerApplication.class, args);
}
}

yml配置

server:
port: 8761 spring:
application:
name: zuul-eureka-server eureka:
instance:
hostname: localhost # eureka 实例名称
client:
register-with-eureka: false # 不向注册中心注册自己
fetch-registry: false # 是否检索服务
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ # 注册中心访问地址

2.创建服务提供者1

创建 zuul-server-provider 项目,引入eureka-client依赖,项目完整源码可以查看:Spring Cloud Zuul 示例源码

以下贴几段关键代码

pom添加依赖

        <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

编写HelloController服务

@RestController
@Slf4j
public class HelloController { @RequestMapping("/hello")
public String index(@RequestParam String name) {
log.info("request one name is " + name);
return "hello " + name + ",this is first messge";
}
}

启动类增加 @EnableDiscoveryClient 注解

@SpringBootApplication
@EnableDiscoveryClient
public class ZuulServerProviderApplication { public static void main(String[] args) {
SpringApplication.run(ZuulServerProviderApplication.class, args);
}
}

yml配置

spring:
application:
name: zuul-server-provider
server:
port: 9000
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka

3.创建服务提供者2

创建 zuul-server-provider2 项目,引入eureka-client依赖,其它同服务提供者1项目,项目完整源码可以查看:Spring Cloud Zuul 示例源码

以下贴出差异部分代码

编写服务,这里为了做服务降级测试,为当前线程设置了一个超长休眠时间

@RestController
@Slf4j
public class HelloController {
@RequestMapping("/hello")
public String index(@RequestParam String name) {
log.info("request two name is " + name);
try{
//为做服务降级测试,设置一个超长休眠时间,故意导致该服务访问超时
Thread.sleep(1000000);
}catch ( Exception e){
log.error(" hello two error",e);
}
return "hello " + name + ",this is two messge";
}
}

4.创建zuul服务网关

创建 zuul-server-gateway 项目,引入netflix-zuul及eureka-client依赖,项目完整源码可以查看:Spring Cloud Zuul 示例源码

以下贴几段关键代码

pom.xml配置

        <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency> <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>

创建过滤器TokenFilter.java

package com.easy.zuulServerGateway.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils; import javax.servlet.http.HttpServletRequest; @Slf4j
public class TokenFilter extends ZuulFilter { @Override
public String filterType() {
//可以在请求被路由之前调用
return "pre";
} @Override
public int filterOrder() {
//filter执行顺序,通过数字指定 ,优先级为0,数字越大,优先级越低
return 0;
} @Override
public boolean shouldFilter() {
//是否执行该过滤器,此处为true,说明需要过滤
return true;
} @Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest(); log.info("--->>> TokenFilter {},{}", request.getMethod(), request.getRequestURL().toString()); //获取请求的参数
String token = request.getParameter("token"); if (StringUtils.isNotBlank(token)) {
//对请求进行路由
ctx.setSendZuulResponse(true);
ctx.setResponseStatusCode(200);
ctx.set("isSuccess", true);
return null;
} else {
//不对其进行路由
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(400);
ctx.setResponseBody("token is empty");
ctx.set("isSuccess", false);
return null;
}
}
}

创建 zuul-server-provider 服务对应的熔断器(这里针对整个服务熔断,也可以对单个服务接口做熔断处理),ProviderFallback.java

package com.easy.zuulServerGateway.fallback;

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.netflix.zuul.filters.route.FallbackProvider;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component; import java.io.ByteArrayInputStream;
import java.io.InputStream; @Slf4j
@Component
public class ProviderFallback implements FallbackProvider { @Override
public String getRoute() {
return "zuul-server-provider";
} @Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
if (cause != null) {
String reason =cause.getMessage();
log.info("Excption {}", reason);
}
return fallbackResponse();
} public ClientHttpResponse fallbackResponse() {
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() {
return HttpStatus.OK;
} @Override
public int getRawStatusCode() {
return 200;
} @Override
public String getStatusText(){
return "OK";
} @Override
public void close() { } @Override
public InputStream getBody() {
return new ByteArrayInputStream("The service is unavailable.".getBytes());
} @Override
public HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
return headers;
}
};
}
}

yml配置

spring:
application:
name: zuul-service-gateway
server:
port: 8888 eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka #是否开启重试功能
zuul:
retryable: true
#对当前服务的重试次数
ribbon:
MaxAutoRetries: 2
#切换相同Server的次数
MaxAutoRetriesNextServer: 0

启动类增加 @EnableZuulProxy 注解,来启动服务网关

ZuulServerGatewayApplication.java

package com.easy.zuulServerGateway;

import com.easy.zuulServerGateway.filter.TokenFilter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
import org.springframework.context.annotation.Bean; @SpringBootApplication
@EnableZuulProxy
public class ZuulServerGatewayApplication { public static void main(String[] args) {
SpringApplication.run(ZuulServerGatewayApplication.class, args);
} @Bean
public TokenFilter tokenFilter() {
return new TokenFilter();
}
}

至上,示例的四个服务创建完毕,接下来运行示例查看效果

使用

现有四个项目如下

zuul-eureka-server:服务注册中心,服务名:zuul-eureka-server,端口:8761

zuul-server-provider:服务提供者1,服务名:zuul-server-provider,端口:9000

zuul-server-provider2:服务提供者,服务名:zuul-server-provider,端口:9001

zuul-server-gateway:服务网关,服务名:zuul-server-gateway,端口:8888

运行测试

分别启动zuul-eureka-server、zuul-server-gateway、zuul-server-provider三个服务

启动zuul-server-provider2

  • 多次访问http://localhost:8888/zuul-server-provider/hello?name=yuntian&token=xx,此时会交替返回
hello yuntian,this is first messge
The service is unavailable
...

从返回结果可以看出:zuul-server-provider2项目已经启用了熔断,返回:The service is unavailable.

资料

服务网关Spring Cloud Zuul的更多相关文章

  1. API网关服务:Spring Cloud Zuul

    最近在学习Spring Cloud的知识,现将API网关服务:Spring Cloud Zuul 的相关知识笔记整理如下.[采用 oneNote格式排版]

  2. 第七章 API网关服务:Spring Cloud Zuul

    API网关是一个更为智能的应用服务器, 它的定义类似于面向对象设计模式中的Facade模式, 它的存在就像是整个微服务架构系统的门面一样,所有的外部客户端访问都需要经过它来进行调度和过滤.它除了要实现 ...

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

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

  4. 路由网关--spring cloud zuul

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

  5. SpringCloud(5)路由网关Spring Cloud Zuul

    一个简单的微服务系统如下图: 1.为什么需要Zuul Zuul很容易实现 负载均衡.智能路由 和 熔断器,可以做身份认证和权限认证,可以实现监控,在高流量状态下,对服务进行降级. 2.路由网关 继续前 ...

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

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

  7. 微服务网关 Spring Cloud Gateway

    1.  为什么是Spring Cloud Gateway 一句话,Spring Cloud已经放弃Netflix Zuul了.现在Spring Cloud中引用的还是Zuul 1.x版本,而这个版本是 ...

  8. spring cloud:服务网关 Spring Cloud GateWay 入门

    Spring 官方最终还是按捺不住推出了自己的网关组件:Spring Cloud Gateway ,相比之前我们使用的 Zuul(1.x) 它有哪些优势呢?Zuul(1.x) 基于 Servlet,使 ...

  9. springcloud(十七):服务网关 Spring Cloud GateWay 熔断、限流、重试

    上篇文章介绍了 Gataway 和注册中心的使用,以及 Gataway 中 Filter 的基本使用,这篇文章我们将继续介绍 Filter 的一些常用功能. 修改请求路径的过滤器 StripPrefi ...

随机推荐

  1. Spring的事件监听机制

    最近公司在重构广告系统,其中核心的打包功能由广告系统调用,即对apk打包的调用和打包完成之后的回调,需要提供相应的接口给广告系统.因此,为了将apk打包的核心流程和对接广告系统的业务解耦,利用了spr ...

  2. 章节十六、7-DataProviders

    一.当我们的同一个test有多套数据需要进行测试,那么我们就需要用到-->DataProviders package testclasses1; import org.testng.annota ...

  3. 【深入浅出-JVM】(77):SPI

    概念 Service Provider Interface 规则 在resource/META-INF/services 创建一个以接口全限定名为命名的文件,内容写上实现类的全限定名 接口实现类在cl ...

  4. 正确重写equals方法和compareTo方法

    一.概述 程序要对一堆数据元素排序,查找,增加删除.数据节点 class Node{ int type; int index; int score; } 规则: 1)对象相等:两个节点n1与n2,如果 ...

  5. 面试贴:java异常小结

    java的异常处理在面试中通常是个敏感的话题,这里我从整体框架方面稍微作一下我的小结. java的异常都继承Throwable这个类,也就是都可以抛出来的异常,在这个祖先类下,又分为如下子类: 1.E ...

  6. VMware Workstation Fixed Unable to connect to the MKS

    场景:早上开虚拟机时突然报这个错 解决办法如下: 以管理员的身份打开CMD,然后执行如下命令: net start vmx86 net start hcmon net start vmauthdser ...

  7. gh-ost 原理剖析

    gh-ost 原理 一 简介 上一篇文章介绍 gh-ost 参数和具体的使用方法,以及核心特性-可动态调整 暂停,动态修改参数等等.本文分几部分从源码方面解释gh-ost的执行过程,数据迁移,切换细节 ...

  8. Spring Boot (三): ORM 框架 JPA 与连接池 Hikari

    前面两篇文章我们介绍了如何快速创建一个 Spring Boot 工程<Spring Boot(一):快速开始>和在 Spring Boot 中如何使用模版引擎 Thymeleaf 渲染一个 ...

  9. Java8虚拟机(JVM)内存溢出实战

    前言 相信很多JAVA中高级的同学在面试的时候会经常碰到一个面试题 你是如何在工作中对JVM调优和排查定位问题的? 事实上,如果用户量不大的情况下,在你的代码还算正常的情况下,在工作中除非真正碰到与J ...

  10. 【Jenkins持续集成(二)】Windows上安装Jenkins教程

    一.前言 Jenkins是一款开源 CI&CD 软件,用于自动化各种任务,包括构建.测试和部署软件. Jenkins 支持各种运行方式,可通过系统包.Docker 或者通过一个独立的 Java ...