You are viewing a plain text version of this content. The canonical link for it is here.
Posted to httpclient-users@hc.apache.org by Santhosh Kumar <sa...@gmail.com> on 2019/02/06 06:55:11 UTC

How to do Http/2 correctly using apache-httpclient-5

HI I m trying to write a client that makes http2 request to multiple
servers(which already supports http2). so far I have written this
standalone program which works fine that I can see all requests goes via
same tcp connection(verified with the help of wireshark). I use Apache
Httpclient 5 with conscrypt to support ALPN in jdk8 (jdk8 is my
requirement, I cannot upgrade to jdk9 or later)

The Main block goes like,

try {
    TrustManager[] trustAllCerts = new TrustManager[]{
        new X509TrustManager(){
            public X509Certificate[] getAcceptedIssuers(){ return null; }
            public void checkClientTrusted(X509Certificate[] certs,
String authType) {}
            public void checkServerTrusted(X509Certificate[] certs,
String authType) {}
        }
    };
    Provider provider = Conscrypt.newProvider();

    SSLContext sslContext = SSLContext.getInstance("TLSv1.3", provider);
    sslContext.init(null, trustAllCerts, new SecureRandom());

    client = Http2AsyncClientBuilder.create().setTlsStrategy(new
ConscryptClientTlsStrategy(sslContext)).setH2Config(H2Config.DEFAULT).build();
    client.start();

    ThreadPoolExecutor tpe =
(ThreadPoolExecutor)Executors.newFixedThreadPool(50);
    for (int i=0; i < 50; i++) {
        Runnable worker = new WorkerClass(client, i);
        tpe.execute(worker);
    }} catch (Exception e) {
    e.printStackTrace();}

The runnable goes like,

static class WorkerClass implements Runnable {
    CloseableHttpAsyncClient client = null;
    int i = 0;
    WorkerClass(CloseableHttpAsyncClient client, int i) {
        this.client = client;
        this.i = i;
    }
    public void run() {
        RequestConfig requestConfig = RequestConfig.custom()
                .setConnectTimeout(Timeout.of(15,
TimeUnit.SECONDS))//Determines the timeout until a new connection is
fully established.
                .setConnectionRequestTimeout(Timeout.of(60,
TimeUnit.SECONDS))//Returns the connection lease request timeout used
when requesting a connection from the connection manager.
                .setResponseTimeout(Timeout.of(60,
TimeUnit.SECONDS))//Determines the timeout until arrival of a response
from the opposite endpoint.
                .build();

        String url =
"https://localhost:8081/myagent/getOutput?"+System.currentTimeMillis();
        String cachedXMLRequest = "<?xml version=\"1.0\"
standalone=\"no\"?><My XML REQUEST GOES HERE>";
        SimpleHttpRequest request= SimpleHttpRequests.POST.create(url);
        request.setBodyText(cachedXMLRequest, ContentType.APPLICATION_JSON);
        request.setConfig(requestConfig);
        final CountDownLatch latch = new CountDownLatch(1);
        client.execute(request, new FutureCallback<SimpleHttpResponse>() {
            @Override
            public void cancelled() {
                System.out.println("Cancelled");
                latch.countDown();
            }

            @Override
            public void completed(SimpleHttpResponse arg0) {
                System.out.println("Completed "+arg0.getBodyText());
                latch.countDown();
            }

            @Override
            public void failed(Exception exception) {
                System.out.println("Failed ");
                exception.printStackTrace();
                latch.countDown();
            }
        });

        try {
            latch.await(60, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }}

So I simulated this standalone in my client which asynchronously calls
multiple servers for polling using the above logic. But here I can see one
tcp connection per request and the connection is closed at the end of the
request(Though the response header returns as HTTP/2.0). I use the main
block code to initialize the client at the startup of my application and
create the url, request and response objects and execute each request
simultaneously in a threaded model(Asynchronous multiplexing). My
requirement is to use one tcp connection per domain and use it for
prolonged time for handling high number of requests. What am I missing here?

Or someone hep me with the proper way fo handling http2 using httpclient 5

Kindy shed some light on it.

SO link :
https://stackoverflow.com/questions/54548110/how-to-do-http2-correctly-with-apache-httpcient-5-beta


TIA

-- 
*With Regards,*
*Santhosh Kumar J*

Re: How to do Http/2 correctly using apache-httpclient-5

Posted by Oleg Kalnichevski <ol...@apache.org>.
On Wed, 2019-02-06 at 12:25 +0530, Santhosh Kumar wrote:
> HI I m trying to write a client that makes http2 request to multiple
> servers(which already supports http2). so far I have written this
> standalone program which works fine that I can see all requests goes
> via
> same tcp connection(verified with the help of wireshark). I use
> Apache
> Httpclient 5 with conscrypt to support ALPN in jdk8 (jdk8 is my
> requirement, I cannot upgrade to jdk9 or later)
> 
> The Main block goes like,
> 
> try {
>     TrustManager[] trustAllCerts = new TrustManager[]{
>         new X509TrustManager(){
>             public X509Certificate[] getAcceptedIssuers(){ return
> null; }
>             public void checkClientTrusted(X509Certificate[] certs,
> String authType) {}
>             public void checkServerTrusted(X509Certificate[] certs,
> String authType) {}
>         }
>     };
>     Provider provider = Conscrypt.newProvider();
> 
>     SSLContext sslContext = SSLContext.getInstance("TLSv1.3",
> provider);
>     sslContext.init(null, trustAllCerts, new SecureRandom());
> 
>     client = Http2AsyncClientBuilder.create().setTlsStrategy(new
> ConscryptClientTlsStrategy(sslContext)).setH2Config(H2Config.DEFAULT)
> .build();
>     client.start();
> 
>     ThreadPoolExecutor tpe =
> (ThreadPoolExecutor)Executors.newFixedThreadPool(50);
>     for (int i=0; i < 50; i++) {
>         Runnable worker = new WorkerClass(client, i);
>         tpe.execute(worker);
>     }} catch (Exception e) {
>     e.printStackTrace();}
> 
> The runnable goes like,
> 
> static class WorkerClass implements Runnable {
>     CloseableHttpAsyncClient client = null;
>     int i = 0;
>     WorkerClass(CloseableHttpAsyncClient client, int i) {
>         this.client = client;
>         this.i = i;
>     }
>     public void run() {
>         RequestConfig requestConfig = RequestConfig.custom()
>                 .setConnectTimeout(Timeout.of(15,
> TimeUnit.SECONDS))//Determines the timeout until a new connection is
> fully established.
>                 .setConnectionRequestTimeout(Timeout.of(60,
> TimeUnit.SECONDS))//Returns the connection lease request timeout used
> when requesting a connection from the connection manager.
>                 .setResponseTimeout(Timeout.of(60,
> TimeUnit.SECONDS))//Determines the timeout until arrival of a
> response
> from the opposite endpoint.
>                 .build();
> 
>         String url =
> "https://localhost:8081/myagent/getOutput?"+System.currentTimeMillis(
> );
>         String cachedXMLRequest = "<?xml version=\"1.0\"
> standalone=\"no\"?><My XML REQUEST GOES HERE>";
>         SimpleHttpRequest request=
> SimpleHttpRequests.POST.create(url);
>         request.setBodyText(cachedXMLRequest,
> ContentType.APPLICATION_JSON);
>         request.setConfig(requestConfig);
>         final CountDownLatch latch = new CountDownLatch(1);
>         client.execute(request, new
> FutureCallback<SimpleHttpResponse>() {
>             @Override
>             public void cancelled() {
>                 System.out.println("Cancelled");
>                 latch.countDown();
>             }
> 
>             @Override
>             public void completed(SimpleHttpResponse arg0) {
>                 System.out.println("Completed "+arg0.getBodyText());
>                 latch.countDown();
>             }
> 
>             @Override
>             public void failed(Exception exception) {
>                 System.out.println("Failed ");
>                 exception.printStackTrace();
>                 latch.countDown();
>             }
>         });
> 
>         try {
>             latch.await(60, TimeUnit.SECONDS);
>         } catch (InterruptedException e) {
>             // TODO Auto-generated catch block
>             e.printStackTrace();
>         }
>     }}
> 
> So I simulated this standalone in my client which asynchronously
> calls
> multiple servers for polling using the above logic. But here I can
> see one
> tcp connection per request and the connection is closed at the end of
> the
> request(Though the response header returns as HTTP/2.0). I use the
> main
> block code to initialize the client at the startup of my application
> and
> create the url, request and response objects and execute each request
> simultaneously in a threaded model(Asynchronous multiplexing). My
> requirement is to use one tcp connection per domain and use it for
> prolonged time for handling high number of requests. What am I
> missing here?
> 
> Or someone hep me with the proper way fo handling http2 using
> httpclient 5
> 
> Kindy shed some light on it.
> 
> SO link :
> 
https://stackoverflow.com/questions/54548110/how-to-do-http2-correctly-with-apache-httpcient-5-beta
> 
> 
> TIA
> 

What is exactly the problem you are having? Is it that connections get
closed after each message exchange? If so, please post wire log of the
session 

hc.apache.org/httpcomponents-client-5.0.x/logging.html

Oleg



---------------------------------------------------------------------
To unsubscribe, e-mail: httpclient-users-unsubscribe@hc.apache.org
For additional commands, e-mail: httpclient-users-help@hc.apache.org