From 42330001b6c274cda8502500b421043b1318560a Mon Sep 17 00:00:00 2001 From: liubao Date: Thu, 24 May 2018 20:51:41 +0800 Subject: [PATCH 1/2] [SCB-611]Provide a default Dispatcher to make user using edge service easier --- .../demo/edge/consumer/Consumer.java | 8 +- .../demo/edge/consumer/ConsumerMain.java | 6 +- .../main/resources/config/log4j.properties | 2 +- .../src/main/resources/microservice.yaml | 8 ++ .../edge/core/DefaultEdgeDispatcher.java | 102 ++++++++++++++++++ ...b.transport.rest.vertx.VertxHttpDispatcher | 18 ++++ .../core/TestServiceAndVersionDispatcher.java | 87 +++++++++++++++ .../rest/vertx/RestServerVerticle.java | 4 +- .../rest/vertx/VertxHttpDispatcher.java | 4 + .../rest/vertx/VertxRestDispatcher.java | 9 ++ 10 files changed, 241 insertions(+), 7 deletions(-) create mode 100644 edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/DefaultEdgeDispatcher.java create mode 100644 edge/edge-core/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher create mode 100644 edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestServiceAndVersionDispatcher.java diff --git a/demo/demo-edge/consumer/src/main/java/org/apache/servicecomb/demo/edge/consumer/Consumer.java b/demo/demo-edge/consumer/src/main/java/org/apache/servicecomb/demo/edge/consumer/Consumer.java index cff8d62b4fd..21d581e7221 100644 --- a/demo/demo-edge/consumer/src/main/java/org/apache/servicecomb/demo/edge/consumer/Consumer.java +++ b/demo/demo-edge/consumer/src/main/java/org/apache/servicecomb/demo/edge/consumer/Consumer.java @@ -78,8 +78,8 @@ public Consumer() { request.setLanguage("zh_CN"); } - public void run() { - prepareEdge(); + public void run(String prefix) { + prepareEdge(prefix); testRecursiveSelf(); testDependType(); @@ -204,12 +204,12 @@ protected void invoke(String appendUrl, int x, int y, List r results.add(result); } - private URIEndpointObject prepareEdge() { + private URIEndpointObject prepareEdge(String prefix) { Microservice microservice = RegistryUtils.getMicroservice(); EndpointsCache endpointsCache = new EndpointsCache(microservice.getAppId(), "edge", "latest", ""); Endpoint ep = endpointsCache.getLatestEndpoints().get(0); URIEndpointObject edgeAddress = (URIEndpointObject) ep.getAddress(); - edgePrefix = String.format("http://%s:%d/api/business", edgeAddress.getHostOrIp(), edgeAddress.getPort()); + edgePrefix = String.format("http://%s:%d/" + prefix + "/business", edgeAddress.getHostOrIp(), edgeAddress.getPort()); return edgeAddress; } diff --git a/demo/demo-edge/consumer/src/main/java/org/apache/servicecomb/demo/edge/consumer/ConsumerMain.java b/demo/demo-edge/consumer/src/main/java/org/apache/servicecomb/demo/edge/consumer/ConsumerMain.java index d8bd6c4991e..9a91656dec0 100644 --- a/demo/demo-edge/consumer/src/main/java/org/apache/servicecomb/demo/edge/consumer/ConsumerMain.java +++ b/demo/demo-edge/consumer/src/main/java/org/apache/servicecomb/demo/edge/consumer/ConsumerMain.java @@ -25,6 +25,10 @@ public static void main(String[] args) throws Exception { Log4jUtils.init(); BeanUtils.init(); - new Consumer().run(); + System.out.println("Running api dispater."); + new Consumer().run("api"); + System.out.println("Running rest dispater."); + new Consumer().run("rest"); + } } diff --git a/demo/demo-edge/edge-service/src/main/resources/config/log4j.properties b/demo/demo-edge/edge-service/src/main/resources/config/log4j.properties index dd0a08095db..3fc9f8bd2bb 100644 --- a/demo/demo-edge/edge-service/src/main/resources/config/log4j.properties +++ b/demo/demo-edge/edge-service/src/main/resources/config/log4j.properties @@ -15,4 +15,4 @@ # limitations under the License. # -log4j.rootLogger=DEBUG,stdout +log4j.rootLogger=INFO,stdout diff --git a/demo/demo-edge/edge-service/src/main/resources/microservice.yaml b/demo/demo-edge/edge-service/src/main/resources/microservice.yaml index f6161c34ab3..27b17dbb2c2 100644 --- a/demo/demo-edge/edge-service/src/main/resources/microservice.yaml +++ b/demo/demo-edge/edge-service/src/main/resources/microservice.yaml @@ -37,3 +37,11 @@ servicecomb: auth: loadbalance executors: default: cse.executor.groupThreadPool + http: + dispatcher: + edge: + default: + enabled: true + prefix: rest + withVersion: true + pathIndex: 2 diff --git a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/DefaultEdgeDispatcher.java b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/DefaultEdgeDispatcher.java new file mode 100644 index 00000000000..3070240e609 --- /dev/null +++ b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/DefaultEdgeDispatcher.java @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.edge.core; + +import java.util.Map; + +import com.netflix.config.DynamicPropertyFactory; + +import io.vertx.ext.web.Router; +import io.vertx.ext.web.RoutingContext; +import io.vertx.ext.web.handler.CookieHandler; + +/** + * Provide an easy mapping dispatcher. User can configure prefix to easily using edge service. + */ +public class DefaultEdgeDispatcher extends AbstractEdgeDispatcher { + private static final String KEY_ENABLED = "servicecomb.http.dispatcher.edge.default.enabled"; + + private static final String KEY_PREFIX = "servicecomb.http.dispatcher.edge.default.prefix"; + + private static final String KEY_WITH_VERSION = "servicecomb.http.dispatcher.edge.default.withVersion"; + + private static final String KEY_PATH_INDEX = "servicecomb.http.dispatcher.edge.default.pathIndex"; + + private CompatiblePathVersionMapper versionMapper = new CompatiblePathVersionMapper(); + + private String prefix; + + private boolean withVersion; + + private int pathIndex; + + @Override + public int getOrder() { + return 20000; + } + + @Override + public boolean enabled() { + return DynamicPropertyFactory.getInstance().getBooleanProperty(KEY_ENABLED, false).get(); + } + + @Override + public void init(Router router) { + prefix = DynamicPropertyFactory.getInstance().getStringProperty(KEY_PREFIX, "api").get(); + withVersion = DynamicPropertyFactory.getInstance().getBooleanProperty(KEY_WITH_VERSION, true).get(); + pathIndex = DynamicPropertyFactory.getInstance().getIntProperty(KEY_PATH_INDEX, 2).get(); + String regex; + if (withVersion) { + regex = "/" + prefix + "/([^\\\\/]+)/([^\\\\/]+)/(.*)"; + } else { + regex = "/" + prefix + "/([^\\\\/]+)/(.*)"; + } + router.routeWithRegex(regex).handler(CookieHandler.create()); + router.routeWithRegex(regex).handler(createBodyHandler()); + router.routeWithRegex(regex).failureHandler(this::onFailure).handler(this::onRequest); + } + + protected void onRequest(RoutingContext context) { + Map pathParams = context.pathParams(); + String microserviceName = pathParams.get("param0"); + String path = findActualPath(context.request().path()); + + EdgeInvocation edgeInvocation = new EdgeInvocation(); + if (withVersion) { + String pathVersion = pathParams.get("param1"); + edgeInvocation.setVersionRule(versionMapper.getOrCreate(pathVersion).getVersionRule()); + } + edgeInvocation.init(microserviceName, context, path, httpServerFilters); + edgeInvocation.edgeInvoke(); + } + + protected String findActualPath(String path) { + int fromIndex = 0; + int counter = pathIndex; + char[] chars = path.toCharArray(); + for (int i = 0; i < chars.length; i++) { + if (chars[i] == '/') { + if (--counter <= 0) { + fromIndex = i; + break; + } + } + } + return path.substring(fromIndex > 0 ? fromIndex : 0); + } +} diff --git a/edge/edge-core/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher b/edge/edge-core/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher new file mode 100644 index 00000000000..cc2856f7f12 --- /dev/null +++ b/edge/edge-core/src/main/resources/META-INF/services/org.apache.servicecomb.transport.rest.vertx.VertxHttpDispatcher @@ -0,0 +1,18 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +org.apache.servicecomb.edge.core.DefaultEdgeDispatcher \ No newline at end of file diff --git a/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestServiceAndVersionDispatcher.java b/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestServiceAndVersionDispatcher.java new file mode 100644 index 00000000000..fb36df95999 --- /dev/null +++ b/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestServiceAndVersionDispatcher.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.servicecomb.edge.core; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import io.vertx.core.Handler; +import io.vertx.core.http.HttpServerRequest; +import io.vertx.ext.web.Route; +import io.vertx.ext.web.Router; +import io.vertx.ext.web.RoutingContext; +import mockit.Deencapsulation; +import mockit.Expectations; +import mockit.Mocked; + +public class TestServiceAndVersionDispatcher { + @Before + public void setUp() { + + } + + @After + public void tearDown() { + ArchaiusUtils.resetConfig(); + } + + @Test + public void testOnRequest(@Mocked Router router, @Mocked Route route + , @Mocked RoutingContext context + , @Mocked HttpServerRequest requst + , @Mocked EdgeInvocation invocation) { + DefaultEdgeDispatcher dispatcher = new DefaultEdgeDispatcher(); + Map pathParams = new HashMap<>(); + pathParams.put("param0", "testService"); + pathParams.put("param1", "v1"); + + new Expectations() { + { + router.routeWithRegex("/api/([^\\\\/]+)/([^\\\\/]+)/(.*)"); + result = route; + route.handler((Handler) any); + result = route; + route.failureHandler((Handler) any); + result = route; + context.pathParams(); + result = pathParams; + context.request(); + result = requst; + requst.path(); + result = "/api/testService/v1/hello"; + invocation.setVersionRule("1.0.0-2.0.0"); + invocation.init("testService", context, "/testService/v1/hello", + Deencapsulation.getField(dispatcher, "httpServerFilters")); + invocation.edgeInvoke(); + } + }; + dispatcher.init(router); + Assert.assertEquals(dispatcher.enabled(), false); + Assert.assertEquals(dispatcher.findActualPath("/api/test"), "/test"); + Assert.assertEquals(dispatcher.getOrder(), 20000); + + dispatcher.onRequest(context); + // assert done in expectations. + } +} 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 a3bd7e823ea..3866827d031 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 @@ -100,7 +100,9 @@ private void mountAccessLogHandler(Router mainRouter) { private void initDispatcher(Router mainRouter) { List dispatchers = SPIServiceUtils.getSortedService(VertxHttpDispatcher.class); for (VertxHttpDispatcher dispatcher : dispatchers) { - dispatcher.init(mainRouter); + if(dispatcher.enabled()) { + dispatcher.init(mainRouter); + } } } diff --git a/transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/VertxHttpDispatcher.java b/transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/VertxHttpDispatcher.java index 6e62b144bf1..cc8b6dc23d8 100644 --- a/transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/VertxHttpDispatcher.java +++ b/transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/VertxHttpDispatcher.java @@ -22,5 +22,9 @@ public interface VertxHttpDispatcher { int getOrder(); + default boolean enabled() { + return true; + } + void init(Router router); } diff --git a/transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/VertxRestDispatcher.java b/transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/VertxRestDispatcher.java index 0d0c0e66cd8..7e7eab51e01 100644 --- a/transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/VertxRestDispatcher.java +++ b/transports/transport-rest/transport-rest-vertx/src/main/java/org/apache/servicecomb/transport/rest/vertx/VertxRestDispatcher.java @@ -36,6 +36,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.netflix.config.DynamicPropertyFactory; + import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.ErrorDataDecoderException; import io.vertx.core.json.JsonObject; import io.vertx.ext.web.Router; @@ -45,6 +47,8 @@ public class VertxRestDispatcher extends AbstractVertxHttpDispatcher { private static final Logger LOGGER = LoggerFactory.getLogger(VertxRestDispatcher.class); + private static final String KEY_ENABLED = "servicecomb.http.dispatcher.rest.enabled"; + private Transport transport; @Override @@ -52,6 +56,11 @@ public int getOrder() { return Integer.MAX_VALUE; } + @Override + public boolean enabled() { + return DynamicPropertyFactory.getInstance().getBooleanProperty(KEY_ENABLED, true).get(); + } + @Override public void init(Router router) { router.route().handler(CookieHandler.create()); From 330089f6f43134186aaf13580eec6fe70f8790d0 Mon Sep 17 00:00:00 2001 From: liubao Date: Fri, 25 May 2018 11:11:28 +0800 Subject: [PATCH 2/2] [SCB-611]fix compile warnings --- .../servicecomb/edge/core/TestServiceAndVersionDispatcher.java | 1 + 1 file changed, 1 insertion(+) diff --git a/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestServiceAndVersionDispatcher.java b/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestServiceAndVersionDispatcher.java index fb36df95999..55efc1010bd 100644 --- a/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestServiceAndVersionDispatcher.java +++ b/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestServiceAndVersionDispatcher.java @@ -47,6 +47,7 @@ public void tearDown() { } @Test + @SuppressWarnings("unchecked") public void testOnRequest(@Mocked Router router, @Mocked Route route , @Mocked RoutingContext context , @Mocked HttpServerRequest requst