2011-12-07 13 views
4

バグを掘り下げながら、私はSpring 3.0.5のソースコードDelegatingFilterProxyに出くわしましたが、パフォーマンスのボトルネックがあるのか​​どうかは疑問です。 Spring DelegatingFilterProxyマルチスレッドに関する懸念

は、WebアプリケーションごとにDelegatingFilterProxyのインスタンスが1つしかないことを考えると、私は、高負荷の下でワーカースレッドの多くは並行して 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)ブロックは、すべての労働者は、彼らが入ることを許可されるまで、辛抱強くアップキューを余儀なくされていることを意味しているすべてのスレッドで渡さなければなりません。

かかわらず、豆の検索はここで行われるために必要な理由の私は​​の使用は、並列実行の賛成で回避されている可能性があることを疑う - だけのルックアップの場合にthis.delegate揮発性および使用の同期を行うことによるものであってもよい行われる必要があります。

私は間違った木を吠えますか?すべての入力をいただければ幸いです。

答えて

2

あなたは正しいです - これは潜在的な問題のようです、alghouth(Ralphが指摘したように)、それは容易に気づくべきではありません。彼らはダブルチェックロックを使用することができました(揮発性デリゲートを使用)。

私はあなたがspring 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と異なる値を持ちます。その後、同期化されたブログには、ただ2つのステートメントif (this.delegate == null)delegateToUse = this.delegateが残っています。

このブロックは、リクエストごとに1回実行されるため、測定できないWebアプリケーションのパフォーマンスには影響しません。

もちろん、ボゾは正しいですが、それはより良いことができます。しかし、パフォーマンスの違いに気づくことはありません。サーバーに十分な負荷がかかって、この循環ブロックに測定可能な影響がある場合、このサーバー上の他のすべては既に完全にオーバーロードされています

+0

お返事ありがとうございます。負荷に関しては、Oracles Exadataで負荷テストを行うことができて幸運でした。そこでは、同様のコードが実際のボトルネックになっていることがわかりました。だから、私は、スレッドが複数になると、それにアクセスする機会があればどこでも、同期ブロックを回避するために自分自身を取り除きました。 – user1085804

関連する問題