Spring Request scope vs java thread-local

2022-09-01 13:02:57

在高容量(每秒约50,000个请求)java web应用程序中,我正在使用ThreadLocal来执行应按请求范围执行的任务。

我可以使用Spring请求范围达到相同的效果,我想知道哪个性能更好?

在代码中,使用 ThreadLocal:

private static final ThreadLocal<SomeClass> myThreadLocal = new ThreadLocal<SomeClass>();

对于每个 http 请求设置:

myThreadLocal.set(new SomeClass());

使用弹簧请求范围:

@Component
@Scope("request")
public class SomeClass{
...
}

现在,什么将花费更多:

myThreadLocal.get();

SpringContext.getBean(SomeClass.class);

我想知道是否有人已经尝试过这样的基准测试?


答案 1

如果我们考虑传统的Java方法,可以从下面的引用中推断出答案要慢得多:

由于反射涉及动态解析的类型,因此无法执行某些 Java 虚拟机优化。因此,反射操作的性能低于非反射操作,因此在性能敏感型应用程序中经常调用的代码节中应避免使用反射操作。

引自JavaDoc关于反射 - http://java.sun.com/docs/books/tutorial/reflect/index.html

因此,由于Spring使用反射方法,因此该方法应该较慢。getBean()SpringContext.getBean(SomeClass.class);

编辑

另请注意,它还嵌入了缓存,因此只要您在这些线程中重用信息,它肯定会更快。ThreadLocal


答案 2

关于解决方案,我想补充一点,您的Web服务器中可能有一个线程池(例如:Tomcat),并且您的线程局部变量实际上不会在每个请求完成后被清除,因为处理线程不会在启用线程池的情况下死亡。ThreadLocal

您需要在完成每个请求时手动清除线程局部变量 ()。为此,例如,您可以使用某种Spring请求/响应拦截器。threadLocal.remove()afterCompletion()


推荐