1

环境:Webphere 6,Solaris box,胖客户端,Java Web应用程序。在这个多线程案例中使用线程池是否明智?

请求数可以在400-600之间。在对服务器的每个请求中,我创建了15个线程(使用Java ExecutorService)来同时请求15个不同的webservies,并将所有响应数据组合在一起并发回给用户。 负载测试将近150-170位用户失败。在为这些Web服务提供服务的DB中会看到CPU和内存尖峰,并且最终在很短的时间内,应用程序服务器崩溃。 网络服务的响应时间最多10-12秒,最短4-6秒。 DB的连接池大小为40.

我假设150个请求正在创建150 * 15 = 2250个线程,并且应用程序服务器资源正在被尖刺并因此崩溃。所以我想使用App服务器线程池并让threadCount声明为100(可能不是很好的数字..)。有一件令我困扰的事情是,有100个线程,我可以处理前6个(6 * 15 = 90)请求和10个7次请求调用。接下来的请求必须等待10-15秒才能获得线程,然后再等待10-15秒来完成自己的web服务调用。这种方法甚至好吗?

另一个想法是在Websphere中提供的异步bean。哪一个适合我的要求。

请建议!!一个接一个地调用一个web服务总共需要15 *(可以说每个请求4秒)= 60秒,这真的很糟糕。所以一起调用webserices是我想要做的。

回答

1

不建议在管理应用程序服务器中的线程。如果您使用的是EJB,则规格为disallows that

为什么不使用缓存解决方案来提高性能?前几个请求会比较慢,但是一旦缓存很热,一切都会非常快。

如果缓存数据不可行,那么更改客户端以向服务器发出多个请求,而不是在多个线程中拆分一个请求呢?您需要更改您的Web应用程序,以便每个方法都可以调用一个Web服务。客户端会调用(并行)当前页面所需的每种方法并汇总最终结果(如果愿意,可能会显示部分结果)。通过这样做,你可以并行工作,不会违反规范。

我假设你有这样的事情,在你的服务器:

public Result retriveData(Long id) { 
    Result myResult = new Result(); 
    //... 
    //do some stuff 
    myResult.setSomeData(slowWebService1.retriveSomeData(id)); 
    myResult.setSomeOtherData(slowWebService2.retriveSomeOtherData(id)); 
    myResult.setData(slowWebService3.retriveData(id)); 
    return myResult; 
} 

在您的客户端:

Result result = webApplication.retriveData(10); 
//use the result 

我的建议,就是分裂在多个方法调用:

public SomeData retriveSomeData(Long id) { 
    //do some stuff 
    SomeData data = slowWebService1.retriveSomeData(id); 
    //do more stuff 
    return data; 
} 

public SomeOtherData retriveSomeOtherData(Long id) { 
    //do some stuff 
    SomeOtherData data = slowWebService2.retriveSomeOtherData(id); 
    //do more stuff 
    return data; 
} 

public Data retriveData(Long id) { 
    //do some stuff 
    Data data = slowWebService3.retriveData(id); 
    //do more stuff 
    return data; 
} 

在您的客户端:

//Call these methods in parallel, if you were using Swing, this could be done with 
//SwingWorker (I have no idea how to it with Flash :)). 
//You can either wait for all methods to return or show partial results. 
callInBackground(webApplication.retriveSomeData(10), useDataWhenDone); 
callInBackground(webApplication.retriveSomeOtherData(10), useDataWhenDone); 
callInBackground(webApplication.retriveData(10), useDataWhenDone); 

通过这样做,您只需调用您的Web应用程序,就像以前一样,所以不应该存在任何安全问题。

我不熟悉Websphere,所以我不能说是否使用它的异步Bean比这更好,但是你应该避免手动启动线程。

+0

谢谢你的回复“iruediger”。你的意思是缓存从Web服务检索到的数据?我们不能这样做,因为来自用户的请求是唯一的(例如:输入是SSN,并且输出将是来自许多服务的所有医疗细节)。如果您的建议不是数据缓存,可以请您多解释一下。谢谢 – user418836 2011-06-10 21:47:15

+0

是的,我正在考虑像[Ehcache](http://ehcache.org/)这样的数据缓存。由于这对您的系统来说不可行,您可以更改客户端以发出多个请求(查看我的答案)。 – iruediger 2011-06-10 22:36:46

+0

我的客户端应用程序是一个Flash应用程序,所有Web服务都是外部第三方服务。 Flash播放器具有内部安全措施,不允许与托管服务器以外的其他服务器进行交互。唯一可能发生的情况是,所有这些第三方服务器都必须在其服务器上具有crossdomain.xml,才能访问我们的服务器域。没有服务提供商会同意。唯一的选择是从我们的应用服务器调用这些服务。我们又回到原点了。 – user418836 2011-06-12 04:21:44