Spring Область запроса vs java thread-local
В больших объемах (~ 50 000 запросов в секунду) Java-приложение Я использую ThreadLocal для выполнения задачи, которая должна выполняться в области запроса.
Я мог бы добиться такого же эффекта, используя область запроса Spring, и я задался вопросом, какая из них лучше?
В коде, используя ThreadLocal:
private static final ThreadLocal<SomeClass> myThreadLocal = new ThreadLocal<SomeClass>();
И для каждого параметра http-запроса:
myThreadLocal.set(new SomeClass());
Использование области запроса Spring:
@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
Решение Spring будет стоить дороже, но сделает для более чистого кода IMO. Существует множество шагов, связанных с извлечением, созданием, инициализацией и хранением bean. Однако вам не придется думать об очистке области запроса bean, как вы бы ThreadLocal
. Он будет собран, когда очищается соответствующая ServletRequest
.
Ответ 3
Что касается решения ThreadLocal
, я хотел бы добавить, что на вашем веб-сервере есть, вероятно, пул потоков (например, Tomcat), и локальная переменная вашего потока на самом деле не будет очищена после завершения каждого запроса в качестве потоков обработки не умирайте с включенным пулом потоков.
Вам необходимо очистить локальную переменную потока (threadLocal.remove()
) вручную после завершения каждого запроса. Для этого вы можете использовать, например, некоторый тип afterCompletion()
некоторых из этих Spring перехватчиков запроса/ответа.