【问题标题】:Is using threadpool in this multthreading case advisible?在这种多线程情况下使用线程池是否可行?
【发布时间】:2011-06-10 18:44:55
【问题描述】:

环境:Webphere 6、Solaris box、Thick client、Java web app。

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

我假设 150 个请求正在创建 150*15=2250 个线程,并且应用服务器资源正在激增并因此崩溃。所以我想使用 App 服务器线程池并让 threadCount 说 100(可能不是好数字..)。困扰我的一件事是,我可以使用 100 个线程处理前 6 个(6*15 = 90)个请求和第 7 个请求的 10 个调用。下一个请求必须等待 10-15 秒才能恢复线程,然后再等待 10-15 秒才能调用自己的 Web 服务。这种方法还好吗?

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

请推荐!!。一个接一个地调用一个网络服务总共需要 15*(假设每个请求需要 4 秒)= 60 秒,这真的很糟糕。所以把webserices一起调用是我想做的。

【问题讨论】:

    标签: multithreading asynchronous javabeans simultaneous-calls


    【解决方案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);
    

    这样做你只是调用你的网络应用程序,就像以前一样,所以不应该有任何安全问题。

    我不熟悉 Websphere,所以我不知道使用它的异步 bean 是否比这更好,但是恕我直言您应该避免手动启动线程。

    【讨论】:

    • 感谢您回复“iruediger”。您的意思是缓存从 Web 服务检索到的数据吗?我们不能这样做,因为来自用户的请求是唯一的(例如:输入是 SSN,输出将是来自许多服务的所有医疗详细信息)。如果您的建议不是数据缓存,请您解释一下。谢谢
    • 是的,我正在考虑使用 Ehcache 之类的数据缓存。由于这对您的系统不可行,因此您可以更改客户端以发出多个请求(查看我的答案)。
    • 我的客户端应用程序是一个 Flash 应用程序,所有的 Web 服务都是外部 3rd 方服务。 Flash 播放器具有内部安全措施,不允许与其托管服务器以外的其他服务器进行交互。发生这种情况的唯一方法是,所有这些第 3 方服务器必须在其服务器中具有 crossdomain.xml 以访问我们的服务器域。没有服务提供商会同意。唯一的选择是从我们的应用服务器调用这些服务。我们又回到了第一广场。
    • 您不需要直接与其他服务器交互。您的 Web 应用可以委托从客户端收到的请求。我假设您的 Web 应用程序有一个调用所有 Web 服务的方法,我的建议是将其拆分为多个方法(在您的托管服务器中),每个方法都会调用不同的 Web 服务,客户端将组装最终结果。我将在我的答案中添加一些伪代码以使其更清晰。
    • 感谢 iruediger。我将提出这个解决方案,并要求测试团队使用这种方法进行负载测试。另一方面,此选项可能无法完全正常工作,因为首先调用了 9 个 Web 服务并分析了 9 个 Web 服务的结果,并根据结果调用了下一组 Web 服务和 DB。它的业务逻辑...前端的这种逻辑???。用这种方法很难说服所有人。很抱歉我没有提到实际的调用过程。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多