This is an automated email from the ASF dual-hosted git repository. liubao pushed a commit to branch 1.3.x in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git
commit ef6895ef508b1fbd00d40e8cd92a1e51cd0bec04 Author: bao liu <[email protected]> AuthorDate: Tue Nov 26 10:47:28 2019 +0800 [SCB-1616]refactor edge dispatcher to make them more extensible (#1406) --- .../edge/core/DefaultEdgeDispatcher.java | 4 +- .../edge/core/URLMappedConfigurationItem.java | 72 ++++++++++++++++ .../edge/core/URLMappedConfigurationLoader.java | 83 +++++++++++++++++++ .../edge/core/URLMappedEdgeDispatcher.java | 95 +++++----------------- .../edge/core/TestURLMappedEdgeDispatcher.java | 21 +++-- .../transport/rest/vertx/VertxRestDispatcher.java | 16 +++- 6 files changed, 200 insertions(+), 91 deletions(-) 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 index 0d195c6..19f9f65 100644 --- 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 @@ -30,6 +30,8 @@ import io.vertx.ext.web.RoutingContext; public class DefaultEdgeDispatcher extends AbstractEdgeDispatcher { private static final String KEY_ENABLED = "servicecomb.http.dispatcher.edge.default.enabled"; + private static final String KEY_ORDER = "servicecomb.http.dispatcher.edge.default.order"; + 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"; @@ -46,7 +48,7 @@ public class DefaultEdgeDispatcher extends AbstractEdgeDispatcher { @Override public int getOrder() { - return 20000; + return DynamicPropertyFactory.getInstance().getIntProperty(KEY_ORDER, 20_000).get(); } @Override diff --git a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/URLMappedConfigurationItem.java b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/URLMappedConfigurationItem.java new file mode 100644 index 0000000..2fa3846 --- /dev/null +++ b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/URLMappedConfigurationItem.java @@ -0,0 +1,72 @@ +/* + * 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.regex.Pattern; + +public class URLMappedConfigurationItem { + private String microserviceName; + + private String versionRule; + + private int prefixSegmentCount; + + private Pattern pattern; + + private String stringPattern; + + public String getMicroserviceName() { + return microserviceName; + } + + public void setMicroserviceName(String microserviceName) { + this.microserviceName = microserviceName; + } + + public String getVersionRule() { + return versionRule; + } + + public void setVersionRule(String versionRule) { + this.versionRule = versionRule; + } + + public int getPrefixSegmentCount() { + return prefixSegmentCount; + } + + public void setPrefixSegmentCount(int prefixSegmentCount) { + this.prefixSegmentCount = prefixSegmentCount; + } + + public Pattern getPattern() { + return pattern; + } + + public void setPattern(Pattern pattern) { + this.pattern = pattern; + } + + public String getStringPattern() { + return stringPattern; + } + + public void setStringPattern(String stringPattern) { + this.stringPattern = stringPattern; + } +} diff --git a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/URLMappedConfigurationLoader.java b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/URLMappedConfigurationLoader.java new file mode 100644 index 0000000..a6f7522 --- /dev/null +++ b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/URLMappedConfigurationLoader.java @@ -0,0 +1,83 @@ +/* + * 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.Iterator; +import java.util.Map; +import java.util.regex.Pattern; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.netflix.config.ConcurrentCompositeConfiguration; +import com.netflix.config.DynamicPropertyFactory; + +public class URLMappedConfigurationLoader { + private static final Logger LOG = LoggerFactory.getLogger(URLMappedConfigurationLoader.class); + + private static final String KEY_MAPPING_PATH = ".path"; + + private static final String KEY_MAPPING_SERVICE_NAME = "%s.%s.microserviceName"; + + private static final String KEY_MAPPING_VERSION_RULE = "%s.%s.versionRule"; + + private static final String KEY_MAPPING_PREFIX_SEGMENT_COUNT = "%s.%s.prefixSegmentCount"; + + public static Map<String, URLMappedConfigurationItem> loadConfigurations( + ConcurrentCompositeConfiguration config, String configPrefix) { + Map<String, URLMappedConfigurationItem> configurations = new HashMap<>(); + Iterator<String> configsItems = config.getKeys(configPrefix); + while (configsItems.hasNext()) { + String pathKey = configsItems.next(); + if (pathKey.endsWith(KEY_MAPPING_PATH)) { + URLMappedConfigurationItem configurationItem = new URLMappedConfigurationItem(); + String pattern = DynamicPropertyFactory.getInstance() + .getStringProperty(pathKey, null).get(); + if (StringUtils.isEmpty(pattern)) { + continue; + } + configurationItem.setPattern(Pattern.compile(pattern)); + configurationItem.setStringPattern(pattern); + String pathKeyItem = pathKey + .substring(configPrefix.length() + 1, pathKey.length() - KEY_MAPPING_PATH.length()); + configurationItem.setMicroserviceName(DynamicPropertyFactory.getInstance() + .getStringProperty(String.format(KEY_MAPPING_SERVICE_NAME, configPrefix, pathKeyItem), null).get()); + if (StringUtils.isEmpty(configurationItem.getMicroserviceName())) { + continue; + } + configurationItem.setPrefixSegmentCount(DynamicPropertyFactory.getInstance() + .getIntProperty(String.format(KEY_MAPPING_PREFIX_SEGMENT_COUNT, configPrefix, pathKeyItem), 0).get()); + configurationItem.setVersionRule(DynamicPropertyFactory.getInstance() + .getStringProperty(String.format(KEY_MAPPING_VERSION_RULE, configPrefix, pathKeyItem), "0.0.0+").get()); + configurations.put(pathKeyItem, configurationItem); + } + } + logConfigurations(configurations); + return configurations; + } + + private static void logConfigurations(Map<String, URLMappedConfigurationItem> configurations) { + configurations.entrySet().forEach(stringConfigurationItemEntry -> { + URLMappedConfigurationItem item = stringConfigurationItemEntry.getValue(); + LOG.info("config item: key=" + stringConfigurationItemEntry.getKey() + ";pattern=" + item.getStringPattern() + + ";service=" + item.getMicroserviceName() + ";versionRule=" + item.getVersionRule()); + }); + } +} diff --git a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/URLMappedEdgeDispatcher.java b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/URLMappedEdgeDispatcher.java index c734b40..31d6936 100644 --- a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/URLMappedEdgeDispatcher.java +++ b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/URLMappedEdgeDispatcher.java @@ -18,11 +18,8 @@ package org.apache.servicecomb.edge.core; import java.util.HashMap; -import java.util.Iterator; import java.util.Map; -import java.util.regex.Pattern; -import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,35 +33,19 @@ import io.vertx.ext.web.RoutingContext; * Provide a URL mapping based dispatcher. Users configure witch URL patterns dispatch to a target service. */ public class URLMappedEdgeDispatcher extends AbstractEdgeDispatcher { - class ConfigurationItem { - String microserviceName; - - String versionRule; - - int prefixSegmentCount; - - Pattern pattern; - - String stringPattern; - } - private static final Logger LOG = LoggerFactory.getLogger(URLMappedEdgeDispatcher.class); private static final String PATTERN_ANY = "/(.*)"; - private static final String KEY_ENABLED = "servicecomb.http.dispatcher.edge.url.enabled"; - - private static final String KEY_MAPPING_PREIX = "servicecomb.http.dispatcher.edge.url.mappings"; - - private static final String KEY_MAPPING_PATH = ".path"; + private static final String KEY_ORDER = "servicecomb.http.dispatcher.edge.url.order"; - private static final String KEY_MAPPING_SERVICE_NAME = "servicecomb.http.dispatcher.edge.url.mappings.%s.microserviceName"; + private static final String KEY_ENABLED = "servicecomb.http.dispatcher.edge.url.enabled"; - private static final String KEY_MAPPING_VERSION_RULE = "servicecomb.http.dispatcher.edge.url.mappings.%s.versionRule"; + private static final String KEY_PATTERN = "servicecomb.http.dispatcher.edge.url.pattern"; - private static final String KEY_MAPPING_PREFIX_SEGMENT_COUNT = "servicecomb.http.dispatcher.edge.url.mappings.%s.prefixSegmentCount"; + private static final String KEY_MAPPING_PREIX = "servicecomb.http.dispatcher.edge.url.mappings"; - private Map<String, ConfigurationItem> configurations = new HashMap<>(); + private Map<String, URLMappedConfigurationItem> configurations = new HashMap<>(); public URLMappedEdgeDispatcher() { if (this.enabled()) { @@ -74,7 +55,7 @@ public class URLMappedEdgeDispatcher extends AbstractEdgeDispatcher { @Override public int getOrder() { - return 30000; + return DynamicPropertyFactory.getInstance().getIntProperty(KEY_ORDER, 30_000).get(); } @Override @@ -85,82 +66,44 @@ public class URLMappedEdgeDispatcher extends AbstractEdgeDispatcher { @Override public void init(Router router) { // cookies handler are enabled by default start from 3.8.3 - router.routeWithRegex(PATTERN_ANY).handler(createBodyHandler()); - router.routeWithRegex(PATTERN_ANY).failureHandler(this::onFailure).handler(this::onRequest); + String pattern = DynamicPropertyFactory.getInstance().getStringProperty(KEY_PATTERN, PATTERN_ANY).get(); + router.routeWithRegex(pattern).handler(createBodyHandler()); + router.routeWithRegex(pattern).failureHandler(this::onFailure).handler(this::onRequest); } private void loadConfigurations() { ConcurrentCompositeConfiguration config = (ConcurrentCompositeConfiguration) DynamicPropertyFactory .getBackingConfigurationSource(); - loadConfigurations(config); + configurations = URLMappedConfigurationLoader.loadConfigurations(config, KEY_MAPPING_PREIX); config.addConfigurationListener(event -> { if (event.getPropertyName().startsWith(KEY_MAPPING_PREIX)) { LOG.info("Map rule have been changed. Reload configurations. Event=" + event.getType()); - loadConfigurations(config); + configurations = URLMappedConfigurationLoader.loadConfigurations(config, KEY_MAPPING_PREIX); } }); } - private void loadConfigurations(ConcurrentCompositeConfiguration config) { - Map<String, ConfigurationItem> configurations = new HashMap<>(); - Iterator<String> configsItems = config.getKeys(KEY_MAPPING_PREIX); - while (configsItems.hasNext()) { - String pathKey = configsItems.next(); - if (pathKey.endsWith(KEY_MAPPING_PATH)) { - ConfigurationItem configurationItem = new ConfigurationItem(); - String pattern = DynamicPropertyFactory.getInstance() - .getStringProperty(pathKey, null).get(); - if (StringUtils.isEmpty(pattern)) { - continue; - } - configurationItem.pattern = Pattern.compile(pattern); - configurationItem.stringPattern = pattern; - String pathKeyItem = pathKey - .substring(KEY_MAPPING_PREIX.length() + 1, pathKey.length() - KEY_MAPPING_PATH.length()); - configurationItem.microserviceName = DynamicPropertyFactory.getInstance() - .getStringProperty(String.format(KEY_MAPPING_SERVICE_NAME, pathKeyItem), null).get(); - if (StringUtils.isEmpty(configurationItem.microserviceName)) { - continue; - } - configurationItem.prefixSegmentCount = DynamicPropertyFactory.getInstance() - .getIntProperty(String.format(KEY_MAPPING_PREFIX_SEGMENT_COUNT, pathKeyItem), 0).get(); - configurationItem.versionRule = DynamicPropertyFactory.getInstance() - .getStringProperty(String.format(KEY_MAPPING_VERSION_RULE, pathKeyItem), "0.0.0+").get(); - configurations.put(pathKeyItem, configurationItem); - } - } - this.configurations = configurations; - logConfigurations(); - } - - private void logConfigurations() { - configurations.entrySet().forEach(stringConfigurationItemEntry -> { - ConfigurationItem item = stringConfigurationItemEntry.getValue(); - LOG.info("config item: key=" + stringConfigurationItemEntry.getKey() + ";pattern=" + item.stringPattern - + ";service=" + item.microserviceName + ";versionRule=" + item.versionRule); - }); - } protected void onRequest(RoutingContext context) { - ConfigurationItem configurationItem = findConfigurationItem(context.request().path()); + URLMappedConfigurationItem configurationItem = findConfigurationItem(context.request().path()); if (configurationItem == null) { context.next(); return; } - String path = Utils.findActualPath(context.request().path(), configurationItem.prefixSegmentCount); + String path = Utils.findActualPath(context.request().path(), configurationItem.getPrefixSegmentCount()); EdgeInvocation edgeInvocation = createEdgeInvocation(); - if (configurationItem.versionRule != null) { - edgeInvocation.setVersionRule(configurationItem.versionRule); + if (configurationItem.getVersionRule() != null) { + edgeInvocation.setVersionRule(configurationItem.getVersionRule()); } - edgeInvocation.init(configurationItem.microserviceName, context, path, httpServerFilters); + edgeInvocation.init(configurationItem.getMicroserviceName(), context, path, httpServerFilters); edgeInvocation.edgeInvoke(); } - private ConfigurationItem findConfigurationItem(String path) { - for (ConfigurationItem item : configurations.values()) { - if (item.pattern.matcher(path).matches()) { + private URLMappedConfigurationItem findConfigurationItem(String path) { + for (URLMappedConfigurationItem item : configurations.values()) { + if (item.getPattern().matcher(path).matches()) { return item; } } diff --git a/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestURLMappedEdgeDispatcher.java b/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestURLMappedEdgeDispatcher.java index 353051c..b308d2c 100644 --- a/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestURLMappedEdgeDispatcher.java +++ b/edge/edge-core/src/test/java/org/apache/servicecomb/edge/core/TestURLMappedEdgeDispatcher.java @@ -19,7 +19,6 @@ package org.apache.servicecomb.edge.core; import java.util.Map; -import org.apache.servicecomb.edge.core.URLMappedEdgeDispatcher.ConfigurationItem; import org.apache.servicecomb.foundation.common.utils.Log4jUtils; import org.apache.servicecomb.foundation.test.scaffolding.config.ArchaiusUtils; import org.junit.After; @@ -51,7 +50,7 @@ public class TestURLMappedEdgeDispatcher { ArchaiusUtils.setProperty("servicecomb.http.dispatcher.edge.url.enabled", true); URLMappedEdgeDispatcher dispatcher = new URLMappedEdgeDispatcher(); - Map<String, ConfigurationItem> items = Deencapsulation + Map<String, URLMappedConfigurationItem> items = Deencapsulation .getField(dispatcher, "configurations"); Assert.assertEquals(items.size(), 0); @@ -68,21 +67,21 @@ public class TestURLMappedEdgeDispatcher { ArchaiusUtils.setProperty("servicecomb.http.dispatcher.edge.url.mappings.service1.versionRule", "2.0.0+"); items = Deencapsulation.getField(dispatcher, "configurations"); Assert.assertEquals(items.size(), 1); - ConfigurationItem item = items.get("service1"); - Assert.assertEquals(item.microserviceName, "serviceName"); - Assert.assertEquals(item.prefixSegmentCount, 2); - Assert.assertEquals(item.stringPattern, "/a/b/c/.*"); - Assert.assertEquals(item.versionRule, "2.0.0+"); + URLMappedConfigurationItem item = items.get("service1"); + Assert.assertEquals(item.getMicroserviceName(), "serviceName"); + Assert.assertEquals(item.getPrefixSegmentCount(), 2); + Assert.assertEquals(item.getStringPattern(), "/a/b/c/.*"); + Assert.assertEquals(item.getVersionRule(), "2.0.0+"); ArchaiusUtils.setProperty("servicecomb.http.dispatcher.edge.url.mappings.service2.versionRule", "2.0.0+"); ArchaiusUtils.setProperty("servicecomb.http.dispatcher.edge.url.mappings.service3.path", "/b/c/d/.*"); items = Deencapsulation.getField(dispatcher, "configurations"); Assert.assertEquals(items.size(), 1); item = items.get("service1"); - Assert.assertEquals(item.microserviceName, "serviceName"); - Assert.assertEquals(item.prefixSegmentCount, 2); - Assert.assertEquals(item.stringPattern, "/a/b/c/.*"); - Assert.assertEquals(item.versionRule, "2.0.0+"); + Assert.assertEquals(item.getMicroserviceName(), "serviceName"); + Assert.assertEquals(item.getPrefixSegmentCount(), 2); + Assert.assertEquals(item.getStringPattern(), "/a/b/c/.*"); + Assert.assertEquals(item.getVersionRule(), "2.0.0+"); new Expectations() { { 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 763a360..bbecec5 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 @@ -46,13 +46,17 @@ import io.vertx.ext.web.RoutingContext; public class VertxRestDispatcher extends AbstractVertxHttpDispatcher { private static final Logger LOGGER = LoggerFactory.getLogger(VertxRestDispatcher.class); + private static final String KEY_ORDER = "servicecomb.http.dispatcher.rest.order"; + private static final String KEY_ENABLED = "servicecomb.http.dispatcher.rest.enabled"; + private static final String KEY_PATTERN = "servicecomb.http.dispatcher.rest.pattern"; + private Transport transport; @Override public int getOrder() { - return Integer.MAX_VALUE; + return DynamicPropertyFactory.getInstance().getIntProperty(KEY_ORDER, Integer.MAX_VALUE).get(); } @Override @@ -63,8 +67,14 @@ public class VertxRestDispatcher extends AbstractVertxHttpDispatcher { @Override public void init(Router router) { // cookies handler are enabled by default start from 3.8.3 - router.route().handler(createBodyHandler()); - router.route().failureHandler(this::failureHandler).handler(this::onRequest); + String pattern = DynamicPropertyFactory.getInstance().getStringProperty(KEY_PATTERN, null).get(); + if(pattern == null) { + router.route().handler(createBodyHandler()); + router.route().failureHandler(this::failureHandler).handler(this::onRequest); + } else { + router.routeWithRegex(pattern).handler(createBodyHandler()); + router.routeWithRegex(pattern).failureHandler(this::failureHandler).handler(this::onRequest); + } } protected void failureHandler(RoutingContext context) {
