本篇作为《Spring Cloud微服务实战》一书关于Spring Cloud Zuul网关在Dalston版本对异常处理的补充。没有看过本书的读书也不要紧,可以先阅读我之前的两篇博文:《Spring Cloud实战小贴士:Zuul统一异常处理(一)》和《Spring Cloud实战小贴士:Zuul统一异常处理(二)》,这两篇文章都详细介绍和分析了Spring Cloud Zuul在过滤器设计中对异常处理的不足。同时,在这两篇文章中,也针对不足之处做了相应的解决方案。不过,这些方案都是基于Brixton版本所做的,在最新的Dalston版本中,Spring Cloud Zuul做了一些优化,所以我们不再需要做这些扩展就已经能够正确的处理异常信息了。那么,在Dalston版中,Spring Cloud Zuul中做了怎么样的修改以达到之前我们自己扩展的效果呢?

过滤器类型的变更

读者是否还记得我们之前分析了Spring Cloud Zuul自带的核心过滤器有哪些呢?我们先根据下图回忆一下:

这次主要将SendErrorFilter过滤器的类型从POST改为了ERROR,所以核心过滤器变成了如下图的结构:

处理逻辑的变化

既然过滤器类型发生了变化,那么请求的处理生命周期就会有所变化。在变化之前,各阶段过滤器的流转如下图所示:

针对异常情况,在图中我们标出了不同的颜色。从pre和route阶段抛出的异常将会进入error阶段,再进入到post阶段进行返回。由于SendErrorFilter需要判断请求上下文中是否包含error.status_code属性:有的话就用SendErrorFilter处理错误结果;没有的话就用SendResponseFilter返回正常结果,但是error.status_code属性默认是在各个阶段过滤器中自己put进去的,这就导致,各个阶段过滤器抛出异常之后,是没有办法返回错误结果的。因此,我们扩展了一个ErrorFilter来捕获异常,然后手工的设置error.status_code属性,让SendErrorFilter能正常运作。

通过上面你的改造,从pre和route阶段的异常都能处理了,但是post阶段抛出异常后,是不会再进入post阶段的,这使得ErrorFilter设置了设置error.status_code属性之后,也没有过滤器去组织返回结果,所以我们通过继承SendErrorFilter在error阶段增加了一个返回错误信息的过滤器。

而这次在Dalston版本中,做了很巧妙的变动:就是上文所述的对SendErrorFilter过滤器类型的变更,这一变动使得所有阶段的异常都会被SendErrorFilter处理,直接解决的上面的第二个问题。当然只是做个变动还是不够的,为了区分SendErrorFilter和SendResponseFitler分别处理出现异常和未出现异常的情况,修改原来根据error.status_code属性判断的逻辑,而是改为根据请求上下文中是否包含Throwable来作为基本依据,而这个对象是在过滤器出现异常之后,Zuul往请求上下文中置入的,所以可以更为准确的判断当前请求处理是否出现了异常,而不再需要我们之前扩展的ErrorFilter了。

public class SendErrorFilter extends ZuulFilter {      @Override    public boolean shouldFilter() {       RequestContext ctx = RequestContext.getCurrentContext();     return ctx.containsKey("error.status_code")             && !ctx.getBoolean(SEND_ERROR_FILTER_RAN, false); } ...}

public class SendResponseFilter extends ZuulFilter {    @Override    public boolean shouldFilter() {       RequestContext context = RequestContext.getCurrentContext();     return context.getThrowable() == null           && (!context.getZuulResponseHeaders().isEmpty()               || context.getResponseDataStream() != null               || context.getResponseBody() != null);   } ...}

所以,最后修改之后,整个处理逻辑变为如下图所示的流程:

推荐阅读

  • Spring Cloud构建微服务架构:服务注册与发现(Eureka、Consul)
  • Spring Cloud构建微服务架构:服务消费者(基础)
  • Spring Cloud构建微服务架构:服务消费者(Ribbon)
  • Spring Cloud构建微服务架构:服务消费者(Feign)
  • Spring Cloud构建微服务架构:分布式配置中心
  • Spring Cloud构建微服务架构:服务容错保护(hystrix服务降级)
  • Spring Cloud构建微服务架构:服务容错保护(hystrix依赖隔离)
  • Spring Cloud构建微服务架构:服务容错保护(hystrix断路器)
  • Spring Cloud构建微服务架构:Hystrix监控面板
  • Spring Cloud构建微服务架构:Hystrix监控数据聚合
  • 更多Spring Cloud内容…

Spring Cloud实战小贴士:Zuul统一异常处理(三)【Dalston版】相关推荐

  1. Spring Cloud实战小贴士:Zuul统一异常处理(一)

    在上一篇<Spring Cloud源码分析(四)Zuul:核心过滤器>一文中,我们详细介绍了Spring Cloud Zuul中自己实现的一些核心过滤器,以及这些过滤器在请求生命周期中的不 ...

  2. Spring Cloud实战小贴士:Zuul统一异常处理(二)

    在前几天发布的<Spring Cloud实战小贴士:Zuul统一异常处理(一)>一文中,我们详细说明了当Zuul的过滤器中抛出异常时会发生客户端没有返回任何内容的问题以及针对这个问题的两种 ...

  3. Spring Cloud实战小贴士:Zuul处理Cookie和重定向

    由于我们在之前所有的入门教程中,对于HTTP请求都采用了简单的接口实现.而实际使用过程中,我们的HTTP请求要复杂的多,比如当我们将Spring Cloud Zuul作为API网关接入网站类应用时,往 ...

  4. Spring Cloud实战小贴士:Zuul的饥饿加载(eager-load)使用

    上一篇 我们介绍了如何使用Ribbon的 earger-load配置加速Spring Cloud中对服务接口的第一次调用.可是这样只是解决了内部服务间的调用,另外一个问题依然经常困扰我们,那就是网关到 ...

  5. Spring Cloud实战小贴士:版本依赖关系

    去年在博客上连载了<Spring Cloud构建微服务架构>的系列博文,虽然这部分内容得到了不少关注者们的支持,但是不得不说这些内容只是适用于Spring Cloud入门阶段对各个组件的初 ...

  6. Spring Cloud实战小贴士:随机端口

    太久没有更新,一时不知道该从哪儿开始,索性就从一个小技巧开始吧. 在之前的<Spring Cloud构建微服务架构>系列博文中,我们经常会需要启动多个实例的情况来测试注册中心.配置中心等基 ...

  7. Spring Cloud实战小贴士:Ribbon的饥饿加载(eager-load)模式

    我们在使用Spring Cloud的Ribbon或Feign来实现服务调用的时候,如果我们的机器或网络环境等原因不是很好的话,有时候会发现这样一个问题:我们服务消费方调用服务提供方接口的时候,第一次请 ...

  8. Spring Cloud实战小贴士:turbine如何聚合设置了context-path的hystrix数据

    之前在spring for all社区看到这样一个问题:当actuator端点设置了context-path之后,turbine如何聚合数据?首先,我们要知道actuator端点设置了context- ...

  9. Spring Cloud实战小贴士:Feign的继承特性(伪RPC模式)

    通过之前发布的<Spring Cloud构建微服务架构:服务消费者(Feign)>,我们已经学会如何使用Spring MVC的注解来绑定服务接口.我们几乎完全可以从服务提供方的Contro ...

最新文章

  1. R语言使用gganimate包可视化动画点直方图生成过程(dot histogram)、在数据遍历的过程中逐步在箱体内堆叠数据点形成最终的点直方图
  2. Long Read Mapping at Scale: Algorithms and Applications
  3. String与StringBuffer 理解
  4. 设计模式——控制反转依赖注入
  5. 大锅菜机器人_炒菜机器人——烹饪界的一场革命
  6. HL7数据类型分析(1)
  7. python大神的程序_6年Python大神总结10个开发技巧,80%的人都不会
  8. 如何在VS上用C#玩坏“Hello World”。
  9. 开源GIS(七)——openlayers中单击获取要素(深度好文)
  10. 图论--最小生成树总结(PrimKruskal)
  11. python返回值函数_Python函数的返回值(一)
  12. 2018年第九届 蓝桥杯 java B组 部分题解
  13. C语言项目源代码大全2021最新!
  14. C语言 生成随机数 srand用法 伪随机函数rand srand需不需要重新播种问题 srand该不该放在循环里
  15. 强化学习11——为什么ADP需要持续激励条件?
  16. 河南理工大学计算机专业几本,河南理工大学是几本?河南理工大学是985或211吗...
  17. Kali Linux 详细安装步骤
  18. 关于增量学习的一点总结思考
  19. 教你一招:复制不能复制的网页文字(通用篇)
  20. IT运维:服务器管理

热门文章

  1. 批量裁剪GIS数据(包含GDB,MDB,Shp)
  2. ASP.NET MVC URL重写与优化(进阶篇)-继承RouteBase玩转URL(转)
  3. linux下编译jrtplib-3.9.1
  4. 排序算法之两路归并排序(Java)
  5. 面试官问:malloc(0)时程序会返回什么?
  6. Intel官宣开发RISC-V处理器:明年首发7nm工艺
  7. Linux cpuidle framework
  8. html实现 左图右文_让CSS flex布局最后一行左对齐的N种方法
  9. TQ210——核心板和底板
  10. python中协程与函数的区别_python 协程与go协程的区别