[ 
https://issues.apache.org/jira/browse/CXF-2792?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Leo Romanoff updated CXF-2792:
------------------------------

         Labels: asynchronous Executor invokeasync concurrency  (was: 
invokeAsync asynchronous Executor)
    Description: 
Hi, 

I'm trying to invoke 10000 external services using invokeAsync from my 
standalone JAX-WS  client. 
I set my custom Executor on the Service objects. This executor is a ThreadPool 
with 3 threads. But it looks like it is ignored completely by the CXF 
run-time. Instead of an Executor, an instance of AutomaticWorkQueueImpl  is 
used. 

BTW, by default, AutomaticWorkQueueImpl  is an unbounded queue, so that a few 
thousands threads are created for processing asynchronous responses. This is of 
cause problematic and has a big performance impact. By providing the 
configuration for AutomaticWorkQueueImpl  in cxf.xml, the 
AutomaticWorkQueueImpl  can be configured to have a required number of threads 
and required maximum capacity.

So, I did some debugging to see, why and where AutomaticWorkQueueImpl is called 
at all during asynchronous WS invocations using Dispatch.invokeAsync(). 

This is the stack trace I got: 
Thread [main] (Suspended (entry into method execute in AutomaticWorkQueueImpl)) 
        AutomaticWorkQueueImpl.execute(Runnable) line: 247      
        HTTPConduit$WrappedOutputStream.handleResponse() line: 2153     
        HTTPConduit$WrappedOutputStream.close() line: 1988      
        HTTPConduit(AbstractConduit).close(Message) line: 66    
        HTTPConduit.close(Message) line: 639    
        
MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(Message) 
line: 62 
        PhaseInterceptorChain.doIntercept(Message) line: 243    
        ClientImpl.invoke(ClientCallback, BindingOperationInfo, Object...) 
line: 422    
        ClientImpl.invokeWrapped(ClientCallback, QName, Object...) line: 371    
        DispatchImpl<T>.invokeAsync(T, AsyncHandler<T>) line: 288       
        TestAsyncProviderClient.invokeMyDispatch(Dispatch<Source>, Object, 
AsyncHandler<Source>) line: 298      
        TestAsyncProviderClient.testManyAsyncResponses() line: 218      
        TestAsyncProviderClient.main(String[]) line: 159        


According to this trace, WS-response processing at the HTTP level is put for 
the execution on a dedicated working queue in the HTTPConduit.handleResponse 
method: 

protected void handleResponse() throws IOException { 
            
            handleRetransmits(); 
            
            if (outMessage == null  || outMessage.getExchange() == null  || 
outMessage.getExchange().isSynchronous()) { 
                handleResponseInternal(); 
            } else { 
                Runnable runnable = new Runnable() { 
                    public void run() { 
                        try { 
                            handleResponseInternal(); 
                        } catch (Exception e) { 
                            Message inMessage = new MessageImpl(); 
                            inMessage.setExchange(outMessage.getExchange()); 
                            inMessage.setContent(Exception.class, e); 
                            incomingObserver.onMessage(inMessage); 
                        } 
                    } 
                }; 
                WorkQueueManager mgr = outMessage.getExchange().get(Bus.class) 
                    .getExtension(WorkQueueManager.class); 
                AutomaticWorkQueue queue = 
mgr.getNamedWorkQueue("http-conduit"); 
                if (queue == null) { 
                    queue = mgr.getAutomaticWorkQueue(); 
                } 
                queue.execute(runnable); 
            } 
 } 

It is easy to see that Executor set for the JAX-WS Service is not propagated 
down to the HTTP transoport level, which required dedicated configuration for 
AutomaticWorkQueue, be it http-conduit queue or automatic work queue. 

For WS-responses at the user-level, i.e. by means of the JAX-WS AsyncHandler 
handlers, the proper Executor is taken from the Service object. 

See also the discussion on the mailing list:
http://old.nabble.com/RejectedExecutionException-when-doing-many-invokeAsync-invocations-ts28266640.html


  was:
Hi, 

I'm trying to invoke 10000 external services using invokeAsync from my 
standalone JAX-WS  client. 
I set my custom Executor on the Service objects. This executor is a ThreadPool 
with 3 threads. But it looks like it is ignored completely by the CXF 
run-time. Instead of an Executor, an instance of AutomaticWorkQueueImpl  is 
used. 

BTW, by default, AutomaticWorkQueueImpl  is an unbounded queue, so that a few 
thousands threads are created for processing asynchronous responses. This is of 
cause problematic and has a big performance impact. By providing the 
configuration for AutomaticWorkQueueImpl  in cxf.xml, the 
AutomaticWorkQueueImpl  can be configured to have a required number of threads 
and required maximum capacity.

So, I did some debugging to see, why and where AutomaticWorkQueueImpl is called 
at all during asynchronous WS invocations using Dispatch.invokeAsync(). 

This is the stack trace I got: 
Thread [main] (Suspended (entry into method execute in AutomaticWorkQueueImpl)) 
        AutomaticWorkQueueImpl.execute(Runnable) line: 247      
        HTTPConduit$WrappedOutputStream.handleResponse() line: 2153     
        HTTPConduit$WrappedOutputStream.close() line: 1988      
        HTTPConduit(AbstractConduit).close(Message) line: 66    
        HTTPConduit.close(Message) line: 639    
        
MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(Message) 
line: 62 
        PhaseInterceptorChain.doIntercept(Message) line: 243    
        ClientImpl.invoke(ClientCallback, BindingOperationInfo, Object...) 
line: 422    
        ClientImpl.invokeWrapped(ClientCallback, QName, Object...) line: 371    
        DispatchImpl<T>.invokeAsync(T, AsyncHandler<T>) line: 288       
        TestAsyncProviderClient.invokeMyDispatch(Dispatch<Source>, Object, 
AsyncHandler<Source>) line: 298      
        TestAsyncProviderClient.testManyAsyncResponses() line: 218      
        TestAsyncProviderClient.main(String[]) line: 159        


According to this trace, WS-response processing at the HTTP level is put for 
the execution on a dedicated working queue in the HTTPConduit.handleResponse 
method: 
        protected void handleResponse() throws IOException { 
            
            // Process retransmits until we fall out. 
            handleRetransmits(); 
            
            if (outMessage == null 
                || outMessage.getExchange() == null 
                || outMessage.getExchange().isSynchronous()) { 
                handleResponseInternal(); 
            } else { 
                Runnable runnable = new Runnable() { 
                    public void run() { 
                        try { 
                            handleResponseInternal(); 
                        } catch (Exception e) { 
                            Message inMessage = new MessageImpl(); 
                            inMessage.setExchange(outMessage.getExchange()); 
                            inMessage.setContent(Exception.class, e); 
                            incomingObserver.onMessage(inMessage); 
                        } 
                    } 
                }; 
                WorkQueueManager mgr = outMessage.getExchange().get(Bus.class) 
                    .getExtension(WorkQueueManager.class); 
                AutomaticWorkQueue queue = 
mgr.getNamedWorkQueue("http-conduit"); 
                if (queue == null) { 
                    queue = mgr.getAutomaticWorkQueue(); 
                } 
                queue.execute(runnable); 
            } 
        } 

It is easy to see that Executor set for the JAX-WS Service is not propagated 
down to the HTTP transoport level, which required dedicated configuration for 
AutomaticWorkQueue, be it http-conduit queue or automatic work queue. 

For WS-responses at the user-level, i.e. by means of the JAX-WS AsyncHandler 
handlers, the proper Executor is taken from the Service object. 



> Custom Executor for Service object is ignored by the CXF JAX-WS run-time when 
> Disaptch.invokeAsync is used
> ----------------------------------------------------------------------------------------------------------
>
>                 Key: CXF-2792
>                 URL: https://issues.apache.org/jira/browse/CXF-2792
>             Project: CXF
>          Issue Type: Bug
>          Components: JAX-WS Runtime
>    Affects Versions: 2.2.7
>         Environment: Standalone CXF-client used on Windows Vista
>            Reporter: Leo Romanoff
>
> Hi, 
> I'm trying to invoke 10000 external services using invokeAsync from my 
> standalone JAX-WS  client. 
> I set my custom Executor on the Service objects. This executor is a 
> ThreadPool with 3 threads. But it looks like it is ignored completely by the 
> CXF 
> run-time. Instead of an Executor, an instance of AutomaticWorkQueueImpl  is 
> used. 
> BTW, by default, AutomaticWorkQueueImpl  is an unbounded queue, so that a few 
> thousands threads are created for processing asynchronous responses. This is 
> of cause problematic and has a big performance impact. By providing the 
> configuration for AutomaticWorkQueueImpl  in cxf.xml, the 
> AutomaticWorkQueueImpl  can be configured to have a required number of 
> threads and required maximum capacity.
> So, I did some debugging to see, why and where AutomaticWorkQueueImpl is 
> called at all during asynchronous WS invocations using 
> Dispatch.invokeAsync(). 
> This is the stack trace I got: 
> Thread [main] (Suspended (entry into method execute in 
> AutomaticWorkQueueImpl))       
>         AutomaticWorkQueueImpl.execute(Runnable) line: 247    
>         HTTPConduit$WrappedOutputStream.handleResponse() line: 2153   
>         HTTPConduit$WrappedOutputStream.close() line: 1988    
>         HTTPConduit(AbstractConduit).close(Message) line: 66  
>         HTTPConduit.close(Message) line: 639  
>         
> MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(Message)
>  line: 62       
>         PhaseInterceptorChain.doIntercept(Message) line: 243  
>         ClientImpl.invoke(ClientCallback, BindingOperationInfo, Object...) 
> line: 422  
>         ClientImpl.invokeWrapped(ClientCallback, QName, Object...) line: 371  
>         DispatchImpl<T>.invokeAsync(T, AsyncHandler<T>) line: 288     
>         TestAsyncProviderClient.invokeMyDispatch(Dispatch<Source>, Object, 
> AsyncHandler<Source>) line: 298    
>         TestAsyncProviderClient.testManyAsyncResponses() line: 218    
>         TestAsyncProviderClient.main(String[]) line: 159      
> According to this trace, WS-response processing at the HTTP level is put for 
> the execution on a dedicated working queue in the HTTPConduit.handleResponse 
> method: 
> protected void handleResponse() throws IOException { 
>             
>             handleRetransmits(); 
>             
>             if (outMessage == null  || outMessage.getExchange() == null  || 
> outMessage.getExchange().isSynchronous()) { 
>                 handleResponseInternal(); 
>             } else { 
>                 Runnable runnable = new Runnable() { 
>                     public void run() { 
>                         try { 
>                             handleResponseInternal(); 
>                         } catch (Exception e) { 
>                             Message inMessage = new MessageImpl(); 
>                             inMessage.setExchange(outMessage.getExchange()); 
>                             inMessage.setContent(Exception.class, e); 
>                             incomingObserver.onMessage(inMessage); 
>                         } 
>                     } 
>                 }; 
>                 WorkQueueManager mgr = 
> outMessage.getExchange().get(Bus.class) 
>                     .getExtension(WorkQueueManager.class); 
>                 AutomaticWorkQueue queue = 
> mgr.getNamedWorkQueue("http-conduit"); 
>                 if (queue == null) { 
>                     queue = mgr.getAutomaticWorkQueue(); 
>                 } 
>                 queue.execute(runnable); 
>             } 
>  } 
> It is easy to see that Executor set for the JAX-WS Service is not propagated 
> down to the HTTP transoport level, which required dedicated configuration for 
> AutomaticWorkQueue, be it http-conduit queue or automatic work queue. 
> For WS-responses at the user-level, i.e. by means of the JAX-WS AsyncHandler 
> handlers, the proper Executor is taken from the Service object. 
> See also the discussion on the mailing list:
> http://old.nabble.com/RejectedExecutionException-when-doing-many-invokeAsync-invocations-ts28266640.html

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to