cxf-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Daniel Kulp <dk...@apache.org>
Subject Re: Minimizing thread usage for asynchronous invocations
Date Fri, 11 May 2012 15:33:43 GMT
On Friday, May 11, 2012 11:18:14 AM Seumas Soltysik wrote:
> Dan,
> Thanks for taking a look at this. Let me know if you need me to help out
> in any way.

Well, the 2.2 TCK doesn't require it.  Maybe a previous version did.  No 
idea.  In anycase, I see no reason for setting the Async executor here so 
I'm going to remove it.

Dan


> Seumas
> 
> On Fri, May 11, 2012 at 11:03 AM, Daniel Kulp <dkulp@apache.org> wrote:
> > You're definitely right.  Still an issue on trunk.  :-(
> > 
> > I'm attempting to remove the setting of the Executor in the ServiceImpl.
> > All the CXF tests are OK with it.   I'm concerned about the TCK (not
> > sure
> > why we would have set it to begin with unless the TCK required it) so
> > I''ve started the process of running those tests now.   That takes
> > quite a bit longer.   If it's OK, I'll get that committed.
> > 
> > What's interesting is that the Camel async stuff doesn't hit this and
> > actually uses the workqueus.   Not really sure what path it's taking to
> > get there, but interesting none-the-less.
> > 
> > Dan
> > 
> > On Friday, May 11, 2012 02:02:54 AM Seumas Soltysik wrote:
> > > Hi Dan,
> > > I think I found the source of the issue.
> > > 
> > > The customer I have been working with noted that for async call, CXF
> > 
> > 2.1.x
> > 
> > > was behaving differently that CXF 2..3.x.
> > > In 2.1.x the number of threads being created to handle the response
> > > for
> > > async call was limited by the parameters of the AutomaticWorkQueue.
> > > The
> > > result was that 100 async calls would only produce a maximum of 25
> > 
> > threads
> > 
> > > to handle the responses to the calls.
> > > 
> > > Howerver, the customer noticed that for 2.3.x for 100 async
> > > invocations,
> > > 100 threads were being created to handle the responses.
> > > 
> > > By comparing the HTTPConduit code for 2.1 to 2.3, I was able to find
> > > the
> > > problem.
> > > 
> > > Here is the pertinent code for 2.1:
> > >                 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);
> > > 
> > > Here is the code for 2.3:
> > >                     Executor ex =
> > > 
> > > outMessage.getExchange().get(Executor.class);
> > > 
> > >                     if (ex == null) {
> > >                     
> > >                         WorkQueueManager mgr =
> > > 
> > > outMessage.getExchange().get(Bus.class)
> > > 
> > >                             .getExtension(WorkQueueManager.class);
> > >                         
> > >                         AutomaticWorkQueue qu =
> > > 
> > > mgr.getNamedWorkQueue("http-conduit");
> > > 
> > >                         if (qu == null) {
> > >                         
> > >                             qu = mgr.getAutomaticWorkQueue();
> > >                         
> > >                         }
> > >                         qu.execute(runnable, 5000);
> > >                     
> > >                     } else {
> > > 
> > > outMessage.getExchange().put(Executor.class.getName()
> > > 
> > >                                                  + ".USING_SPECIFIED",
> > > 
> > > Boolean.TRUE);
> > > 
> > >                         ex.execute(runnable);
> > >                     
> > >                     }
> > > 
> > > As you may notice the major difference is that the first step in the
> > > 2.3
> > > 
> > >  code is to get an Executor from the Exchange.
> > > 
> > > For async calls the Executor is not null. The Executor is set in the
> > > 
> > > ServiceImpl.createPort() code:
> > >         service.setExecutor(new Executor() {
> > >         
> > >             public void execute(Runnable command) {
> > >             
> > >                 Executor ex = getExecutor();
> > >                 
> > >                 if (ex == null) {
> > >                 
> > >                     ex = OneShotAsyncExecutor.getInstance();
> > >                 
> > >                 }
> > >                 
> > >                 ex.execute(command);
> > >             
> > >             }
> > >         
> > >         });
> > > 
> > > The OneShotAsyncExecutor does not throttle the thread creation which
> > > results in the issue mentioned above.
> > > 
> > > 
> > > By adding code like this after the creation of the proxy, the old
> > 
> > behavior
> > 
> > > is established:
> > > 
> > > 
> > > rpcperf = aRPCPerfService.getRPCPerfSoapHttpPort();
> > > 
> > > Bus bus = BusFactory.getDefaultBus();
> > > 
> > > 
> > > WorkQueueManager mgr = bus.getExtension(WorkQueueManager.class);
> > > 
> > > Executor ex = mgr.getAutomaticWorkQueue();
> > > 
> > > 
> > > org.apache.cxf.endpoint.Client client =
> > > org.apache.cxf.frontend.ClientProxy.getClient(rpcperf);
> > > 
> > > org.apache.cxf.endpoint.Endpoint cxfEndpoint = client.getEndpoint();
> > > 
> > > cxfEndpoint.setExecutor(ex);
> > > 
> > > 
> > > Not sure what the exact fix is for this since adding the check for the
> > > Executor on the service seems like it might be important for setting
> > > custom Executors.
> > > 
> > > 
> > > By inspection, this seems to be a problem on trunk as well.
> > > 
> > > 
> > > Thoughts?
> > > 
> > > 
> > > Seumas
> > > 
> > > 
> > > 
> > > The problem is that for async calls, this is not null by default.
> > > 
> > > On Thu, Mar 29, 2012 at 3:06 PM, Daniel Kulp <dkulp@apache.org> wrote:
> > > > On Thursday, March 29, 2012 02:36:55 PM Seumas Soltysik wrote:
> > > > > It would appear at this point that each async invocation involves
> > > > > a
> > > > > listener thread, waiting for a response from the server. Is there
> > > > > a
> > > > > way
> > > > 
> > > > to
> > > > 
> > > > > configure the number of listener threads used by a particular
> > > > > client
> > > > > so
> > > > > that 100 async invocations do not result in 100 listener threads?
> > > > 
> > > > The default should max out at 25 per bus.   Basically, they end up
> > > > on
> > > > the
> > > > "default" WorkQueue of the bus which default to a max of 25 threads.
> > > > You can configure the default WorkQueue to have more or less threads
> > > > if
> > > > you want.
> > > > 
> > > > There is supposed to be code to allow for a specific "http-conduit"
> > > > named
> > > > workqueue to be optionally configured, but I just noticed that code
> > > > isn't
> > > > working properly and will always re-grab the default workqueue. 
> > > > I'll
> > > > get
> > > > that fixed.
> > > > 
> > > > You can also call the Service.setExecutor(..) prior to creating the
> > > > proxy
> > > > if
> > > > you want to specify a specify executor for the client.
> > > > 
> > > > > I was doing some research on this issue and it appears that at
> > > > > some
> > > > > point
> > 
> > > > > there was some work being done in this area:
> > http://cxf.547215.n5.nabble.com/Async-HTTP-client-side-td2835428.html
> > 
> > > > Never had time to really finish/pursue that more in depth.   :-(
> > > > 
> > > > 
> > > > --
> > > > Daniel Kulp
> > > > dkulp@apache.org - http://dankulp.com/blog
> > > > Talend Community Coder - http://coders.talend.com
> > 
> > --
> > Daniel Kulp
> > dkulp@apache.org - http://dankulp.com/blog
> > Talend Community Coder - http://coders.talend.com
-- 
Daniel Kulp
dkulp@apache.org - http://dankulp.com/blog
Talend Community Coder - http://coders.talend.com


Mime
View raw message