Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8195137

HttpClient doesn't reuse TCP connection for both h2 and h2c connections

    Details

      Description

      Run the following test:

      import static jdk.incubator.http.HttpClient.Version.HTTP_2;

      import java.net.URI;
      import java.nio.file.Paths;
      import java.util.Arrays;
      import java.util.Enumeration;
      import java.util.Set;
      import java.util.concurrent.CompletableFuture;
      import java.util.concurrent.ConcurrentSkipListSet;
      import java.math.BigInteger;
      import javax.net.ssl.SSLSessionContext;

      import org.testng.annotations.DataProvider;
      import org.testng.annotations.Test;

      import jdk.incubator.http.HttpClient;
      import jdk.incubator.http.HttpClient.Version;
      import jdk.incubator.http.HttpRequest;
      import jdk.incubator.http.HttpResponse;

      /*
       * @test
       * @compile HttpTestUtils.java
       * @modules jdk.incubator.httpclient
       * @run testng/othervm TestConnectionReuse
       */
      public class TestConnectionReuse {
          private static HttpClient getClient(Version v) {
              return HttpTestUtils.clientBuilder().version(v).build();
          }
          
          @DataProvider(name = "uri")
          public Object[][] uri() {
              return new Object[][] {
                      {new String[] { "https://<host>/yc/data/d31.data",
                        "https://<host>/yc/data/d32.data",
                        "https://<host>/yc/data/d33.data",
                        "https://<host>/yc/data/d34.data",
                        "https://<host>/yc/data/d35.data"
                      }}
              };
          }
          
          @Test(dataProvider = "uri")
          public void testAllStrart(String[] uris) throws Exception {
              HttpClient client = getClient(HTTP_2);

              CompletableFuture[] results = new CompletableFuture[uris.length];
              Set<byte[]> sessionSet = new ConcurrentSkipListSet<>((byte[] e1, byte[] e2) -> new BigInteger​(e1).compareTo(new BigInteger​(e2)));
              
              for (int i = 0; i < uris.length; i++)
                  results[i] = client.sendAsync(
                          HttpRequest.newBuilder(new URI(uris[i])).GET().build(),
                          (statusCode, responseHeaders) -> {
                              SSLSessionContext ctx = client.sslContext().getClientSessionContext();
                              Enumeration<byte[]> ids = ctx.getIds();
                              while (ids.hasMoreElements()) {
                                  byte[] id = ids.nextElement();
                                  sessionSet.add(Arrays.copyOf(id, id.length));
                              }
                              return HttpResponse.BodySubscriber.asByteArray();
                          });

              CompletableFuture.allOf(results).join();
              
              System.out.println("session: ");
              for (byte[] session : sessionSet)
                  System.out.println(Arrays.toString(session));
          }
          
          @Test(dataProvider = "uri")
          public void testOneLead(String[] uris) throws Exception {
              HttpClient client = getClient(HTTP_2);

              CompletableFuture[] results = new CompletableFuture[uris.length];
              Set<byte[]> sessionSet = new ConcurrentSkipListSet<>((byte[] e1, byte[] e2) -> new BigInteger​(e1).compareTo(new BigInteger​(e2)));
              
              results[0] = client.sendAsync(
                      HttpRequest.newBuilder(new URI(uris[0])).GET().build(),
                      (statusCode, responseHeaders) -> {
                          SSLSessionContext ctx = client.sslContext().getClientSessionContext();
                          Enumeration<byte[]> ids = ctx.getIds();
                          while (ids.hasMoreElements()) {
                              byte[] id = ids.nextElement();
                              sessionSet.add(Arrays.copyOf(id, id.length));
                          }
                          return HttpResponse.BodySubscriber.asByteArray();
                      });
              results[0].join();
              
              for (int i = 1; i < uris.length; i++)
                  results[i] = client.sendAsync(
                          HttpRequest.newBuilder(new URI(uris[i])).GET().build(),
                          (statusCode, responseHeaders) -> {
                              SSLSessionContext ctx = client.sslContext().getClientSessionContext();
                              Enumeration<byte[]> ids = ctx.getIds();
                              while (ids.hasMoreElements()) {
                                  byte[] id = ids.nextElement();
                                  sessionSet.add(Arrays.copyOf(id, id.length));
                              }
                              return HttpResponse.BodySubscriber.asByteArray();
                          });

              CompletableFuture.allOf(results).join();
              
              System.out.println("session: ");
              for (byte[] session : sessionSet)
                  System.out.println(Arrays.toString(session));
          }
      }

      It shows 5 sessions in testAllStrart, 1 new session in testOneLead(the first 5 sessions are created in testAllStrart).

      I also tested h2c, but I have no means to show by program, however, I check the network traffics, it also doesn't reuse one tcp connnection in testAllStrart.

        Attachments

          Activity

            People

            • Assignee:
              chegar Chris Hegarty
              Reporter:
              fyuan Frank Yuan
            • Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: