场景:
- Feign熔断降级;
- 被调用服务全局异常捕获了;
解决方案:
- 将需要分布式事务的调用链异常一直往上抛出去; 参考:https://blog.csdn.net/qq_16468489/article/details/121798016
- 手动开启全局事务并进行回滚 ;参考:https://blog.csdn.net/qq_36155375/article/details/115950439
方案1示例:
1.Feign熔断降级,在FallbackFactory中继续往上抛出。
2.被调用服务全局异常捕获了,在Feign结果解析器中对返回结果进行判断,然后抛出异常,注意:解析器中抛出的异常会继续被FallbackFactory的默认实现捕获,需要在Feign熔断降级中将异常继续往上抛出(如上图)。
package com.lbdj.app.feign.workerorder;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import feign.Response;
import feign.Util;
import feign.codec.Decoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.support.SpringDecoder;
import java.io.IOException;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
@Slf4j
public class ResultStatusDecoder implements Decoder{
final SpringDecoder delegate;
public ResultStatusDecoder(SpringDecoder delegate) {
Objects.requireNonNull(delegate, "Decoder must not be null. ");
this.delegate = delegate;
}
@Override
public Object decode(Response response, Type type) throws IOException {
String resultStr = Util.toString(response.body().asReader(Util.UTF_8));
log.info("进来了 ,result msg ->{}",resultStr);
JSONObject jsonObject = JSONUtil.parseObj(resultStr);
if(jsonObject.containsKey("code")){
String code = jsonObject.getStr("code");
if("200".equals(code)){
throw new RuntimeException("我知道错了");
}
}
//回写body,因为response的流数据只能读一次,这里回写后重新生成response
return delegate.decode(response.toBuilder().body(resultStr, StandardCharsets.UTF_8).build(), type);
}
}
package com.lbdj.app.feign.workerorder;
import feign.codec.Decoder;
import feign.optionals.OptionalDecoder;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.cloud.openfeign.support.ResponseEntityDecoder;
import org.springframework.cloud.openfeign.support.SpringDecoder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CustomizedConfiguration {
@Bean
public Decoder decoder(ObjectProvider<HttpMessageConverters> messageConverters){
return new OptionalDecoder((new ResponseEntityDecoder(new ResultStatusDecoder(new SpringDecoder(messageConverters)))));
}
}
Tip:Feign调用出现异常时如果没写FallbackFactory,或在FallbackFactory中继续往上抛出,则程序会因为异常执行中断;如果写了FallbackFactory,没有往上抛出异常,程序会继续执行。