You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot调用接口报错:session作用域当前线程未激活

Fixing Session Scope Error with Hystrix and OAuth2 SSO in Spring Boot

Hey there, let's break down why you're hitting this Scope 'session' is not active error when calling your /helloWorld endpoint, and how to fix it.

The Root Cause

Hystrix uses thread isolation by default—meaning when a @HystrixCommand is triggered, it spins up a new thread to execute the logic. But your oauth2ClientContext is scoped to the session, which is tied to the original web request thread. The new Hystrix thread doesn't have access to that request/session context, hence the error. Even though you added RequestContextListener, it only works for the original request thread, not the Hystrix-managed ones.

Solution 1: Switch Hystrix Isolation Strategy to Semaphore

The simplest fix is to tell Hystrix not to switch threads. Use the SEMAPHORE isolation strategy instead, which keeps execution in the original request thread.

You can set this globally in your application.yml:

hystrix:
  command:
    default:
      execution:
        isolation:
          strategy: SEMAPHORE

Or apply it to just your specific command:

@HystrixCommand(commandProperties = {
    @HystrixProperty(name = "execution.isolation.strategy", value = "SEMAPHORE")
})
public String helloWorld() {
    // Your logic here
}

Solution 2: Pass Request Context to Hystrix Threads (For Thread Isolation)

If you need to keep thread isolation (e.g., for better resource management), you can create a custom HystrixConcurrencyStrategy to copy the request context from the original thread to the Hystrix thread.

First, create the strategy class:

public class RequestContextHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {
    private final HystrixConcurrencyStrategy delegate;

    public RequestContextHystrixConcurrencyStrategy() {
        try {
            this.delegate = HystrixPlugins.getInstance().getConcurrencyStrategy();
            if (this.delegate instanceof RequestContextHystrixConcurrencyStrategy) {
                return;
            }
            // Reset and re-register existing plugins along with our strategy
            HystrixPlugins.reset();
            HystrixPlugins.getInstance().registerConcurrencyStrategy(this);
            HystrixPlugins.getInstance().registerCommandExecutionHook(HystrixPlugins.getInstance().getCommandExecutionHook());
            HystrixPlugins.getInstance().registerEventNotifier(HystrixPlugins.getInstance().getEventNotifier());
            HystrixPlugins.getInstance().registerMetricsPublisher(HystrixPlugins.getInstance().getMetricsPublisher());
            HystrixPlugins.getInstance().registerPropertiesStrategy(HystrixPlugins.getInstance().getPropertiesStrategy());
        } catch (Exception e) {
            throw new RuntimeException("Failed to register RequestContext Hystrix strategy", e);
        }
    }

    @Override
    public <T> Callable<T> wrapCallable(Callable<T> callable) {
        // Capture the request context from the original thread
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        return () -> {
            try {
                // Set the context on the Hystrix thread
                RequestContextHolder.setRequestAttributes(requestAttributes);
                return callable.call();
            } finally {
                // Clean up after execution
                RequestContextHolder.resetRequestAttributes();
            }
        };
    }

    // Delegate other methods to the original strategy
    @Override
    public ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey, HystrixProperty<Integer> corePoolSize, HystrixProperty<Integer> maximumPoolSize, HystrixProperty<Integer> keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        return delegate.getThreadPool(threadPoolKey, corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    }

    @Override
    public BlockingQueue<Runnable> getBlockingQueue(int maxQueueSize) {
        return delegate.getBlockingQueue(maxQueueSize);
    }

    @Override
    public <T> HystrixRequestVariable<T> getRequestVariable(HystrixRequestVariableLifecycle<T> rv) {
        return delegate.getRequestVariable(rv);
    }
}

Then register this bean in your Spring Boot application:

@SpringBootApplication
@EnableOAuth2Sso
@EnableEurekaClient
public class YourAppApplication {
    // ... other beans

    @Bean
    public RequestContextHystrixConcurrencyStrategy requestContextHystrixConcurrencyStrategy() {
        return new RequestContextHystrixConcurrencyStrategy();
    }

    public static void main(String[] args) {
        SpringApplication.run(YourAppApplication.class, args);
    }
}

Double-Check Your RequestContextListener

Make sure your RequestContextListener is properly registered as a bean (not just added manually somewhere):

@Bean
public RequestContextListener requestContextListener() {
    return new RequestContextListener();
}

This ensures the request context is available in the original thread before Hystrix takes over.


内容的提问来源于stack exchange,提问作者gstackoverflow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:25:21