【问题标题】:Send concurrently multiple POST Requests to one URL [duplicate]同时向一个 URL 发送多个 POST 请求 [重复]
【发布时间】:2016-02-03 15:40:12
【问题描述】:

主要目标是通过 REST 服务将 xml 文件从一个文件夹发送到 Cassandra DB。我要做的只是读取某个文件夹中的所有文件,然后创建一个 Worker 对象,其中设置了文件路径。

while (RUNS > 0) {
            ExecutorService executor = Executors.newFixedThreadPool(N_THREADS);

            File dir = new File(PATH_TO_SAMPLES);
            File[] listFiles = dir.listFiles();

            if (listFiles != null) {

                for (File file : listFiles) {

                    Worker worker = new Worker();
                    worker.setPath(file.toPath());

                    executor.submit(worker);
                }
            }

            executor.shutdown();

            // Wait until all threads are finish
            while (!executor.isTerminated()) {
            }

            Thread.sleep(1000);

            RUNS--;
        }

之后,执行程序获取一个工作实例并转到目录中的下一个文件。 RUNS 初始化为总迭代次数,默认为 100_000。 N_THREADS - 线程总数,默认设置为 100。

Worker 类实现 Runnable。运行方法:

@Override
    public void run() {

        String url = getUrl();
        String payload = "xml_file_representation";

        MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();

        HttpClient client = new HttpClient();

        HttpConnectionManagerParams httpConnectionManagerParams = new HttpConnectionManagerParams();
        connectionManager.setParams(httpConnectionManagerParams);

        client.setHttpConnectionManager(connectionManager);

        PostMethod postMethod = new PostMethod(url);

        try {

            postMethod.setRequestHeader("User-Agent", USER_AGENT);
            postMethod.setRequestHeader("Content-Type", "application/xml");

            postMethod.setRequestEntity(new StringRequestEntity(payload, "application/xml", StandardCharsets.UTF_8.toString()));

            int statusCode = client.executeMethod(postMethod);

            InputStream body = postMethod.getResponseBodyAsStream();

            if (statusCode == HttpStatus.SC_OK) {

                //OK
            }

        } catch (Exception e) {
            LOG.error("POST: ERROR!");
        } finally {
            postMethod.releaseConnection();
            connectionManager.shutdown();
        }
    }

如果我删除等待,即

线程.sleep(1000);

在运行结束时,当发送 ~16_000 个请求时,我会得到一个异常:

java.net.BindException: Address already in use

BindException: address already in use on a client socket?很像

无论如何,接受的答案对我没有帮助。我没有更多的想法来关闭这些“连接”以防止该错误。

像 Thread.sleep() 这样的解决方法看起来也不是很好的解决方案。感谢您的任何帮助或建议。

【问题讨论】:

  • 很好奇。只是一个猜测,但根据您的描述,线程的创建听起来可能在它们关闭之前运行;并且您的可用端口已用完。再一次,看起来您在终止应该避免这种情况的线程之前正确地关闭了 HTTP 客户端。很可能您的 finally 块正在调用在线程返回之前不会执行的本机代码。
  • @Berger 完美的建议,谢谢。方法 A(当所有线程之间共享全局 HttpClient 时)解决了我的问题。
  • @ElliotteRustyHarold 不确定真正的原因是什么,但全局 HttpClient 和 MultiThreadConnManager 已经解决了我的问题。

标签: java multithreading http post concurrency


【解决方案1】:

为每个工人创建一个连接管理器违背了连接管理器的目的。从 Berger 链接的其他帖子来看,它应该在线程之间共享。 就像没有一样。

您让操作系统在关闭后保持套接字挥之不去。除了使用其他问题中提出的设计重用套接字(连接)之外,您无能为力。

除非你想冒险玩 Socket.setSOLinger() TCP option SO_LINGER (zero) - when it's required

Thread.sleep(1000) 肯定不是一个可行的选择,因为您可能需要一天超过 1 秒...否则操作系统可能会在其他情况下更改该数量的延迟套接字。

【讨论】:

  • 将此答案选为已接受,Berger 的评论也是有用建议的一部分。谢谢
猜你喜欢
  • 1970-01-01
  • 2016-07-30
  • 1970-01-01
  • 1970-01-01
  • 2019-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多