6

そのため、Spring Security を使用してこの Spring MVC アプリケーションに取り組んでいます。コントローラーの応答に時間がかかりすぎる場合に、パフォーマンスの問題が発生することがあります。これは、一部のユーザー入力に基づいて、処理に大量のデータを取り込むことができる処理方法によるものです。

現在、私はチームと一緒にその処理方法のコードを少し調整していますが、スライスして各スライスを非同期で実行しない限り、パフォーマンスを大幅に向上させることはできないと思います。

問題は、java.util.concurrent のスレッドプールを使用して、それをスライスして子スレッドに分散しようとすると、実行時にセキュリティ コンテキストに関するエラー メッセージが表示されることです。

スタックトレースの抜粋は次のとおりです。

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 人の専用ユーザーによって週に 1 回のみ使用されることが予想されます。

securityContext を子スレッドまたはそれらのスレッドの実行を許可する同様のものに渡す方法はありますか?

ありがとう

4

4 に答える 4

3

同様の問題が発生したときに、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 DelegatingSecurityContextRunnableDelegatingSecurityContextExecutorまたはDelegatingSecurityContextExecutorを使用します。このソリューションは、Spring Concurrency Support Documentationで詳しく説明されています

于 2017-06-07T13:37:43.133 に答える
2

We usually do the following: In the initial spring-managed thread do

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

Now you need to put those two values somewhere your new thread can find them. Then you do:

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

In your new thread. Although I'm not sure if this is the supported method, it's always worked well.

于 2009-09-06T07:05:44.287 に答える
1

たぶん、InheritableThreadLocalSecurityContextHolderStrategyのようなものを使用できますか?現在のスレッドのセキュリティコンテキストを、作成したスレッドにコピーすることだと思います

于 2009-09-06T21:12:20.393 に答える