2009-09-04 3 views
6

Итак, я работаю над этим приложением Spring MVC с использованием Spring Security. Я сталкивался с проблемой производительности в некоторых случаях, когда мой контроллер слишком долго реагирует. Это связано с методом обработки, который может обрабатывать огромное количество данных для обработки, основываясь на некотором пользовательском вводе.Spring Security Child Thread Context

Теперь я немного изменил код и вокруг этого метода обработки с моей командой, и я не думаю, что мы можем получить гораздо лучшую производительность, не разрезая его и выполняя каждый фрагмент асинхронно.

Проблема заключается в том, что я пытаюсь разрезать его и распространять работу на дочерние потоки, используя threadpool из java.util.concurrent, я получаю сообщения об ошибках в контексте безопасности при их выполнении.

Вот выдержка из StackTrace:

Exception in thread "pool-1-thread-3" org.springframework.security.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext 
    at org.springframework.security.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:342) 
    at org.springframework.security.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:254) 
    at org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:63) 
Exception in thread "pool-1-thread-4" at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) 
    at $Proxy63.batchSaveCampaignpayment(Unknown Source) 
    at com.fim.pnp.controller.PaymentForm$1.run(PaymentForm.java:224) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675) 
    at java.lang.Thread.run(Thread.java:595) 
org.springframework.security.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext 
    at org.springframework.security.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:342) 
    at org.springframework.security.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:254) 
    at org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:63) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) 
    at $Proxy63.batchSaveCampaignPayment(Unknown Source) 
    at com.fim.pnp.controller.PaymentForm$1.run(PaymentForm.java:224) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675) 
    at java.lang.Thread.run(Thread.java:595) 
Exception in thread "pool-1-thread-5" org.springframework.security.AuthenticationCredentialsNotFoundException: An Authentication object was not found in the SecurityContext 
    at org.springframework.security.intercept.AbstractSecurityInterceptor.credentialsNotFound(AbstractSecurityInterceptor.java:342) 
    at org.springframework.security.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:254) 
    at org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:63) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) 
    at $Proxy63.batchSaveCampaignPayment(Unknown Source) 
    at com.fim.pnp.controller.PaymentForm$1.run(PaymentForm.java:224) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:650) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675) 
    at java.lang.Thread.run(Thread.java:595) 

Я знаю, что это не хорошая практика, чтобы породить потоки от запроса ... но мы выбежали из идей в этой точке, и каждый рабочий поток не должен Наши измерения измеряются более чем за несколько секунд. Также ожидается, что эта функция будет использоваться 1 или 2 выделенными пользователями один раз в неделю.

Есть ли способ передать securityContext дочерним потокам или что-то подобное, что позволит этим потокам выполнить?

Благодаря

+0

Предполагая, что вы используете «TaskExecutor», вы можете обернуть его в «DelegatingSecurityContextTaskExecutor», который позаботится обо всем этом. Все это объяснено в [справочном руководстве] (https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#concurrency). –

ответ

1

Мы обычно делаем следующее: В начальной яровой управляемой нити сделать

Locale locale = LocaleContextHolder.getLocale(); 
RequestAttributes ra = RequestContextHolder.getRequestAttributes(); 

Теперь вам нужно поместить эти два значения где ваш новый поток может их найти. Затем вы делаете:

LocaleContextHolder.setLocale(locale, true); 
RequestContextHolder.setRequestAttributes(ra, true); 

В вашей новой теме. Хотя я не уверен, что это поддерживаемый метод, он всегда хорошо работает.

+0

Я пробовал именно этот код. сделал 2 переменных final, чтобы я мог использовать их с Threadpool. Все еще были те же ошибки. Я убедился, что печатаю содержимое переменных, которые они правильно передали дочерним потокам. – Lancelot

1

Возможно, вы могли бы использовать что-то вроде InheritableThreadLocalSecurityContextHolderStrategy? Я думаю, что он делает это скопировать контекст безопасности текущего потока на любые создаваемые вами потоки в

+0

даст этот снимок очень скоро ... спасибо. – Lancelot

2

Я нашел два решения, когда у меня была аналогичная проблема:

Решение 1 Изменение стратегии SecurityContextHolder в MODE_INHERITABLETHREADLOCAL

Вы можете сделать это таким образом

<beans:bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> 
    <beans:property name="targetClass" 
       value="org.springframework.security.core.context.SecurityContextHolder"/> 
    <beans:property name="targetMethod" value="setStrategyName"/> 
    <beans:property name="arguments" value="MODE_INHERITABLETHREADLOCAL"/> 
</beans:bean> 

Решение 2 Использование DelegatingSecurityContextRunnable, DelegatingSecurityContextExecutor или DelegatingSecurityContextExecutor.Эта мысль хорошо описана в Spring Concurrency Support Documentation

 Смежные вопросы

  • Нет связанных вопросов^_^