This is an automated email from the ASF dual-hosted git repository. liubao pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-servicecomb-java-chassis.git
The following commit(s) were added to refs/heads/master by this push: new ec56566 [SCB-482] Http2 support for java-chassis ec56566 is described below commit ec565664840065e851d79d8285487bb809af2188 Author: Rajadeepan D Ramesh <rajadeepan.d.ram...@huawei.com> AuthorDate: Fri May 11 07:45:38 2018 +0530 [SCB-482] Http2 support for java-chassis * Adding support to http2 * support h2c also * Adding UT and AT for supporting Http2 * Addressing review comments * Addressing Review comments * [SCB-482]Addressing review comments --- .../src/main/resources/microservice.yaml | 2 +- .../foundation/common/net/URIEndpointObject.java | 14 ++++++ .../common/net/TestURIEndpointObject.java | 7 +++ .../transport/rest/client/RestTransportClient.java | 32 ++++++++++++- .../rest/client/TestRestTransportClient.java | 53 ++++++++++++++++++++++ .../transport/rest/vertx/RestServerVerticle.java | 4 +- .../rest/vertx/TestRestServerVerticle.java | 32 +++++++++++++ 7 files changed, 141 insertions(+), 3 deletions(-) diff --git a/demo/demo-pojo/pojo-server/src/main/resources/microservice.yaml b/demo/demo-pojo/pojo-server/src/main/resources/microservice.yaml index 9ca4af4..e705183 100644 --- a/demo/demo-pojo/pojo-server/src/main/resources/microservice.yaml +++ b/demo/demo-pojo/pojo-server/src/main/resources/microservice.yaml @@ -24,7 +24,7 @@ servicecomb: registry: address: http://127.0.0.1:30100 rest: - address: 0.0.0.0:8080 + address: 0.0.0.0:8080?protocol=http2 highway: address: 0.0.0.0:7070 #executors: diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/net/URIEndpointObject.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/net/URIEndpointObject.java index 8ec116d..4c46e14 100644 --- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/net/URIEndpointObject.java +++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/net/URIEndpointObject.java @@ -33,8 +33,14 @@ import org.apache.http.client.utils.URLEncodedUtils; public class URIEndpointObject extends IpPort { private static final String SSL_ENABLED_KEY = "sslEnabled"; + private static final String PROTOCOL_KEY = "protocol"; + + private static final String HTTP2 = "http2"; + private boolean sslEnabled; + private boolean http2Enabled; + private Map<String, List<String>> querys; public URIEndpointObject(String endpoint) { @@ -47,6 +53,10 @@ public class URIEndpointObject extends IpPort { setPort(uri.getPort()); querys = splitQuery(uri); sslEnabled = Boolean.parseBoolean(getFirst(SSL_ENABLED_KEY)); + String httpversion = getFirst(PROTOCOL_KEY); + if (httpversion != null && httpversion.equals(HTTP2)) { + http2Enabled = true; + } } public static Map<String, List<String>> splitQuery(URI uri) { @@ -65,6 +75,10 @@ public class URIEndpointObject extends IpPort { return sslEnabled; } + public boolean isHttp2Enabled() { + return http2Enabled; + } + public List<String> getQuery(String key) { return querys.get(key); } diff --git a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/net/TestURIEndpointObject.java b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/net/TestURIEndpointObject.java index 9590687..5f7f4d4 100644 --- a/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/net/TestURIEndpointObject.java +++ b/foundations/foundation-common/src/test/java/org/apache/servicecomb/foundation/common/net/TestURIEndpointObject.java @@ -41,6 +41,13 @@ public class TestURIEndpointObject { Assert.assertEquals(8080, obj.getPort()); Assert.assertTrue(obj.isSslEnabled()); Assert.assertNull(obj.getFirst("notExist")); + + obj = new URIEndpointObject("http://127.0.2.0:8080?sslEnabled=true&protocol=http2"); + Assert.assertEquals("127.0.2.0", obj.getHostOrIp()); + Assert.assertEquals(8080, obj.getPort()); + Assert.assertTrue(obj.isSslEnabled()); + Assert.assertTrue(obj.isHttp2Enabled()); + Assert.assertNull(obj.getFirst("notExist")); } @Test(expected = IllegalArgumentException.class) diff --git a/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/RestTransportClient.java b/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/RestTransportClient.java index 8c43814..7b04ecb 100644 --- a/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/RestTransportClient.java +++ b/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/RestTransportClient.java @@ -21,6 +21,7 @@ import java.util.List; import org.apache.servicecomb.common.rest.filter.HttpClientFilter; import org.apache.servicecomb.core.Invocation; +import org.apache.servicecomb.foundation.common.net.URIEndpointObject; import org.apache.servicecomb.foundation.common.utils.SPIServiceUtils; import org.apache.servicecomb.foundation.vertx.VertxTLSBuilder; import org.apache.servicecomb.foundation.vertx.VertxUtils; @@ -36,6 +37,7 @@ import org.slf4j.LoggerFactory; import io.vertx.core.DeploymentOptions; import io.vertx.core.Vertx; import io.vertx.core.http.HttpClientOptions; +import io.vertx.core.http.HttpVersion; public class RestTransportClient { private static final Logger LOGGER = LoggerFactory.getLogger(RestTransportClient.class); @@ -44,8 +46,11 @@ public class RestTransportClient { protected ClientPoolManager<HttpClientWithContext> clientMgr; + private ClientPoolManager<HttpClientWithContext> clientMgrHttp2; + private List<HttpClientFilter> httpClientFilters; + public ClientPoolManager<HttpClientWithContext> getClientMgr() { return clientMgr; } @@ -56,9 +61,20 @@ public class RestTransportClient { HttpClientOptions httpClientOptions = createHttpClientOptions(); clientMgr = new ClientPoolManager<>(vertx, new HttpClientPoolFactory(httpClientOptions)); + + HttpClientOptions httpClientOptionshttp2 = createHttpClientOptions(); + httpClientOptionshttp2.setUseAlpn(true).setProtocolVersion(HttpVersion.HTTP_2); + httpClientOptionshttp2.setHttp2ClearTextUpgrade(false); + + clientMgrHttp2 = new ClientPoolManager<>(vertx, new HttpClientPoolFactory(httpClientOptionshttp2)); + DeploymentOptions deployOptions = VertxUtils.createClientDeployOptions(clientMgr, TransportClientConfig.getThreadCount()); VertxUtils.blockDeploy(vertx, ClientVerticle.class, deployOptions); + + DeploymentOptions deployOptionshttp2 = VertxUtils.createClientDeployOptions(clientMgrHttp2, + TransportClientConfig.getThreadCount()); + VertxUtils.blockDeploy(vertx, ClientVerticle.class, deployOptionshttp2); } private static HttpClientOptions createHttpClientOptions() { @@ -73,8 +89,18 @@ public class RestTransportClient { } public void send(Invocation invocation, AsyncResponse asyncResp) { - HttpClientWithContext httpClientWithContext = findHttpClientPool(invocation); + URIEndpointObject endpoint = (URIEndpointObject) invocation.getEndpoint().getAddress(); + HttpClientWithContext httpClientWithContext; + + if (endpoint.isHttp2Enabled()) { + httpClientWithContext = findHttp2ClientPool(invocation); + + } else { + httpClientWithContext = findHttpClientPool(invocation); + } + RestClientInvocation restClientInvocation = new RestClientInvocation(httpClientWithContext, httpClientFilters); + try { restClientInvocation.invoke(invocation, asyncResp); } catch (Throwable e) { @@ -86,4 +112,8 @@ public class RestTransportClient { protected HttpClientWithContext findHttpClientPool(Invocation invocation) { return clientMgr.findClientPool(invocation.isSync()); } + + public HttpClientWithContext findHttp2ClientPool(Invocation invocation) { + return clientMgrHttp2.findClientPool(invocation.isSync()); + } } diff --git a/transports/transport-rest/transport-rest-client/src/test/java/org/apache/servicecomb/transport/rest/client/TestRestTransportClient.java b/transports/transport-rest/transport-rest-client/src/test/java/org/apache/servicecomb/transport/rest/client/TestRestTransportClient.java index d133105..c008adf 100644 --- a/transports/transport-rest/transport-rest-client/src/test/java/org/apache/servicecomb/transport/rest/client/TestRestTransportClient.java +++ b/transports/transport-rest/transport-rest-client/src/test/java/org/apache/servicecomb/transport/rest/client/TestRestTransportClient.java @@ -17,10 +17,14 @@ package org.apache.servicecomb.transport.rest.client; +import java.lang.reflect.Field; + import org.apache.servicecomb.common.rest.RestConst; import org.apache.servicecomb.common.rest.definition.RestOperationMeta; +import org.apache.servicecomb.core.Endpoint; import org.apache.servicecomb.core.Invocation; import org.apache.servicecomb.core.definition.OperationMeta; +import org.apache.servicecomb.foundation.common.net.URIEndpointObject; import org.apache.servicecomb.foundation.vertx.VertxUtils; import org.apache.servicecomb.foundation.vertx.client.ClientPoolManager; import org.apache.servicecomb.foundation.vertx.client.http.HttpClientWithContext; @@ -35,6 +39,7 @@ import io.vertx.core.AbstractVerticle; import io.vertx.core.DeploymentOptions; import io.vertx.core.Vertx; import io.vertx.core.http.HttpClientOptions; +import io.vertx.core.http.impl.HttpClientImpl; import mockit.Deencapsulation; import mockit.Mock; import mockit.MockUp; @@ -52,6 +57,17 @@ public class TestRestTransportClient { RestOperationMeta swaggerRestOperation = Mockito.mock(RestOperationMeta.class); + URIEndpointObject uriEndpointObject = Mockito.mock(URIEndpointObject.class); + + Endpoint endPoint = Mockito.mock(Endpoint.class); + + HttpClientWithContext httpClientWithContext = Mockito.mock(HttpClientWithContext.class); + + HttpClientImpl httpClient = Mockito.mock(HttpClientImpl.class); + + HttpClientOptions httpClientOptions = Mockito.mock(HttpClientOptions.class); + + @Before public void setUp() throws Exception { instance = new RestTransportClient(); @@ -97,6 +113,43 @@ public class TestRestTransportClient { Assert.assertFalse(status); } + + @Test + public void testRestTransportClientHttp2(@Mocked Vertx vertx, @Mocked VertxUtils utils) + throws Exception { + boolean status = true; + Mockito.when(invocation.getEndpoint()).thenReturn(endPoint); + Mockito.when(invocation.isSync()).thenReturn(true); + Mockito.when(endPoint.getAddress()).thenReturn(uriEndpointObject); + Mockito.when(uriEndpointObject.isHttp2Enabled()).thenReturn(true); + Mockito.when(invocation.getOperationMeta()).thenReturn(operationMeta); + Mockito.when(operationMeta.getExtData(RestConst.SWAGGER_REST_OPERATION)).thenReturn(operationMeta); + Mockito.when(httpClientWithContext.getHttpClient()).thenReturn(httpClient); + Mockito.when(httpClient.getOptions()).thenReturn(httpClientOptions); + + instance.init(vertx); + Field clientMgrHttp2Field = instance.getClass().getDeclaredField("clientMgrHttp2"); + clientMgrHttp2Field.setAccessible(true); + + + ClientPoolManager<HttpClientWithContext> client = new ClientPoolManager<HttpClientWithContext>(vertx, null) { + @Mock + public HttpClientWithContext findClientPool(boolean sync) { + return httpClientWithContext; + } + }; + + clientMgrHttp2Field.set(instance, client); + + try { + instance.send(invocation, asyncResp); + } catch (Exception e) { + status = false; + } + + Assert.assertTrue(status); + } + @Test public void testCreateHttpClientOptions() { HttpClientOptions obj = (HttpClientOptions) Deencapsulation.invoke(instance, "createHttpClientOptions"); diff --git a/transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/RestServerVerticle.java b/transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/RestServerVerticle.java index 3eb679c..a3bd7e8 100644 --- a/transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/RestServerVerticle.java +++ b/transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/RestServerVerticle.java @@ -133,7 +133,9 @@ public class RestServerVerticle extends AbstractVerticle { serverOptions.setIdleTimeout(TransportConfig.getConnectionIdleTimeoutInSeconds()); serverOptions.setCompressionSupported(TransportConfig.getCompressed()); serverOptions.setMaxHeaderSize(TransportConfig.getMaxHeaderSize()); - + if (endpointObject.isHttp2Enabled()) { + serverOptions.setUseAlpn(true); + } if (endpointObject.isSslEnabled()) { SSLOptionFactory factory = SSLOptionFactory.createSSLOptionFactory(SSL_KEY, null); diff --git a/transports/transport-rest/transport-rest-vertx/src/test/java/org/apache/servicecomb/transport/rest/vertx/TestRestServerVerticle.java b/transports/transport-rest/transport-rest-vertx/src/test/java/org/apache/servicecomb/transport/rest/vertx/TestRestServerVerticle.java index ebd1c3e..146c561 100644 --- a/transports/transport-rest/transport-rest-vertx/src/test/java/org/apache/servicecomb/transport/rest/vertx/TestRestServerVerticle.java +++ b/transports/transport-rest/transport-rest-vertx/src/test/java/org/apache/servicecomb/transport/rest/vertx/TestRestServerVerticle.java @@ -110,6 +110,38 @@ public class TestRestServerVerticle { } @Test + public void testRestServerVerticleWithHttp2(@Mocked Transport transport, @Mocked Vertx vertx, + @Mocked Context context, + @Mocked JsonObject jsonObject, @Mocked Future<Void> startFuture) throws Exception { + URIEndpointObject endpointObject = new URIEndpointObject("http://127.0.0.1:8080?protocol=http2"); + new Expectations() { + { + transport.parseAddress("http://127.0.0.1:8080?protocol=http2"); + result = endpointObject; + } + }; + Endpoint endpiont = new Endpoint(transport, "http://127.0.0.1:8080?protocol=http2"); + + new Expectations() { + { + context.config(); + result = jsonObject; + jsonObject.getValue(AbstractTransport.ENDPOINT_KEY); + result = endpiont; + } + }; + RestServerVerticle server = new RestServerVerticle(); + boolean status = false; + try { + server.init(vertx, context); + server.start(startFuture); + } catch (Exception e) { + status = true; + } + Assert.assertFalse(status); + } + + @Test public void testStartFutureAddressEmpty() { boolean status = false; try { -- To stop receiving notification emails like this one, please contact liu...@apache.org.