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