当前位置: 首页 > 知识库问答 >
问题:

Apache HTTPClient 4. x vs多个JDK URL连接

羊舌和安
2023-03-14

我正在试用ApacheHttpClient 4.3.6连接池管理器,以提高HTTP调用的吞吐量。我的假设是,HTTPClient实现通常使用持久性连接。然而,我的测试代码(包括在最后)的结果显示,使用JDKURLConnection的多个并发HTTP连接的性能更好。

  1. 如何使HTTPClient快速

谢啦

import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;

public class FooTest {

public static void main(String[] args) throws Exception {
    runWithConnectionPool();
}

 private static String extract(BufferedReader reader) throws Exception {
     StringBuilder buffer = new StringBuilder();
     String line = null;
     while ((line = reader.readLine()) != null) {
         buffer.append(line);
     }
     return buffer.toString();
 }

 private static void runWithConnectionPool() throws Exception {
     PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
     cm.setMaxTotal(1);

     CloseableHttpClient httpClient = HttpClients.custom()
         .setConnectionManager(cm)
         .setMaxConnTotal(100)
         .setMaxConnPerRoute(100)
         .build();

     long start = System.currentTimeMillis();

     HttpGet getReq = new HttpGet("http://www.google.com");

     /*
       Option A: Using HTTP connection pool
       Option B: Individual JDK 8 URL connection
     */
 //    Thread[] workers = generateAndStart(10, httpClient, getReq, 0);                 // (A)
     Thread[] workers = generateAndStart(10, getReq.getURI().toURL(), 0);  // (B)

     for (int i = 0; i < workers.length; i++) {
         workers[i].join();
     }

     System.out.println("Elasped: " + (System.currentTimeMillis() - start));
 }

 private static Thread[] generateAndStart(int num, URL url, long delay) {
     Thread[] workers = new Thread[num];
     for (int i = 0; i < num; i++) {
         System.out.println("Starting worker: " + i);
         int j = i;
         workers[i] = new Thread(() -> connect(url, delay, j));
         workers[i].start();
     }
     return workers;
 }

 private static void connect(URL url, long delay, int ndx)  {
     try {
         System.out.println(url.toURI().toString() + " started.");
     } catch (Exception e) {
         e.printStackTrace();
     }

     try {

         URLConnection connection = url.openConnection();
         connection.addRequestProperty("Accept", "application/json");
         BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));

         String line;
         while ((line = reader.readLine()) != null) {
             ObjectMapper mapper = new ObjectMapper();
             System.out.println(line);
         }
         if (delay > 0) {
             System.out.println("Delayed.");
             sleep(delay);
         }
         reader.close();
     } catch (Exception e) {
         e.printStackTrace();
     }
 }

 private static Thread[] generateAndStart(int num, CloseableHttpClient httpClient, HttpGet getReq, long delay) {
     Thread[] workers = new Thread[num];
     for (int i = 0; i < num; i++) {
         System.out.println("Starting worker: " + i);
         final int j = i;
         workers[i] = new Thread(() -> connect(httpClient, getReq, delay, j));
         workers[i].start();
     }
     return workers;
 }

 private static void connect(CloseableHttpClient httpClient, HttpGet request, long delay, int ndx) {
     System.out.println(request.getURI().toString() + " started.");

     try(
         CloseableHttpResponse response = httpClient.execute(request, HttpClientContext.create());
         BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()))) {

         String line;
         while ((line = reader.readLine()) != null) {
             ObjectMapper mapper = new ObjectMapper();
             System.out.println(line);
         }
         if (delay > 0) {
             System.out.println("Delayed.");
             sleep(delay);
         }
     } catch (Exception e) {
         e.printStackTrace();
     }
 }

 private static void sleep(long delay) {
     try {
         Thread.sleep(delay);
     } catch (Exception e) {
         e.printStackTrace();
     }
 }
 }

我做了一些观察和结论,

  1. JDKjava。网URLConnectionURLConnection之前不会建立连接。调用getInputStream()

我的观察来自我贴在这里的例子。它们是比上面粘贴的代码更好的示例。

共有1个答案

解阳荣
2023-03-14

在使用JDKURLConnection和Apache HTTPClient进行实验后,我找到了答案。

  1. URLConnection速度很快,因为它为每个线程与服务器的每个连接打开新的套接字,而Apache HTTPClient根据其在多线程环境中的设置控制打开的套接字数量。当套接字被限制为很少时,两个HTTP库的总连接时间大致相同
  2. Apache HTTPClient对不同的URL使用到同一服务器的持久连接

mitmproxy是一个很好且易于使用的HTTP连接验证工具。

 类似资料:
  • 问题内容: 目前,我的连接 mongoose.js 具有以下代码: 需要连接的文件是 test.js : 如何更新mongoose.js以使用mongoose.createConnection(…)函数使用多个连接? 当我进行如下更改时,我仅从一个连接的更改开始: 我得到“未定义不是函数”。如果我使用此代码: 我收到“错误:尝试打开未关闭的连接” 有什么建议吗? 问题答案: mongoose通过

  • 我有一些元素,我想通过JSPlumb社区版将它们连接起来。我在javascript中有以下代码行: 我想做的是在运行时制作两个和一个,并将两个源endpoint连接到目标endpoint,但当我将一个源endpoint连接到目标endpoint时,目标不会接受第二个源endpoint。我该怎么做?

  • 问题内容: 我正在尝试创建一个应用程序,该应用程序可以连接并接收来自多个蓝牙低能耗设备的通知。我想知道如何实现这一目标。每个连接是否需要一个单独的线程?考虑到API的异步特性,如何确保能够按发现的顺序发现服务并设置通知。我目前使用的是此处提供的相同结构:https : //developer.android.com/guide/topics/connectivity/bluetooth- le.h

  • 问题内容: 我正在使用标准的join命令来连接基于column1的两个排序文件。命令是简单的连接文件1文件2>输出文件。 但是,如何使用相同的技术加入3个或更多文件?join file1 file2 file3> output_file上面的命令给了我一个空文件。我认为sed可以帮助我,但我不太确定该怎么做? 问题答案: : 它仅适用于 两个 文件。 如果您需要加入三个,也许您可​​以先加入前两个

  • 问题内容: 我从来没有做过这样的PHP / MYSQL技巧来加入多表。请具有该领域经验的人员帮助: TICKETS 表中的字段: 表 RECEPTS中的 字段: 表 PAYMENTS中的 字段: 表 CUSTOMERS中的 字段: 表之间的关系很容易理解: 我希望达到的最终结果: 我试图做这样的事情,但在某个地方出错: 问题答案: 您应该可以使用以下方法获得结果: 参见带有演示的SQL Fiddl

  • 问题内容: 我正在尝试使用hibernate条件生成器连接4个表。 下面分别是这些表。 在这4个表中,我想为MySQL执行以下sql脚本: 那么,如何使用Hibernate CriteriaBuilder实现这一目标?请帮助… 预先感谢....... 问题答案: CriteriaBuilder cb = entityManager.getCriteriaBuilder(); CriteriaQue

  • 请以我的英语为基础,我正在使用spring Boot2和注册3 jndi连接的tomcat,如下所示:

  • 我的本机查询将类似于:“select*from a inner join b inner join c on a.ida=b.idb and b.lastname=c.lastname and a.name=c.name” 在hibernate中,如果要连接两个表,可以使用@joincolum,如果要通过表B连接表A和表C,可以使用@joincable。 因此在HQL中查询将看起来像:“from