springcloud-zuul进阶篇
一 前言
经过zuul初级篇(博客或者公主号springcloud专栏可以找到)的学习,读者都懂得如何简单的使用zuul进行路由网关配置,在进阶篇中你将获得zuul核心功能过滤器的基本使用,通过zuul实现文件上传等;
二管理端点
默认情况下使用@EnableZuulProxy注解和 Spring Boot Actuator集成方式会有两个端点 Routes 和 Filters;
2.1 zuul-server
在zuul-server中添加依赖actuator
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
在 application.yml中添加配置如下,开启routes端点
management:
endpoints:
web:
exposure:
include: routes,filters
启动 eureka-server, zuul-server;
2.2 ruotes端点
访问地址http://localhost:8100/actuator/routes 可以查看如下结果,表明集成成功;
{
/api/**: "zuul-client",
/eureka-server-cluster/**: "eureka-server-cluster",
/zuul-client/**: "zuul-client"
}
还可以详细的查看routes 端点具体的内容;访问地址 http://localhost:8100/actuator/routes/details 可以查看到如下内容;
{
"/api/**": {
"id": "zuul-client",
"fullPath": "/api/**",
"location": "zuul-client",
"path": "/**",
"prefix": "/api",
"retryable": false,
"customSensitiveHeaders": false,
"prefixStripped": true
},
"/eureka-server-cluster/**": {
"id": "eureka-server-cluster",
"fullPath": "/eureka-server-cluster/**",
"location": "eureka-server-cluster",
"path": "/**",
"prefix": "/eureka-server-cluster",
"retryable": false,
"customSensitiveHeaders": false,
"prefixStripped": true
},
"/zuul-client/**": {
"id": "zuul-client",
"fullPath": "/zuul-client/**",
"location": "zuul-client",
"path": "/**",
"prefix": "/zuul-client",
"retryable": false,
"customSensitiveHeaders": false,
"prefixStripped": true
}
}
2.3 filter端点
访问地址http://localhost:8100/actuator/filters 可以的到具体过滤器信息如下;每个过滤器模块中具体包含哪些具体过滤器请读者看返回结果;
- error 过滤器
- post 过滤器
- pre 过滤器
- route 过滤器
{
"error": [{
"class": "org.springframework.cloud.netflix.zuul.filters.post.SendErrorFilter",
"order": 0,
"disabled": false,
"static": true
}],
"post": [{
"class": "org.springframework.cloud.netflix.zuul.filters.post.SendResponseFilter",
"order": 1000,
"disabled": false,
"static": true
}],
"pre": [{
"class": "org.springframework.cloud.netflix.zuul.filters.pre.DebugFilter",
"order": 1,
"disabled": false,
"static": true
}, {
"class": "org.springframework.cloud.netflix.zuul.filters.pre.FormBodyWrapperFilter",
"order": -1,
"disabled": false,
"static": true
}, {
"class": "org.springframework.cloud.netflix.zuul.filters.pre.Servlet30WrapperFilter",
"order": -2,
"disabled": false,
"static": true
}, {
"class": "org.springframework.cloud.netflix.zuul.filters.pre.ServletDetectionFilter",
"order": -3,
"disabled": false,
"static": true
}, {
"class": "org.springframework.cloud.netflix.zuul.filters.pre.PreDecorationFilter",
"order": 5,
"disabled": false,
"static": true
}],
"route": [{
"class": "org.springframework.cloud.netflix.zuul.filters.route.SimpleHostRoutingFilter",
"order": 100,
"disabled": false,
"static": true
}, {
"class": "org.springframework.cloud.netflix.zuul.filters.route.RibbonRoutingFilter",
"order": 10,
"disabled": false,
"static": true
}, {
"class": "org.springframework.cloud.netflix.zuul.filters.route.SendForwardFilter",
"order": 500,
"disabled": false,
"static": true
}]
}
三 过滤器
3.1 过滤器特征
在zuul的request和response工作过程的核心就是以过滤器为基础执行一系列的动作;zuul的核心特色如下
- Type : 过滤器类型定义了在路由期间过滤器被执行的顺序;
- Execution Order: 同一类型的过滤器中,能够定义多个过滤器的执行顺序;
- Criteria: 过滤器被执行的条件;
- Action: 过滤条件满足情况下,被执行的动作;
zuul 提供了一个框架去动态的读取,编译,和运行过滤器;过滤器之间的交流机制是通过RequestContext 进行分享各自的状态;RequestContext 中有各自独立的 request (request 由 ThreadLocal 持有) 进行 存储数据;每个ThreadLocal 都会负责各自请求信息,错误信息,真实的 HttpServletRequest 和 HttpServletResponse;RequestContext 扩展于 ConcurrentHashMap ,所以任何的信息基本都能存储;
3.2 过滤器类型
过滤器类型就对应了 zuul Request 的整个生命周期,具体的流程可以参照来自zuul官网下图;
- PRE 过滤器 在 routing 到 origin 之前执行;主要包括请求认证,选择origin server , debug日志信息;
- ROUTING 过滤器 在 routing 到 origin 之间执行; 建立和发送亲求,支持Apache HttpClient 和 Netflix Ribbon
- POST 过滤器 在 routing 到 origin 之后 执行;处理响应信息,比如添加响应头,收集统计信息和指标,将响应输送给客户端;
- ERROR 过滤器,当发生异常时就会执行;

3.3 自定义filter
自定义filter需要实现 ZuulFilter ;主要实现方法如下
- filterOrder 定义过滤器执行顺序;官网默认不同的过滤器顺序如下
PRE_DECORATION_FILTER_ORDER,SIMPLE_HOST_ROUTING_FILTER_ORDER,PRE_DECORATION_FILTER_ORDER - filterType 定义过滤器类型;通常就是
PRE_TYPE,ROUTE_TYPE,POST_TYPE - shouldFilter 判定是否执行过滤器
- run 执行过滤器
如下代码中是一个PRE过滤器,简单实现了个业务逻辑,对请求的信息进行日志跟踪,获得request上下文进行自定义业务逻辑操作;
/**
* @Author lsc
* <p> 前置过滤器示例 </p>
*/
@Component
public class QueryParamPreFilter extends ZuulFilter {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public String filterType() {
return PRE_TYPE;
}
@Override
public int filterOrder() {
return PRE_DECORATION_FILTER_ORDER - 1;
}
@Override
public boolean shouldFilter() {
// 读者可以拿到请求上下文做业务判断是否执行过滤器
return true;
}
@Override
public Object run() throws ZuulException {
System.out.println("----pre filter be excuted");
//// 获得当前request 请求上下文
RequestContext ctx = RequestContext.getCurrentContext();
// 获得 request
HttpServletRequest request = ctx.getRequest();
// 获得远程主机 ip
String remoteHost = request.getRemoteHost();
// 获得请求参数
String username = request.getParameter("username");
// 打印日志信息
logger.info("the remote host is {} and params is {}",remoteHost,username);
// 设置 key
if (username!=null){
ctx.put("zszxz", "you can set service");
}
return null;
}
}
执行结果
----pre filter be excuted
2020-01-30 17:40:22.472 INFO 20792 --- [nio-8100-exec-4] c.z.z.server.filter.QueryParamPreFilter : the remote host is 0:0:0:0:0:0:0:1 and params is zszxz
四文件上传
4.1 application.yml
在实现文件上传之前需要给配置文件中zuul加上超时设置,和文件大小限制
spring:
application:
name: zuul-server # 应用名称
servlet:
multipart:
max-file-size: 200MB #单个文件上传大小
max-request-size: 600MB #连续上传文件大小
location: / #临时目录
# hystrix 超时设置
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 60000
# ribbon 超时设置
ribbon:
ConnectTimeout: 3000
ReadTimeout: 60000
4.2 controller
以下是一个简单的文件上传示例;
/**
* @Author lsc
* <p>zuul文件上传 </p>
*/
@RestController
public class ZuulFileUploadController {
@PostMapping("/file/upload")
public String fileUpload(@RequestParam("file") MultipartFile file) throws IOException {
// 上传简单文件名
String originalFilename = file.getOriginalFilename();
byte[] bytes = file.getBytes();
File saveFile = new File(originalFilename);
FileCopyUtils.copy(bytes,saveFile);
return saveFile.getAbsolutePath();
}
}
4.3 测试
简单的通过postman测试如下,正确的返回了图片所在的路径;

五 参考文档
Netflix-zuul https://github.com/Netflix/zuul/
springcloud官方文档https://cloud.spring.io/spring-cloud-static/Finchley.SR4/single/spring-cloud.html
springcloud-zuul进阶篇的更多相关文章
- 白话SpringCloud | 第十章:路由网关(Zuul)进阶:过滤器、异常处理
前言 简单介绍了关于Zuul的一些简单使用以及一些路由规则的简单说明.而对于一个统一网关而言,需要处理各种各类的请求,对不同的url进行拦截,或者对调用服务的异常进行二次处理等等.今天,我们就来了解下 ...
- springcloud(十一):服务网关Zuul高级篇
时间过的很快,写springcloud(十):服务网关zuul初级篇还在半年前,现在已经是2018年了,我们继续探讨Zuul更高级的使用方式. 上篇文章主要介绍了Zuul网关使用模式,以及自动转发机制 ...
- 跟我学SpringCloud | 第十篇:服务网关Zuul高级篇
SpringCloud系列教程 | 第十篇:服务网关Zuul高级篇 Springboot: 2.1.6.RELEASE SpringCloud: Greenwich.SR1 如无特殊说明,本系列教程全 ...
- 跟我学SpringCloud | 第十七篇:服务网关Zuul基于Apollo动态路由
目录 SpringCloud系列教程 | 第十七篇:服务网关Zuul基于Apollo动态路由 Apollo概述 Apollo相比于Spring Cloud Config优势 工程实战 示例代码 Spr ...
- Spring+SpringMVC+MyBatis+easyUI整合进阶篇(十五)阶段总结
作者:13 GitHub:https://github.com/ZHENFENG13 版权声明:本文为原创文章,未经允许不得转载. 一 每个阶段在结尾时都会有一个阶段总结,在<SSM整合基础篇& ...
- 跟我学SpringCloud | 第三篇:服务的提供与Feign调用
跟我学SpringCloud | 第三篇:服务的提供与Feign调用 上一篇,我们介绍了注册中心的搭建,包括集群环境吓注册中心的搭建,这篇文章介绍一下如何使用注册中心,创建一个服务的提供者,使用一个简 ...
- 跟我学SpringCloud | 第十三篇:Spring Cloud Gateway服务化和过滤器
SpringCloud系列教程 | 第十三篇:Spring Cloud Gateway服务化和过滤器 Springboot: 2.1.6.RELEASE SpringCloud: Greenwich. ...
- Membership三步曲之进阶篇 - 深入剖析Provider Model
Membership 三步曲之进阶篇 - 深入剖析Provider Model 本文的目标是让每一个人都知道Provider Model 是什么,并且能灵活的在自己的项目中使用它. Membershi ...
- idea 插件的使用 进阶篇
CSDN 2016博客之星评选结果公布 [系列直播]零基础学习微信小程序! "我的2016"主题征文活动 博客的神秘功能 idea 插件的使用 进阶篇(个人收集 ...
随机推荐
- PAT 1017 Queueing at Bank (模拟)
Suppose a bank has K windows open for service. There is a yellow line in front of the windows which ...
- Abaqus 子模型法 和 子结构法
目录 1 子模型法 1.2 子模型法应用考虑因素 1.3 子模型法关键技术 1.3.1 单元选择 1.3.2 驱动变量 1.3.3 链接整体模型和子模型 1.4 仿真过程 1.4.1 问题描述 1.4 ...
- IDEA启动报错-java.net.BindException: Address already in use: bind
启动IDEA报错日志如下: Internal error. Please refer to http://jb.gg/ide/critical-startup-errors java.net.Bind ...
- P3368 (模板)树状数组2
借这个题学新姿势,这个题需要利用差分才能AC,普通树状树有3个点过不了. 差分原理(参考题解区大佬): 一个例子,一组数据 $ a[] = { 1, 5, 4, 2, 3 } $,差分后得到 $ b[ ...
- SEO 建站过程复盘
今天在A5看到一篇关于一个牛站的复盘,整个建站过程值得借鉴. https://www.admin5.com/article/20200218/943930.shtml
- idea新建maven project工程
1.new project: 2.新建在main 下新建 java directory 并mark as source root,这里我已经makr过java目录所以以showfor做演示: 3.新 ...
- MySQL - Schema和Database的区别
问题来源 在pycharm发现Create new schema的效果和新建数据库一样,所以产生这个问题 参考 https://stackoverflow.com/questions/11618277 ...
- matlab学习记录
1.在命令框输入preferences,可以调整字体大小 2.产生正太分布函数 参考:https://blog.csdn.net/s334wuchunfangi/article/details/816 ...
- 【代码学习】PHP面向对象之封装与继承
一.封装(访问控制) 就是将属性私有,并提供公有的setter放置与getter取值方法注:封装是进行访问控制,不是拒绝访问 public(公有) protected(受 ...
- 常见排序的Java实现
插入排序 1.原理:在有序数组中从后向前扫描找到要插入元素的位置,将元素插入进去. 2.步骤:插入元素和依次和前一个元素进行比较,若比前一个元素小就交换位置,否则结束循环. 3.代码: package ...