You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@cxf.apache.org by "Leo Romanoff (JIRA)" <ji...@apache.org> on 2010/04/29 17:53:56 UTC

[jira] Updated: (CXF-2792) Custom Executor for Service object is ignored by the CXF JAX-WS run-time when Disaptch.invokeAsync is used

     [ 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.