服务网关Spring Cloud Zuul
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三个服务
- 访问地址:http://localhost:8888/zuul-server-provider/hello?name=yuntian,返回:token is empty ,请求被拦截返回。
- 访问地址:http://localhost:8888/zuul-server-provider/hello?name=yuntian&token=xx,返回:hello yuntian,this is first messge,说明请求正常响应。
启动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的更多相关文章
- API网关服务:Spring Cloud Zuul
		最近在学习Spring Cloud的知识,现将API网关服务:Spring Cloud Zuul 的相关知识笔记整理如下.[采用 oneNote格式排版] 
- 第七章 API网关服务:Spring Cloud Zuul
		API网关是一个更为智能的应用服务器, 它的定义类似于面向对象设计模式中的Facade模式, 它的存在就像是整个微服务架构系统的门面一样,所有的外部客户端访问都需要经过它来进行调度和过滤.它除了要实现 ... 
- Spring Cloud 微服务二:API网关spring cloud zuul
		前言:本章将继续上一章Spring Cloud微服务,本章主要内容是API 网关,相关代码将延续上一章,如需了解请参考:Spring Cloud 微服务一:Consul注册中心 Spring clou ... 
- 路由网关--spring cloud zuul
		路由网关--spring boot Zuul 1.为什么需要Zuul? Zuul Ribbon 以及 Eureka 相结合,可以实现智能路由和负载均衡的功能, Zuul 能够将请求流量按某种策略分发到 ... 
- SpringCloud(5)路由网关Spring Cloud Zuul
		一个简单的微服务系统如下图: 1.为什么需要Zuul Zuul很容易实现 负载均衡.智能路由 和 熔断器,可以做身份认证和权限认证,可以实现监控,在高流量状态下,对服务进行降级. 2.路由网关 继续前 ... 
- spring boot 2.0.3+spring cloud (Finchley)5、路由网关Spring Cloud Zuul
		Zuul作为微服务系统的网关组件,用于构建边界服务,致力于动态路由.过滤.监控.弹性伸缩和安全. 为什么需要Zuul Zuul.Ribbon以及Eureka结合可以实现智能路由和负载均衡的功能:网关将 ... 
- 微服务网关 Spring Cloud Gateway
		1. 为什么是Spring Cloud Gateway 一句话,Spring Cloud已经放弃Netflix Zuul了.现在Spring Cloud中引用的还是Zuul 1.x版本,而这个版本是 ... 
- spring cloud:服务网关 Spring Cloud GateWay 入门
		Spring 官方最终还是按捺不住推出了自己的网关组件:Spring Cloud Gateway ,相比之前我们使用的 Zuul(1.x) 它有哪些优势呢?Zuul(1.x) 基于 Servlet,使 ... 
- springcloud(十七):服务网关 Spring Cloud GateWay 熔断、限流、重试
		上篇文章介绍了 Gataway 和注册中心的使用,以及 Gataway 中 Filter 的基本使用,这篇文章我们将继续介绍 Filter 的一些常用功能. 修改请求路径的过滤器 StripPrefi ... 
随机推荐
- hdu 3966 Aragorn's Story(树链剖分+区间修改+单点查询)
			题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意:给一棵树,并给定各个点权的值,然后有3种操作: I C1 C2 K: 把C1与C2的路径上 ... 
- hdu Sumsets
			Farmer John commanded his cows to search for different sets of numbers that sum to a given number. T ... 
- Linux入门基础之一
			Linux 入门基础 一.Linux 系统安装 安装方法网上很多,请自行百度 二.Linux 基本操作 2.1.GNOME图形界面基本操作 操作类似于Windows系统操作 打开每一个文件夹都会打开一 ... 
- Go语言基础之并发
			并发是编程里面一个非常重要的概念,Go语言在语言层面天生支持并发,这也是Go语言流行的一个很重要的原因. Go语言中的并发编程 并发与并行 并发:同一时间段内执行多个任务(你在用微信和两个女朋友聊天) ... 
- TensorFlow读取数据的三种方法
			tensortlfow数据读取有三种方式 placehold feed_dict:从内存中读取数据,占位符填充数据 queue队列:从硬盘读取数据 Dataset:同时支持内存和硬盘读取数据 plac ... 
- android 解决 多品牌手机拍照问题,尤其是小米手机
			先上个图吧 .点击头像弹出下面对话框,然后直接上代码. 头像是自定义控件实现的圆形头像,当然就目前而言 想要实现 圆形头像的资料太多了,随便找个就行 <com.kuibu.jucai.widge ... 
- Android 网络通信框架Volley(三)
			NetworkImageView 分析:public class NetworkImageView extends ImageView 他继承自ImageView,并且添加了一个新方法: public ... 
- jar包部署到window系统服务器的办法
			1:把jar包和lib(如果打包出现有lib目录)放在同级目录 2:windows服务器安装jdk等 3:通过bat批处理命令或者 cmd命令启动jar包,其中之一就可以 3.1:bat命令如下: @ ... 
- Java面向对象程序设计第5章1-9
			1.面向对象的主要特征是什么? 三大特征是:封装.继承和多态. 封装:是指将某事物的属性和行为包装到对象中,这个对象只对外公布需要公开的属性和行为,而这个公布也是可以有选择性的公布给其它对象. 继承: ... 
- Swift从入门到精通第七篇 - 扩展 初识
			扩展(学习笔记) 环境Xcode 11.0 beta4 swift 5.1 扩展 为类.结构体.枚举.协议添加新功能,同OC的分类很像,但扩展没有名字 扩展可以添加计算实例属性和计算类型属性(不能添加 ... 
