如何处理线程池达到服务器连接限制

Posted

技术标签:

【中文标题】如何处理线程池达到服务器连接限制【英文标题】:How to handle ThreadPool hitting the server connection limit 【发布时间】:2017-04-15 01:21:24 【问题描述】:

我可能在这里问一个设计模式问题。

android 上,我使用线程池打开 8 个线程来下载一些文件。

    try 
        ExecutorService pool = Executors.newFixedThreadPool(8);
        for (int i = 0; i < someList.size(); i++) 
            pool.submit(new DownloadJsonTask(someList.get(i), context));
        
        pool.shutdown();
        pool.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
     catch (Exception e) 
    

我注意到如果我使用一个线程逐个下载,那么我几乎不会下载失败,但如果我使用 8 个线程,那么我有时会下载失败。我不是服务器/网络人员,所以我不知道详细信息,但我猜服务器限制了一台设备(或一个 IP 地址)尝试连接多个连接。 如果是这个原因,那我该如何设计代码来克服这个问题呢?我已经实现了在失败前尝试下载 3 次。它似乎“暂时”修复了它。但是,我知道我的代码并不健壮,它可能会在某一时刻失败。

我想,我不会是第一个面临这个问题的人。我想知道针对此问题的可靠解决方案。

我能想到的解决方案: - 在失败前尝试下载至少 3 次 - 一旦失败,然后尝试随机睡眠一段时间。这样失败的线程就不会同时唤醒并再次失败。 - 如果服务器抛出某种独特的消息,例如服务器忙,则重试无限(?)(大量)次。

我还没有实施上述可能的解决方案。我想先了解常见/最佳解决方案,然后花时间实施它。

有什么想法吗?

【问题讨论】:

【参考方案1】:

这个问题是基于意见的。我正在分享我对它的看法。

理想情况下,如果您可以检查服务器日志并发现它应该在服务器端进行修复,那么您绝对应该首先这样做。

除此之外,即使客户端和服务器能够进行多线程处理并处理并发,也总会出现网络故障。也就是说,您应该在客户端有一个重试机制。

关于重试策略的一些设计要点

    保持重试次数是可配置的,而不是固定为 3。(您可以在分析和测试中找到正确的尝试次数) 不要随机睡一段时间,试试exponential backoff。 不是无限次重试,我们可以向用户标记一条消息,以便稍后在指数退避后重试自己重试。 (类似于“网站正在加载。请稍后再试”)。 查看为您进行重试的库。类似this。 网络带宽也可能是下载失败的一个原因。您可以监控网络速度和类型(WiFi、LTE、3G)等,并决定是下载还是安排稍后。

另一篇文章here。

希望这会有所帮助。

【讨论】:

以上是关于如何处理线程池达到服务器连接限制的主要内容,如果未能解决你的问题,请参考以下文章

线程池中断 任务如何处理

线程池中某个线程执行有异常,该如何处理?

线程池中某个线程执行有异常,该如何处理?

线程池异常如何处理你都了解吗?

面试官:线程池中线程抛了异常,该如何处理?

京东二面:线程池中的线程抛出了异常,该如何处理?大部分人都会答错!