private static HttpClient createHttpClient(FeedClientBuilderImpl b) throws IOException {
        SslContextFactory.Client clientSslCtxFactory = new SslContextFactory.Client();
        clientSslCtxFactory.setSslContext(b.constructSslContext());
        if (b.hostnameVerifier != null) {
            clientSslCtxFactory.setHostnameVerifier(b.hostnameVerifier);
            // Disable built-in hostname verification in the JDK's TLS implementation
            clientSslCtxFactory.setEndpointIdentificationAlgorithm(null);
        }
        ClientConnector connector = new ClientConnector();
        int threads = Math.max(Math.min(Runtime.getRuntime().availableProcessors(), 32), 8);
        connector.setExecutor(new QueuedThreadPool(threads));
        connector.setSslContextFactory(clientSslCtxFactory);
        connector.setIdleTimeout(IDLE_TIMEOUT);
        boolean secureProxy = b.proxy != null && b.proxy.getScheme().equals("https");
        // Increase connect timeout for secure HTTP/2 proxy
        connector.setConnectTimeout(Duration.ofSeconds(secureProxy ? 120 : 30));
        HTTP2Client h2Client = new HTTP2Client(connector);
        h2Client.setMaxConcurrentPushedStreams(b.maxStreamsPerConnection);
        // Set the HTTP/2 flow control windows very large to cause TCP congestion instead of HTTP/2 flow control congestion.
        int initialWindow = Integer.MAX_VALUE;
        h2Client.setInitialSessionRecvWindow(initialWindow);
        h2Client.setInitialStreamRecvWindow(initialWindow);
        // Need HTTP/1.1 for tunnel using CONNECT method
        ClientConnectionFactory.Info h1 = HttpClientConnectionFactory.HTTP11;
        ClientConnectionFactory.Info http2 = new ClientConnectionFactoryOverHTTP2.HTTP2(h2Client);
        HttpClientTransportDynamic transport = new HttpClientTransportDynamic(connector, http2, h1);
        int connectionsPerEndpoint = b.connectionsPerEndpoint;
        transport.setConnectionPoolFactory(dest ->
                new MaxMultiplexConnectionPool(dest, connectionsPerEndpoint, secureProxy, b.connectionTtl));
        HttpClient httpClient = new HttpClient(transport);
        httpClient.setMaxRequestsQueuedPerDestination(Integer.MAX_VALUE);
        httpClient.setFollowRedirects(false);
        httpClient.setUserAgentField(
                new HttpField(HttpHeader.USER_AGENT, String.format("vespa-feed-client/%s (Jetty:%s)", Vespa.VERSION, Jetty.VERSION)));
        // Stop client from trying different IP address when TLS handshake fails
        httpClient.setSocketAddressResolver(new Ipv4PreferringResolver(httpClient, Duration.ofSeconds(10)));
        httpClient.setHttpCookieStore(new HttpCookieStore.Empty());

        if (b.proxy != null) addProxyConfiguration(b, httpClient);
        try { httpClient.start(); } catch (Exception e) { throw new IOException(e); }
        // Must be removed after client has started
        httpClient.getProtocolHandlers().remove(WWWAuthenticationProtocolHandler.NAME);
        return httpClient;
    }
Client implementation based on Jetty HTTP Client

@author bjorncs
vespa-feed-client/src/main/java/ai/vespa/feed/client/impl/JettyCluster.java