Spring Delegation Threading

When searching for errors, I came across Spring 3.0.5 the source code of DelegatingFilterProxy , and I am wondering if it has a performance bottleneck or not.

Given that for each web application there is only one instance of the delegation of FilterProxy (for the declaration of <filter> , of course), I must assume that under heavy load many workflows try to call the doFilter() method in parallel.

Now take a look at the code:

 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); } 

The synchronized (this.delegateMonitor) block synchronized (this.delegateMonitor) must be passed by all threads, which means that all workers are forced to endure the queue in the queue until they are allowed to enter.

Regardless of why you need to search for a bean here, I suspect that using synchronized could have been avoided in favor of parallel execution - maybe do this.delegate volatile and use synchronization only if the search needs to be performed.

So am I barking the wrong tree? Any input is appreciated.

+4
source share
3 answers

You are right - this seems like a potential problem, alghouth (as Ralph noted), this should not be easily understood. They could use double check lock (with volatile delegate).

I suggest you create a problem in spring jira. If you do not, I will do it.

+2
source

For me it looks like an initialization code. After the first run, this.delegate has a value other than null . Then in the synchronous blog there are only two entries if (this.delegate == null) and delegateToUse = this.delegate .

This block is executed once for each request, therefore: NO, this does not affect the performance of the web application that can be measured.

Of course, God is right, this can be done better. But you will never notice a difference in performance - if there is enough load on the server, so that this synchronized block will have a measurable effect, then everything else on this server is already completely overloaded.

+1
source

This was fixed with double check in Spring 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); } 

View Commit
https://github.com/spring-projects/spring-framework/commit/c26272cef62b1e6f3bb982d7f71b2f47c685b014

See JIRA https://jira.spring.io/browse/SPR-10413

+1
source

Source: https://habr.com/ru/post/1385131/


All Articles