美文网首页
分布式事务Seata框架+springcloud踩坑

分布式事务Seata框架+springcloud踩坑

作者: 静态变量 | 来源:发表于2020-09-17 13:24 被阅读0次

1、编排脚本中指定的ServiceName,报找不到bean
脚本片段:

{
...
    "States": {
        "ServiceA": {
            "Type": "ServiceTask",
            "ServiceName": "IServiceASeata",
            "ServiceMethod": "run",
            "CompensateState": "CompensateServiceA",
...

需要在feign接口上指定quilifier,属性值是服务名

@FeignClient(value = "servicea", qualifier = "IServiceASeata")
public interface IServiceASeata extends IservicewithCancel {
}

2、服务中抛异常后,Seata无法控制事务回滚
debug发现Seata拿不到异常,异常被feign拿走后直接抛出来了,所以需要重新实现feign的异常处理

public class FeignExceptionConfiguration {
    private static final Logger LOG = LoggerFactory.getLogger(FeignExceptionConfiguration.class);
    @Bean
    public ErrorDecoder errorDecoder() {
        return new UserErrorDecoder();
    }
    /**
     * 重新实现feign的异常处理,捕捉restful接口返回的json格式的异常信息
     *
     */
    public class UserErrorDecoder implements ErrorDecoder {

        public Exception decode(String methodKey, Response response) {
            Exception exception = null;
            ObjectMapper mapper = new ObjectMapper();
            //空属性处理
            mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_EMPTY);
            //设置输入时忽略在JSON字符串中存在但Java对象实际没有的属性
            mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);
            //禁止使用int代表enum的order来反序列化enum
            mapper.configure(DeserializationConfig.Feature.FAIL_ON_NUMBERS_FOR_ENUMS, true);
            try {
                String json;
                //增加判空
                if(response.body() == null){
                    json = "{ \"body\": \"empty body\"}";
                }else {
                    json = Util.toString(response.body().asReader());
                }
                exception = new RuntimeException(json);
                if (StringUtils.isEmpty(json)) {
                    return null;
                }
                FeignFaildResult result = mapper.readValue(json, FeignFaildResult.class);
                // 业务异常包装成自定义异常类MyException
                if (result.getStatus() != HttpStatus.OK.value()) {
                    exception = new MyException(result.getMessage(),result.getStatus());
                }
            } catch (IOException ex) {
                LOG.error(ex.getMessage(), ex);
            }
            return exception;
        }
    }
}
public class FeignFaildResult {
    private String message;
    private int status;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }
}

然后在接口上指定这个处理:

@FeignClient(value = "servicea", qualifier = "IServiceASeata",configuration = FeignExceptionConfiguration.class)
public interface IServiceASeata extends IservicewithCancel {
}

参考:
https://www.jianshu.com/p/b2a0168afeba
异常处理的代码基本是原样照搬,增加了对response.body的判空,不然我的场景会报空指针

相关文章

网友评论

      本文标题:分布式事务Seata框架+springcloud踩坑

      本文链接:https://www.haomeiwen.com/subject/lrelyktx.html