Nepxion / Discovery

☀️ Nepxion Discovery is a solution for Spring Cloud with blue green, gray, route, limitation, circuit breaker, degrade, isolation, tracing, dye, failover, active 蓝绿灰度发布、路由、限流、熔断、降级、隔离、追踪、流量染色、故障转移、多活
http://www.nepxion.com
Apache License 2.0
5.64k stars 1.43k forks source link

在spring-cloud异步场景下使用Hystrix情况下,调用服务出现空指针 #174

Closed dongweizhao closed 3 years ago

dongweizhao commented 3 years ago

堆栈信息

堆栈信息: image

场景核心代码:

业务类

` @Service @Slf4j public class TestService {

@Autowired

private InfraTestClient infraTestClient; @Scheduled(cron = "/ * ?") public void execute() { testInvoke(); log.info("thread id:{},FixedPrintTask execute times:{}", Thread.currentThread().getId()); }

@HystrixCommand(fallbackMethod = "portFallback")
public void testInvoke(){
    log.info("调用路径:{}", infraTestClient.rest("1"));
}

public String portFallback() {
    return "sorry ribbon, it's error!";
}

`

pom配置

`

    <dependency>
        <groupId>com.nepxion</groupId>
        <artifactId>discovery-plugin-strategy-starter-hystrix</artifactId>
        <version>${discovery.version}</version>
    </dependency>

`

配置文件配置

` feign.hystrix.enabled = true

spring.application.strategy.hystrix.threadlocal.supported = true

`

原因: image

解决办法

进行非空判断 `

@Override
public <T> Callable<T> wrapCallable(Callable<T> callable) {
    RequestAttributes originRequestAttributes = RequestContextHolder.getRequestAttributes();
    if (requestDecoratorEnabled && Objects.nonNull(originRequestAttributes)) {
        originRequestAttributes = ServiceStrategyRequestDecoratorFactory.decorateRequestAttributes(originRequestAttributes);
    }

}

`

dongweizhao commented 3 years ago

版本 6.8.0

HaojunRen commented 3 years ago

你提供的方案治标不治本,你红框内标识的对象是Spring内置对象为空,应该研究一下,为何这个对象为空?否则就算加了非空判断,依旧拿不到这个对象,还是会影响逻辑的

HaojunRen commented 3 years ago

我观察你的截图,有两重异步,Kafaka和Hystrix,Spring内核的Threadlocal应该是Kafka层面弄丢的,建议试试DiscoveryAgent,同时不需要引入Hystrix增强包

dongweizhao commented 3 years ago

我看了spring的源码的RequestContextHolder的requestAttributesHolder和inheritableRequestAttributesHolder的值是通过FrameworkServlet中接收到web请求把请求属性注入进去的,而我们的场景是通过kafka或者定时任务发起的服务调用,所以不会走FrameworkServlet类,因此才会出现上面的问题,所以在DefaultServiceStrategyCallableWrapper的wrapCallable方法中应该判断一下!

HaojunRen commented 3 years ago

OK。比较遗憾,6.12.0昨天行发版,我可以加上这段代码,但下个版本需要到至少2个月后了,请自行修改一下源码吧