2011-10-03 5 views
8

시나리오 : Websphere에서 실행되는 Spring 관리 웹 응용 프로그램이 있습니다. (Spring 3.0.x, WAS 7) webapp는 Spring의 WorkManagerTaskExecutor (스레드 풀 크기가 10으로 구성된)을 통해 Websphere의 작업 관리자를 활용하여 계산 집약적 인 db 읽기 작업을 실행합니다. 그래서 기본적으로 10 개의 서로 다른 문서를 생성하는 요청이 들어옵니다. 문서를 생성하려면 데이터를 수집/처리하는 데 db 읽기 만 필요합니다. 그래서 우리는 기본적으로 10 개의 문서를 처리하기 위해 10 개의 스레드를 생성하고 마지막에는 10 명의 작업자가 반환 한 10 개의 문서를 모아서 병합하고 하나의 커다란 응답을 클라이언트에게 되돌려 씁니다. 우리가 확인한 바에 따르면 10 개의 스레드가 데이터를 수집/처리하는 동안 유사한 db 호출이 많이 발생했습니다. 그래서 우리가 생각해 낸 것은 응답을 캐싱하기 위해 가장 많이 실행 된 db 메소드를 중심으로 Aspect를 만드는 것입니다. 애스펙트는 싱글 톤으로 구성되며 애스펙트가 사용하는 캐시는 범위가 요청 범위로 설정된 aspect에 자동으로 요청되어 각 요청에 자체 캐시가 있습니다.다중 스레드 웹 응용 프로그램에서 요청 범위 Bean에 액세스

문제 : 이제이 방법의 문제점은 스레드가 db 호출을 수행하고 있고 Aspect가 끼어들 때 java.lang.IllegalStateException: No thread-bound request found 예외가 발생한다는 것입니다. 스레드가 요청 컨텍스트 외부에서 실행될 때 완전히 이해됩니다.

이 문제를 쉽게 탐색 할 수있는 방법이 있습니까? 요청 범위 캐시가있는 애스펙트를이 스레드가 호출하는 메소드에 적용 할 수 있습니까?

답변

5

나는 이것을 직접 할 수 있다고 생각하지 않습니다. 당신이 할 수 있었다하더라도, 그것은 약간 추한 것입니다. 그러나 고유 한 요청 식별자를 생성 할 수도 있고 세션 ID를 사용할 수도 있지만 여러 탭에주의해야합니다. 각 처리 스레드에 전달합니다. 그러면 aspect는 그 id를 캐시의 키로 사용할 수 있습니다. 캐시 자체도 싱글 톤이지만, String이 ID이고 X가 캐시 된 결과 인 Map<String, X>이 있습니다.

처리하기 쉽도록 스레드를 수동으로 생성하는 대신 @Async 메서드를 사용할 수 있으며 각 @Async 메서드는 첫 번째 매개 변수로 캐시 ID를 전달할 수 있습니다.

나는 방법에 대해 생각

+0

(물론, 비동기 방식을 사용하면 요청 스레드에서의 결과를 수집 할 수 있도록 Future<Result>를 반환해야합니다),하지만 난 찾을 하나의 단점은 이렇게 되었 저를 강제하는 것입니다 캐시하려는 모든 메소드 호출 (스레드 실행 중)의 고유 요청 식별자 다운 스트림. 또한 캐시가 잠시 후에 꽤 크게되지 않을까요? 그런 다음 주기적으로 관리해야합니다. 어쩌면 여기서 뭔가를 놓칠 수 있습니다. – r4j1v

+0

아마도 내 고유 요청 식별자를 저장하고 그것을 직접 전달하지 않고도 측면에서 검색 할 수있는 "스레드 실행 컨텍스트"가 있습니까? – r4j1v

+5

나는이 문제를 해결할 수 있었다. 나는'WorkManagerTaskExecutor' 대신'SimpleAsyncTaskExecutor'를 사용하기 시작했습니다. 이점은'SimpleAsyncTaskExecutor'는 스레드를 결코 다시 사용하지 않는다는 것입니다. 솔루션의 절반에 불과합니다. 나머지 절반은'RequestContextListener' 대신'RequestContextFilter'를 사용하는 것입니다. 'RequestContextFilter'는 기본적으로 자식 스레드가 부모 컨텍스트를 상속 할 수있게 해주는'setThreadContextInheritable()'메소드를 가지고 있습니다. – r4j1v

관련 문제