2011-12-07 3 views
4

버그를 찾아 내면서 Spring 3.0.5 소스 코드 DelegatingFilterProxy을 발견했으며 성능 병목 현상이 있는지 없는지 궁금합니다. Spring DelegatingFilterProxy 멀티 스레딩 문제

는 웹 응용 프로그램 당 DelegatingFilterProxy 하나의 인스턴스 만이 있음을 감안할 때 나는 높은 부하 상태에서 작업자 스레드의 많은 병렬 doFilter() 메소드를 호출하려고한다고 가정해야한다 (물론 <filter> 선언, 당).

이제 코드를 살펴 있습니다

public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) 
     throws ServletException, IOException { 

    // Lazily initialize the delegate if necessary. 
    Filter delegateToUse = null; 
    synchronized (this.delegateMonitor) { 
     if (this.delegate == null) { 
      WebApplicationContext wac = findWebApplicationContext(); 
      if (wac == null) { 
       throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener registered?"); 
      } 
      this.delegate = initDelegate(wac); 
     } 
     delegateToUse = this.delegate; 
    } 

    // Let the delegate perform the actual doFilter operation. 
    invokeDelegate(delegateToUse, request, response, filterChain); 
} 

synchronized (this.delegateMonitor) 블록은 그들이 입력 할 수 있습니다 때까지 모든 근로자가 참을성 대기열을 강요하는 것을 의미하는 모든 스레드에 의해 전달되어야합니다. 에 관계없이 필요한 콩 조회가 여기에 수행 될 이유

내가 synchronized의 사용이 병렬 실행에 찬성 피할 수 있다고 생각한다 - 만 조회의 경우 this.delegate 휘발성 및 사용 동기화함으로써 될 수있다 할 필요가있다 .

그래서 나는 잘못된 나무를 짖고 있습니까? 모든 입력을 부탁드립니다.

답변

2

당신이 맞습니다 - 이것은 잠재적 인 문제처럼 보입니다, alghouth (Ralph가 지적한 바와 같이), 그것은 쉽게 눈에 띄지 않아야합니다. 그들은 이중 체크 락 (휘발성 델리게이트)을 사용할 수있었습니다.

스프링 jira에서 문제를 만들 것을 제안합니다. 네가하지 않으면 내가 해줄거야.

+0

를 저지를 참조 봄 4

@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException { // Lazily initialize the delegate if necessary. Filter delegateToUse = this.delegate; if (delegateToUse == null) { synchronized (this.delegateMonitor) { if (this.delegate == null) { WebApplicationContext wac = findWebApplicationContext(); if (wac == null) { throw new IllegalStateException("No WebApplicationContext found: " + "no ContextLoaderListener or DispatcherServlet registered?"); } this.delegate = initDelegate(wac); } delegateToUse = this.delegate; } } // Let the delegate perform the actual doFilter operation. invokeDelegate(delegateToUse, request, response, filterChain); } 

두 번 검사로 수정되었습니다. 자유롭게 그렇게하십시오. 성능 영향과 관련하여 필자는 사랑스런 'Java Concurrency in Practice'서적에서 객체 할당과 비교하여 스레드를 일시 중단하고 다시 활성화하는 것이 클럭주기에 엄청나다는 것을 상기합니다. 또한 가능한 한 동기화 된 블록을 피하는'AtomicLong' 또는'ConcurrentHashMap'과 같은 클래스를 보면 저에게 같은 방향을 제공합니다. – user1085804

1

제게는 초기화 코드처럼 보입니다. 첫 번째 실행 후 this.delegatenull과 다른 값을 갖습니다. 그렇다면 동기화 된 블로그에는 if (this.delegate == null)delegateToUse = this.delegate 두 개의 문장 만 남아 있습니다.

이 블록은 요청 당 한 번 실행되므로 NO : 측정 할 수있는 웹 응용 프로그램의 성능에 영향을주지 않습니다.

물론 Bozho가 맞습니다. 더 잘 수행 될 수 있습니다. 그러나 성능에서의 차이를 결코 눈치 채지 못할 것입니다. 서버에 충분한로드가있어이 순환 블록에 측정 기준이 영향을 미친다면이 서버의 다른 모든 서버는 이미 완전히 오버로드되었습니다.

+0

응답 해 주셔서 감사합니다. 로드에 관해서는 Oracles Exadata에 대한로드 테스트를 수행하는 것이 행운이었으며 비슷한 코드가 실제 병목 현상이되는 것을 보았습니다. 그래서 몇 가지 스레드 이상으로 액세스 할 수있는 기회가있을 때마다 동기화 된 블록을 피하기 위해 혼자서 떠났습니다. – user1085804