<div dir="ltr">I&#39;ve been using https all the time. Let me add a debug statement to check the response protocol to ensure that http2 is used all the time. Thanks for pointing to the right direction. <div><br></div><div>Although HTTP2.0 supports multiplex, do you think it would be problem if too many concurrent requests go through the same connection? Should I create a connection poll to split the load to multiple connections like HTTP 1.1?</div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Aug 29, 2017 at 7:37 PM, Stuart Douglas <span dir="ltr">&lt;<a href="mailto:sdouglas@redhat.com" target="_blank">sdouglas@redhat.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">The issue is that you are attempting to use prior knowledge to connect<br>
to a https endpoint. HTTPS endpoints must use ALPN instead.<br>
<br>
I did not notice you were attempting to use HTTPS in the original<br>
issue. The code should not attempt an upgrade in this case. Is it<br>
possible that ALPN is failing so normal HTTP/1 is used instead, then<br>
the server closes the connection so your request fails due to the<br>
connection being closed?<br>
<span class="HOEnZb"><font color="#888888"><br>
Stuart<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
On Wed, Aug 30, 2017 at 9:24 AM, Steve Hu &lt;<a href="mailto:stevehu@gmail.com">stevehu@gmail.com</a>&gt; wrote:<br>
&gt; Hi Stuart,<br>
&gt;<br>
&gt; I have created two servers with one calls another with h2c-prior to<br>
&gt; reproduce the issue. There is a README.md in the root folder with<br>
&gt; instructions.<br>
&gt;<br>
&gt; <a href="https://github.com/stevehu/server2server" rel="noreferrer" target="_blank">https://github.com/stevehu/<wbr>server2server</a><br>
&gt;<br>
&gt; Thanks,<br>
&gt;<br>
&gt; Steve<br>
&gt;<br>
&gt; On Mon, Aug 28, 2017 at 11:01 PM, Stuart Douglas &lt;<a href="mailto:sdouglas@redhat.com">sdouglas@redhat.com</a>&gt;<br>
&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; That would be great. This is tested in the test suite so I am not sure why<br>
&gt;&gt; it is not working for you.<br>
&gt;&gt;<br>
&gt;&gt; Stuart<br>
&gt;&gt;<br>
&gt;&gt; On 29 Aug. 2017 12:59 pm, &quot;Steve Hu&quot; &lt;<a href="mailto:stevehu@gmail.com">stevehu@gmail.com</a>&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; Yes. It is another Undertow server with HTTP 2.0 enabled. I can build a<br>
&gt;&gt; repo with two servers to reproduce the issue if it is necessary.<br>
&gt;&gt;<br>
&gt;&gt; Thanks,<br>
&gt;&gt;<br>
&gt;&gt; Steve<br>
&gt;&gt;<br>
&gt;&gt; On Mon, Aug 28, 2017 at 10:43 PM, Stuart Douglas &lt;<a href="mailto:sdouglas@redhat.com">sdouglas@redhat.com</a>&gt;<br>
&gt;&gt; wrote:<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; What is the endpoint that you are trying to connect to? Is it another<br>
&gt;&gt;&gt; Undertow server?<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Stuart<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; On Tue, Aug 29, 2017 at 12:17 PM, Steve Hu &lt;<a href="mailto:stevehu@gmail.com">stevehu@gmail.com</a>&gt; wrote:<br>
&gt;&gt;&gt; &gt; Hi Stuart,<br>
&gt;&gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt; Thanks for the quick reply. I have opened an issue<br>
&gt;&gt;&gt; &gt; <a href="https://issues.jboss.org/browse/UNDERTOW-1170" rel="noreferrer" target="_blank">https://issues.jboss.org/<wbr>browse/UNDERTOW-1170</a><br>
&gt;&gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt; Also, I have tried your workaround with h2c-prior:// but got the<br>
&gt;&gt;&gt; &gt; following<br>
&gt;&gt;&gt; &gt; error in the callback.<br>
&gt;&gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt; java.nio.channels.<wbr>ClosedChannelException<br>
&gt;&gt;&gt; &gt; at<br>
&gt;&gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt; io.undertow.protocols.http2.<wbr>Http2Channel.createStream(<wbr>Http2Channel.java:827)<br>
&gt;&gt;&gt; &gt; at<br>
&gt;&gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt; io.undertow.client.http2.<wbr>Http2ClientConnection.<wbr>sendRequest(<wbr>Http2ClientConnection.java:<wbr>195)<br>
&gt;&gt;&gt; &gt; at<br>
&gt;&gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt; com.networknt.apic.handler.<wbr>DataGetHandler.handleRequest(<wbr>DataGetHandler.java:57)<br>
&gt;&gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt; On Mon, Aug 28, 2017 at 9:50 PM, Stuart Douglas &lt;<a href="mailto:sdouglas@redhat.com">sdouglas@redhat.com</a>&gt;<br>
&gt;&gt;&gt; &gt; wrote:<br>
&gt;&gt;&gt; &gt;&gt;<br>
&gt;&gt;&gt; &gt;&gt; This looks like a bug in the client with regards to how it handles<br>
&gt;&gt;&gt; &gt;&gt; HTTP upgrade. If the second request is added before the initial<br>
&gt;&gt;&gt; &gt;&gt; upgrade request is fully processed you can get this error.<br>
&gt;&gt;&gt; &gt;&gt;<br>
&gt;&gt;&gt; &gt;&gt; If you file a JIRA I will look into it. For now a possible workaround<br>
&gt;&gt;&gt; &gt;&gt; would be to use prior knowledge rather than upgrade (by using a URL of<br>
&gt;&gt;&gt; &gt;&gt; the form h2c-prior://target:p8080/<wbr>whatever).<br>
&gt;&gt;&gt; &gt;&gt;<br>
&gt;&gt;&gt; &gt;&gt; Stuart<br>
&gt;&gt;&gt; &gt;&gt;<br>
&gt;&gt;&gt; &gt;&gt; On Tue, Aug 29, 2017 at 11:25 AM, Steve Hu &lt;<a href="mailto:stevehu@gmail.com">stevehu@gmail.com</a>&gt; wrote:<br>
&gt;&gt;&gt; &gt;&gt; &gt; Hi,<br>
&gt;&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt;&gt; &gt; I am trying to use UndertowClient to call another service in the<br>
&gt;&gt;&gt; &gt;&gt; &gt; current<br>
&gt;&gt;&gt; &gt;&gt; &gt; service handleRequest using HTTP 2.0. If I have concurrent requests<br>
&gt;&gt;&gt; &gt;&gt; &gt; to<br>
&gt;&gt;&gt; &gt;&gt; &gt; the<br>
&gt;&gt;&gt; &gt;&gt; &gt; current service, then I will get the following error.<br>
&gt;&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt;&gt; &gt; java.io.IOException: UT001033: Invalid connection state<br>
&gt;&gt;&gt; &gt;&gt; &gt; at<br>
&gt;&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt;&gt; &gt; io.undertow.client.http.<wbr>HttpClientConnection.<wbr>sendRequest(<wbr>HttpClientConnection.java:336)<br>
&gt;&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt;&gt; &gt; Since HTTP 2.0 connection is multiplex, so I use instance variables<br>
&gt;&gt;&gt; &gt;&gt; &gt; for<br>
&gt;&gt;&gt; &gt;&gt; &gt; UndertowClient instance and ClientConnection instance and don&#39;t<br>
&gt;&gt;&gt; &gt;&gt; &gt; close<br>
&gt;&gt;&gt; &gt;&gt; &gt; the<br>
&gt;&gt;&gt; &gt;&gt; &gt; connection for each call.<br>
&gt;&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt;&gt; &gt; My question is how many requests can go through the same connection?<br>
&gt;&gt;&gt; &gt;&gt; &gt; Is<br>
&gt;&gt;&gt; &gt;&gt; &gt; the<br>
&gt;&gt;&gt; &gt;&gt; &gt; Invalid connection state caused by too many requests in the same<br>
&gt;&gt;&gt; &gt;&gt; &gt; connection?<br>
&gt;&gt;&gt; &gt;&gt; &gt; If yes, I can use a connection pool just like the HTTP 1.1. Also, is<br>
&gt;&gt;&gt; &gt;&gt; &gt; it<br>
&gt;&gt;&gt; &gt;&gt; &gt; possible that the server will close the connection if it is idle for<br>
&gt;&gt;&gt; &gt;&gt; &gt; a<br>
&gt;&gt;&gt; &gt;&gt; &gt; period of time?<br>
&gt;&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt;&gt; &gt; Here is the handler code for reference.<br>
&gt;&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt;&gt; &gt; public class DataGetHandler implements HttpHandler {<br>
&gt;&gt;&gt; &gt;&gt; &gt;     UndertowClient client = UndertowClient.getInstance();<br>
&gt;&gt;&gt; &gt;&gt; &gt;     ClientConnection connection;<br>
&gt;&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt;&gt; &gt;     @Override<br>
&gt;&gt;&gt; &gt;&gt; &gt;     public void handleRequest(<wbr>HttpServerExchange exchange) throws<br>
&gt;&gt;&gt; &gt;&gt; &gt; Exception<br>
&gt;&gt;&gt; &gt;&gt; &gt; {<br>
&gt;&gt;&gt; &gt;&gt; &gt;         List&lt;String&gt; list = new ArrayList&lt;&gt;();<br>
&gt;&gt;&gt; &gt;&gt; &gt;         final CountDownLatch latch = new CountDownLatch(1);<br>
&gt;&gt;&gt; &gt;&gt; &gt;         if(connection == null) {<br>
&gt;&gt;&gt; &gt;&gt; &gt;             try {<br>
&gt;&gt;&gt; &gt;&gt; &gt;                 connection = client.connect(new URI(apidHost),<br>
&gt;&gt;&gt; &gt;&gt; &gt; Http2Client.WORKER, Http2Client.SSL, Http2Client.POOL, enableHttp2 ?<br>
&gt;&gt;&gt; &gt;&gt; &gt; OptionMap.create(<wbr>UndertowOptions.ENABLE_HTTP2, true):<br>
&gt;&gt;&gt; &gt;&gt; &gt; OptionMap.EMPTY).get();<br>
&gt;&gt;&gt; &gt;&gt; &gt;             } catch (Exception e) {<br>
&gt;&gt;&gt; &gt;&gt; &gt;                 logger.error(&quot;Exeption:&quot;, e);<br>
&gt;&gt;&gt; &gt;&gt; &gt;                 throw new ClientException(e);<br>
&gt;&gt;&gt; &gt;&gt; &gt;             }<br>
&gt;&gt;&gt; &gt;&gt; &gt;         }<br>
&gt;&gt;&gt; &gt;&gt; &gt;         final AtomicReference&lt;<wbr>ClientResponse&gt; reference = new<br>
&gt;&gt;&gt; &gt;&gt; &gt; AtomicReference&lt;&gt;();<br>
&gt;&gt;&gt; &gt;&gt; &gt;         try {<br>
&gt;&gt;&gt; &gt;&gt; &gt;             ClientRequest request = new<br>
&gt;&gt;&gt; &gt;&gt; &gt; ClientRequest().setMethod(<wbr>Methods.GET).setPath(apidPath)<wbr>;<br>
&gt;&gt;&gt; &gt;&gt; &gt;             connection.sendRequest(<wbr>request,<br>
&gt;&gt;&gt; &gt;&gt; &gt; client.createClientCallback(<wbr>reference, latch));<br>
&gt;&gt;&gt; &gt;&gt; &gt;             latch.await();<br>
&gt;&gt;&gt; &gt;&gt; &gt;             int statusCode = reference.get().<wbr>getResponseCode();<br>
&gt;&gt;&gt; &gt;&gt; &gt;             if(statusCode &gt;= 300){<br>
&gt;&gt;&gt; &gt;&gt; &gt;                 throw new Exception(&quot;Failed to call API D: &quot; +<br>
&gt;&gt;&gt; &gt;&gt; &gt; statusCode);<br>
&gt;&gt;&gt; &gt;&gt; &gt;             }<br>
&gt;&gt;&gt; &gt;&gt; &gt;             List&lt;String&gt; apidList =<br>
&gt;&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt;&gt; &gt; Config.getInstance().<wbr>getMapper().readValue(<wbr>reference.get().getAttachment(<wbr>Http2Client.RESPONSE_BODY),<br>
&gt;&gt;&gt; &gt;&gt; &gt;                     new TypeReference&lt;List&lt;String&gt;&gt;(){<wbr>});<br>
&gt;&gt;&gt; &gt;&gt; &gt;             list.addAll(apidList);<br>
&gt;&gt;&gt; &gt;&gt; &gt;         } catch (Exception e) {<br>
&gt;&gt;&gt; &gt;&gt; &gt;             logger.error(&quot;Exception:&quot;, e);<br>
&gt;&gt;&gt; &gt;&gt; &gt;             throw new ClientException(e);<br>
&gt;&gt;&gt; &gt;&gt; &gt;         }<br>
&gt;&gt;&gt; &gt;&gt; &gt;         list.add(&quot;API C: Message 1&quot;);<br>
&gt;&gt;&gt; &gt;&gt; &gt;         list.add(&quot;API C: Message 2&quot;);<br>
&gt;&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt;&gt; &gt; exchange.getResponseSender().<wbr>send(Config.getInstance().<wbr>getMapper().<wbr>writeValueAsString(list));<br>
&gt;&gt;&gt; &gt;&gt; &gt;     }<br>
&gt;&gt;&gt; &gt;&gt; &gt; }<br>
&gt;&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt;&gt; &gt; ______________________________<wbr>_________________<br>
&gt;&gt;&gt; &gt;&gt; &gt; undertow-dev mailing list<br>
&gt;&gt;&gt; &gt;&gt; &gt; <a href="mailto:undertow-dev@lists.jboss.org">undertow-dev@lists.jboss.org</a><br>
&gt;&gt;&gt; &gt;&gt; &gt; <a href="https://lists.jboss.org/mailman/listinfo/undertow-dev" rel="noreferrer" target="_blank">https://lists.jboss.org/<wbr>mailman/listinfo/undertow-dev</a><br>
&gt;&gt;&gt; &gt;<br>
&gt;&gt;&gt; &gt;<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;<br>
</div></div></blockquote></div><br></div>