Spring Cloud 异常处理

  一开始我想着是在Feign的ErrorDecoder上做自定义的异常处理,来实现根据http code抛出各种异常。但是Feign与Hystrix结合之后,发现一个问题,只要服务调用抛出了Throwable类就会触发Hystrix的fallback(前提是配置了fallback)。想来想去都没有想到怎么利用这套机制来实现业务逻辑上的异常分支和服务器处理异常。最后,灵光一现:

  我把异常分成两大类,ClientException和ServiceException。无论哪一种异常,都会导致对应服务本地事务回滚。当发生ClientException时,向客户端返回的http code为200,当发生ServiceException时,向客户端返回的http code为500。

  ClientException是由客户端引起的异常,比如输入非法参数或者用户登录输入错误的密码导致登录失败而业务逻辑进入到非主线分支,这类问题其实都是客户端导致的,只需要拒绝服务让客户端提交正确的参数即可恢复。因此当遇到这种异常的时候,其实业务逻辑是执行成功的,只不过进入了非主线分支而已。

  ServiceException则是由服务器上的逻辑漏洞或者其他什么原因导致的无法由客户端重新提交来纠正的错误,比如服务器代码上写的不严谨在某个地方报了空指针异常,这种问题客户端无论提交多少次正确的参数都无法修正,因此是属于服务器内部错误。

  将异常分成这两类之后,处理起来就清晰很多了。现在假设有两个服务A、B,外部请求进来的时候,由网关服务转发至A,A的处理过程中需要调用B,此时可能会发生以下几种情况:

  1、A调用B之前发生ClientException,以Http Code 200返回结果至外部客户端,http Body中会有固定的格式包含自定义的业务code、msg、data等。客户端解析code后提示用户msg并执行对应的逻辑来重新提交请求。通俗一点讲就是登陆的时候输入了错误的密码,请求提交后页面提示密码错误,此时重新输入正确密码,提交,登录成功。

  2、A调用B之前发生ServiceException,这个没办法,服务暂时不可用了。等重新发布来修复。

  3、A调用B时,B发生ClientException。此时Http Code 200返回结果至A,但是A在从http Body中提取data时,会发现业务code不等于操作成功的那个值,则A抛出对应的ClientException,让客户端重新提交正确参数。

  4、A调用B时,B发生ServiceException。则A的Feign 客户端在解析的时候就会抛出FeignException异常(由于http code为500)。此时有两种选择,A捕获到FeignException,本地事务中断回滚,并告知客户端服务整体不可用,不过这样体验不好。还有一种选择,就是当A的feign客户端配置了fallback,则发生FeignException时会进入对应的fallback代码,那么在这段代码里可以向消息队列里发送这个调用请求!对应的B会监听这个调用消息,然而此时无论B调用多少次都会报错,不过没关系。紧急发布一个补丁,修复导致ServiceException的那个bug,然后部署上线。当新版本的B代码监听到这个消息时,请求就会处理成功,以达到最终一致性!

  5、A调用B成功后,A本地事务提交出错,这个问题比较恶心,粗略想了一下A try catch一下然后调用B的补偿接口来使B的数据恢复正常。

最后,为了安全起见,微服务之前涉及到修改操作的接口,都要保证幂等性。最简单的一个情况就是服务调用超时,Feign会自动重新发送请求几次,那么假设某服务响应过慢,则极有可能导致请求重复提交,若没有做到幂等则会产生错误数据。另外一个就是基于消息队列来保证最终一致性,也有可能发生请求重复处理。

时间: 2024-12-10 22:24:39

Spring Cloud 异常处理的相关文章

笔记:Spring Cloud Hystrix 异常处理、缓存和请求合并

异常处理 在 HystrixCommand 实现的run方法中抛出异常,除了 HystrixBadRequestException之外,其他异常均会被Hystrix 认为命令执行失败并触发服务降级处理逻辑,所以当需要在命令中执行抛出不触发降级的异常时使用他,在使用注解配置实现 Hystrix 命令时,支持忽略指定异常类型功能,只需要通过设置 @HystrixCommand 注册的 ignoreException 参数,示例代码如下: @HystrixCommand (ignoreExceptio

Spring Cloud微服务如何设计异常处理机制?

导读 今天和大家聊一下在采用Spring Cloud进行微服务架构设计时,微服务之间调用时异常处理机制应该如何设计的问题.我们知道在进行微服务架构设计时,一个微服务一般来说不可避免地会同时面向内部和外部提供相应的功能服务接口.面向外部提供的服务接口,会通过服务网关(如使用Zuul提供的apiGateway)面向公网提供服务,如给App客户端提供的用户登陆.注册等服务接口. 而面向内部的服务接口,则是在进行微服务拆分后由于各个微服务系统的边界划定问题所导致的功能逻辑分散,而需要微服务之间彼此提供内

Spring Cloud Gateway-自定义异常处理

前提 我们平时在用SpringMVC的时候,只要是经过DispatcherServlet处理的请求,可以通过@ControllerAdvice和@ExceptionHandler自定义不同类型异常的处理逻辑,具体可以参考ResponseEntityExceptionHandler和DefaultHandlerExceptionResolver,底层原理很简单,就是发生异常的时候搜索容器中已经存在的异常处理器并且匹配对应的异常类型,匹配成功之后使用该指定的异常处理器返回结果进行Response的渲

Spring Cloud Stream异常处理

应用处理 当消费者在处理接收到的消息时,有可能会由于某些原因而抛出异常.若希望对抛出来的异常进行处理的话,就需要采取一些异常处理手段,异常处理的方式可分为三种:应用层面的处理.系统层面的处理以及通过RetryTemplate进行处理. 本小节先来介绍较为常用的应用层面的异常处理方式,该方式又细分为局部处理和全局处理. 局部处理 Stream相关的配置内容如下: spring: cloud: stream: rocketmq: binder: name-server: 192.168.190.12

传统Java Web(非Spring Boot)、非Java语言项目接入Spring Cloud方案

技术架构在向spring Cloud转型时,一定会有一些年代较久远的项目,代码已变成天书,这时就希望能在不大规模重构的前提下将这些传统应用接入到Spring Cloud架构体系中作为一个服务以供其它项目调用.我们需要使用原生的Eureka/Ribbon手动完成注册中心.查询服务列表功能.如果是非Java项目,可以使用 Spring Sidecar 项目接入Spring Cloud形成异构系统. JDK版本的选择 强烈建议使用JDK8, 因为Eureka Client的最新版本已经要求JDK8起了

全链路spring cloud sleuth+zipkin

http://blog.csdn.net/qq_15138455/article/details/72956232 版权声明:@入江之鲸 一.About ZipKin please google 二. Demo Scene 三. Result Display 四.Prepare 1.soft version kafka:2.10-0.10.2.0zokeeper:3.4.10elasticsearch:5.2.2jdk:1.8spring boot:1.5.3.RELEASEsprign clo

《Spring Cloud与Docker微服务架构实战》配套代码

不才写了本使用Spring Cloud玩转微服务架构的书,书名是<Spring Cloud与Docker微服务架构实战> - 周立,已于2017-01-12交稿.不少朋友想先看看源码,现将代码放出. 本次放出的代码: 共计70+个DEMO 覆盖Eureka.Ribbon.Feign.Hystrix.Zuul.Spring Cloud Config.Spring Cloud Bus.Spring Cloud Sleuth.Docker.Docker Compose等. 1-11章代码地址: ht

Spring Cloud教程合集

Spring Cloud系列终于搞完啦! 这一系列是笔者的学习笔记,原书之前也给小伙伴们推荐过 <Spring Cloud微服务实战> 原书采用了较老的Brixton版,笔者在学习的过程中,采用了当时最新的Dalston.SR3版,可是Spring Cloud的更新还是太快了,还没学完,Dalston.SR3就已经不是最新版了,囧了个囧.不过大部分的API都还是没有什么差异的,可以直接用:另一方面,可能由于原书作者的疏忽,<Spring Cloud微服务实战>一书中有的案例按照作者

Spring cloud学习--Zuul02

过滤器 Zuul包括两部分内容:请求的路由和过滤.而实际上请求的路由也是通过过滤器实现的,例如理由映射主要通过pre类型的过滤器完成,它将请求路径与配置的路由规则进行匹配,找到需要转发的目标地址:请求转发的部分则是由route类型的过滤器来完成的,对pre类型过滤器获得的路由地址进行转发.所以过滤器时Zuul实现API网关功能最为核心的部件,每一个进入Zuul的Http请求都会经过一系列的过滤器处理链得到请求响应并返回给客户端. ZuulFilter接口四特征 过滤类型.执行顺序.执行条件.具体