@ExceptionHandler+seata+sentinel冲突问题

背景说明

@ExceptionHandlerspringboot中的通用异常处理,通过与配合@RestControllerAdvice,达到处理全局异常的目的。

seataspringcloud alibaba的分布式事务组件

sentinelspringcloud alibaba的服务降级、熔断组件

当这三个组件在一起出现时,会产生什么结果呢?

模拟情况

testService作为服务消费者,userService作为服务提供者,当userService出现异常时,大致分为以下几种情况:

模拟情况

情况1:ExceptionHandler+seata

服务提供者的ExceptionHandler将异常处理成了ResponseResultUtil.error这种返回值,而服务消费者的feign将其识别为了无异常的返回值,导致调用方不回滚事务。

情况1

情况2:sentinel+seata

服务提供者返回异常,服务消费者的sentinel将其降级处理,进入fallback后,服务消费者视作无异常,导致其不回滚事务。

情况2

情况3:ExceptionHandler+seata+sentinel

类似情况1,服务消费者无异常,也不会降级,导致其不回滚事务。

解决方案

1.sentinel作为服务降级组件、存在的意义就在于能够让业务正常走下去,所以在逻辑要求严格的业务中不应引入。

不应引入的模块,如转销售:先改单据状态、再占库、最后做账,这一系列流程的结果必须保证一致,需要同时完成,不可降级。(其他思考:功能痛点:逻辑严格的系统中,如果一个微小的系统异常,导致用户表单无法提交,很影响体验。这种严格流程是否应该?是否也可以增加状态来控制流程?比如订单状态改了,但占库失败,增加未占库状态,之后再手动、或者自动去占库、做账,提高系统的容错率及可用性。

可以考虑引入的模块,如新建用户:先创建用户,再关联角色,如果用户表单的项目很多,角色是其中一个select,而恰好关联角色时,又有问题,则可以考虑先保存用户信息,关联角色降级处理,这样的好处是可以让使用者先将要创建的大部分数据创建进去,回头再处理有问题的部分。当然前提必须是对业务影响较小的情况。

处理方式只需去掉fallback即可

而且,目前fallback只能针对对于整个interface,而不支持针对于interface中的某一个方法。所以如果有某一个方法需要特殊处理,还需要再额外增加接口。所以对于sentinel,应持保守态度。

2.@ExceptionHandler配合@RestControllerAdvice意味着绑定了所有的@RequestMapping,即所有的接口都会进行异常处理,结合目前只有记录错误日志、和处理返回体2种功能的这种情况,而影响到全局事务的功能只有处理通用返回体,所以应明确:

2.1.终端的所有请求,皆通过主服务,即服务消费者。所以在此独立jar包中,采用通用的异常处理,去处理返回体是没问题的。

2.2.而其他的服务提供者,如库存、账款、订单、基础服务提供者,一定不能将异常处理为正常返回体(日志保留),只有这样,才能不影响seata全局事务。

你可能感兴趣的:(@ExceptionHandler+seata+sentinel冲突问题)