2009-09-04 21 views
6

Así que estoy trabajando en esta aplicación Spring MVC utilizando Spring Security. Llegué a un problema de rendimiento en algunos casos en que mi controlador tarda demasiado en responder. Esto se debe a un método de procesamiento que puede llevar una gran cantidad de datos a procesar, en función de la entrada del usuario.Spring Security Child Thread Context

Ahora he estado ajustando el código un poco en y alrededor de ese método de procesamiento con mi equipo y no creo que podamos obtener un mejor rendimiento de eso sin cortarlo y ejecutar cada segmento de forma asincrónica.

El problema es cuando trato de cortarlo y distribuir el trabajo a subprocesos secundarios, utilizando un subproceso de subprocesos de java.util.concurrent, obtengo mensajes de error sobre el contexto de seguridad cuando se ejecutan.

He aquí un extracto de la 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) 

Yo sé que no es una buena práctica para desovar hilos de una petición ... pero hemos acabaron las ideas en este punto y cada subproceso de trabajo shouldn No tomará más de un puñado de segundos con nuestras mediciones. También se espera que esta característica sea utilizada por 1 o 2 usuarios dedicados una vez a la semana solamente.

¿Hay alguna manera de pasar el securityContext a los subprocesos hijo o algo similar que permitiría ejecutar esos subprocesos?

Gracias

+0

Suponiendo que está utilizando un 'TaskExecutor' puede envolverlo en un' DelegatingSecurityContextTaskExecutor' que se encarga de todo eso. Todo lo cual se explica en la [guía de referencia] (https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#concurrency). –

Respuesta

1

Por lo general, hacer lo siguiente: En el hilo inicial del resorte gestionados hacen

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

Ahora tiene que poner esos dos valores en alguna parte de su nuevo hilo puede encontrarlos. Luego lo hace:

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

En su nuevo hilo. Aunque no estoy seguro de si este es el método admitido, siempre funcionó bien.

+0

He intentado exactamente ese código. hizo que las 2 variables fueran definitivas para poder usarlas con Threadpool. Todavía tengo los mismos errores. Sin embargo, me he asegurado imprimiendo el contenido de las variables que pasaron correctamente a los hilos hijo. – Lancelot

1

Tal vez podría usar algo como InheritableThreadLocalSecurityContextHolderStrategy? Creo que lo que hace es copiar el contexto de seguridad del subproceso actual para todos los hilos que crear dentro de

+0

dará una oportunidad muy pronto ... gracias. – Lancelot

2

he encontrado dos soluciones cuando tuve un problema similar:

Solución 1 cambio de estrategia de SecurityContextHolder a MODE_INHERITABLETHREADLOCAL

es posible hacerlo de tal manera

<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> 

Solución 2 Uso DelegatingSecurityContextRunnable, DelegatingSecurityContextExecutor o DelegatingSecurityContextExecutor.Esta receta está bien descrita en Spring Concurrency Support Documentation

Cuestiones relacionadas