简体   繁体   English

Java中连接受限的多个HTTPS请求

[英]Multiple HTTPS requests with limited connections in java

I'm working on a task where I need to make multiple request to an HTTPS url from my java program and read the response. 我正在执行一项任务,我需要从我的Java程序向HTTPS URL发出多个请求并读取响应。 This process is to be repeated multiple times with different requests. 对于不同的请求,此过程将重复多次。

The latency(time difference between request and response) for each request is around 300ms if I use just 1 thread - making requests sequentially.And the throughput is around 3.3 requests per second. 如果我仅使用1个线程-依次发出请求,则每个请求的等待时间(请求与响应之间的时间差)约为300毫秒-吞吐量约为每秒3.3个请求。

However, as the goal is to get a high throughput number I have decided to go with multiple threads each making a request at given point of time. 但是,由于目标是获得较高的吞吐量,因此我决定使用多个线程,每个线程在给定的时间点发出请求。

Some important details: 一些重要的细节:

  1. I am using only those number of URL instances as number of threads. 我仅使用那些数量的URL实例作为线程数。 The idea is that each thread uses a single URL instance and calls new URL(url).openConnection() every time it makes a request. 这个想法是每个线程都使用一个URL实例,并在每次发出请求时调用new URL(url).openConnection()。

  2. I'm closing input stream using inputStream.close() each time after reading the response and this closing will make the socket reusable. 每次读取响应后,我都会使用inputStream.close()关闭输入流,并且这种关闭将使套接字可重用。

  3. I'm not calling httpConnectionURL.disconnect() as this will close the underlying socket. 我没有调用httpConnectionURL.disconnect(),因为这将关闭基础套接字。

  4. I have set http.maxConnections to number of threads using System.setProperty("http.maxConnections", threadCount); 我已经使用System.setProperty(“ http.maxConnections”,threadCount)将http.maxConnections设置为线程数;

  5. I am also checking the number of connections open at any given point of time using "netstat -a | grep | wc -l" and this is always giving a number equat to or above threadcount as expected. 我还在使用“ netstat -a | grep | wc -l”检查在任何给定时间点打开的连接数,并且该数字总是等于或大于预期的线程数。

Even after doing all these, I am not getting an expected throughput. 即使完成所有这些操作,我仍达不到预期的吞吐量。 For 1 thread when I am getting a throughput of 3.3 I assume using 100 threads I should get a throughput of at least 300 per second. 对于1个线程,当我获得3.3的吞吐量时,我假设使用100个线程,我应该获得至少300 /秒的吞吐量。

Can anyone kindly explain me where am I going wrong. 谁能告诉我我要去哪里错了。 or any other better solutions. 或任何其他更好的解决方案。 Below is my code snippet. 以下是我的代码段。

Main Class:
    public static void main(String[] args)
    {
      URL[] urlConnArray = new URL[threadCount];
      for(int j = 0;j < urlConnArray.length;j++)
        urlConnArray[j] = new URL(regURL);

      System.setProperty("http.keepalive", "true");
      System.setProperty("http.maxConnections", String.valueOf(threadCount));

      for(int i=0;i<1000000;i++)
      {
         Thread regThread = new Thread(new RegisterThread(urlConnArray[i]));
         regThread.start();
      }
    }

RegisterThread Class:
    public class RegisterThread implements Runnable
    {
       httpConn = (HttpURLConnection) urlConnArray[i].openConnection();
       httpConn.setUseCaches(false);
       httpConn.setDoOutput(true);
       httpConn.setRequestMethod("POST");
       httpConn.setRequestProperty("Content-Type", "application/json" );
       //Prepare the request body.....
       long requestTime = System.currentTimeMillis();
       InputStream is = httpConn.getInputStream();
       long responseTime = System.currentTimeMillis();
       long latency = responseTime - requestTime;
       reader = new BufferedReader(new InputStreamReader(is));  
       StringBuffer response = new StringBuffer();
       String line = "";
       while ((line = reader.readLine()) != null) 
       {
          response.append(line);
       } 
       is.close();
     }

Too Many Threads 线程太多

  • The code is creating far too many concurrent threads at 1,000,000 (the code loops 1M times creating a new thread and starting each time). 该代码以1,000,000的数量创建了太多的并发线程(该代码循环1M次,以创建一个新线程并每次启动)。

  • The URL definitions being pooled and a new connection is being opened each time 每次都合并URL定义并打开一个新连接

  • You may also get better performance from some of the custom REST clients available from various sources (Apache, Grizzly, Netty etc) than from the inbuilt JDK URL / Connnection classes . 从各种来源(Apache,Grizzly,Netty等)获得的一些自定义REST客户端,与内置的JDK URL / Connnection类相比,您可能还会获得更好的性能。

I/O Bound I / O绑定

The application is I/O bound, rather than CPU bound. 该应用程序受I / O约束,而不是CPU约束。

This app should have a lot more threads than cores , but not 1 million! 这个应用程式的执行应该比核心多得多 ,但不能超过一百万! (I'm surprised it's not running out of memory). (我很惊讶它没有用完内存)。

The reasons you should use more threads 您应该使用更多线程的原因

  1. The I/O blocks the current thread, while it waits on data from a remote System I / O在等待来自远程系统的数据时阻止当前线程

  2. The CPU can be better utilized doing other work during that period 在此期间,可以更好地利用CPU进行其他工作

  3. Having more threads than CPU cores for blocking I/O will, therefore, result in both better CPU usage, and better I/O. 因此,拥有比CPU内核更多的线程来阻止I / O,将导致更好的CPU使用率和更好的I / O。

Paul Tyma's overview on synchronous I/O & Non-blocking I/O (2008) is a very useful read. Paul Tyma对同步I / O和非阻塞I / O的概述 (2008)非常有用。

Java 8 Streaming Java 8流

While JDK in Java 8 provides Streaming infrastructure for CPU bound tasks (not suitable here), we have a created library simple-react that is designed precisely for your purpose - improving system throughput where you have blocking IO. 虽然Java 8中的JDK为CPU绑定的任务提供了Streaming基础结构(此处不适合),但我们已经创建了一个简单反应的库,该库专门针对您的目的而设计-提高了阻塞IO的系统吞吐量。 With simple-react you could create a Stream something like this 使用简单反应,您可以创建类似这样的流

   LazyReact streamBuilder = new LazyReact(threadCount);  //create a Stream builder with x threads

   streamBuilder.range(0,1000000)
                .map(i-> new RegisterThread(urlConnArray[i])))
                .forEach(url-> url.run());

Unfortunately, your assumption is wrong. 不幸的是,您的假设是错误的。

For 1 thread when I am getting a throughput of 3.3. 对于1个线程,当我获得3.3的吞吐量时。 I assume using 100 threads I should get a throughput of at least 300 per second. 我假设使用100个线程,我应该获得至少每秒300个吞吐量。

The performance of multi-threading will depend on number of cores of CPU. 多线程的性能将取决于CPU的内核数量。 If you are running your application on one core CPU, you may not notice any gain with multi-threading. 如果您在一个核心CPU上运行应用程序,那么多线程可能不会带来任何好处。 Even things will become worse due to context switching between multiple threads due to single core CPU. 由于单核CPU,由于在多个线程之间进行上下文切换,甚至情况会变得更糟。 In that case, your results are inferior to single thread processing for the same use case. 在这种情况下,对于相同的用例,您的结果将不如单线程处理。

If you have 100 core CPU, you can achieve results similar to 300-500ms per thread amusing that threads are not using many shared locks on objects/methods. 如果您有100个核心CPU,则每个线程可以获得300-500ms的相似结果,这是因为线程没有在对象/方法上使用许多共享锁。

If you want to fine tune the performance, I would suggest below changes ( in General and not specific to your problem) 如果您想微调性能,我建议您进行以下更改(总体而言,并非针对您的问题)

1) Use java advanced threading features like ExecutorService etc and declare the thread pool count as number of cores of your CPU. 1)使用Java高级线程功能(例如ExecutorService等),并将线程池计数声明为CPU的内核数。

2) Avoid shared locks as much as possible between threads. 2)尽可能避免线程之间的共享锁。

Have a look at java support for multi-threaing in multi core CPUs at java support for parallel processing Java对并行处理的支持下,了解Java对多核CPU中的多处理器的支持。

Example of executor service code. 执行程序服务代码示例。

// Here replace 10 with number > number of CPU cores for better performance

ExecutorService executorService = Executors.newFixedThreadPool(10);

executorService.execute(new Runnable() {
    public void run() {
        // Here add your business logic
        System.out.println("Asynchronous task");
    }
});

executorService.shutdown();

Have a look at Executor Service usage 看看执行器服务的用法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM