You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by li...@apache.org on 2023/02/04 02:32:40 UTC

[servicecomb-java-chassis] branch master updated: [SCB-2767]change filter chain to spring bean injection (#3615)

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/servicecomb-java-chassis.git


The following commit(s) were added to refs/heads/master by this push:
     new a624636b3 [SCB-2767]change filter chain to spring bean injection (#3615)
a624636b3 is described below

commit a624636b3e84590b207647eac4dff8389f89bfff
Author: liubao68 <bi...@qq.com>
AuthorDate: Sat Feb 4 10:32:34 2023 +0800

    [SCB-2767]change filter chain to spring bean injection (#3615)
---
 .../rest/filter/inner/RestServerCodecFilter.java   |  13 +++
 .../org/apache/servicecomb/core/Invocation.java    |   9 +-
 .../servicecomb/core/filter/ConsumerFilter.java    |   7 +-
 .../org/apache/servicecomb/core/filter/Filter.java |  30 +++---
 .../core/filter/FilterChainsManager.java           |  36 ++-----
 .../apache/servicecomb/core/filter/FilterNode.java |  20 +---
 .../servicecomb/core/filter/InternalFilter.java    |  20 ----
 .../core/filter/InvocationFilterChains.java        |  89 ++++-------------
 .../servicecomb/core/filter/ProducerFilter.java    |   7 +-
 .../filter/config/AbstractFilterChainsConfig.java  |  33 -------
 .../core/filter/config/FilterChainsConfig.java     | 105 ---------------------
 .../config/InvocationFilterChainsConfig.java       |  69 --------------
 .../core/filter/config/TransportChainsConfig.java  |  40 --------
 .../servicecomb/core/filter/impl/EmptyFilter.java  |   4 +-
 .../core/filter/impl/ParameterValidatorFilter.java |   7 ++
 .../core/filter/impl/ProducerOperationFilter.java  |   7 ++
 .../core/filter/impl/ScheduleFilter.java           |   7 ++
 .../core/filter/impl/SimpleLoadBalanceFilter.java  |   7 ++
 .../core/filter/impl/TransportFilters.java         |  59 ------------
 .../servicecomb/core/filter/FilterChainTest.java   |  75 +--------------
 .../servicecomb/core/filter/SimpleRetryFilter.java |   6 ++
 .../servicecomb/edge/core/EdgeAddHeaderFilter.java |   9 +-
 .../edge/core/EdgeServerCodecFilter.java           |  18 +++-
 .../transport/highway/HighwayClientFilter.java     |  13 +++
 .../highway/HighwayServerCodecFilter.java          |  13 +++
 .../rest/client/RestClientCodecFilter.java         |  13 +++
 .../rest/client/RestClientSenderFilter.java        |  13 +++
 27 files changed, 186 insertions(+), 543 deletions(-)

diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/inner/RestServerCodecFilter.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/inner/RestServerCodecFilter.java
index a6d166eca..8634ac960 100644
--- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/inner/RestServerCodecFilter.java
+++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/filter/inner/RestServerCodecFilter.java
@@ -33,14 +33,17 @@ import org.apache.servicecomb.common.rest.RestConst;
 import org.apache.servicecomb.common.rest.codec.RestCodec;
 import org.apache.servicecomb.common.rest.codec.produce.ProduceProcessor;
 import org.apache.servicecomb.common.rest.definition.RestOperationMeta;
+import org.apache.servicecomb.core.Const;
 import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.core.definition.OperationMeta;
+import org.apache.servicecomb.core.filter.Filter;
 import org.apache.servicecomb.core.filter.FilterNode;
 import org.apache.servicecomb.core.filter.ProducerFilter;
 import org.apache.servicecomb.foundation.common.utils.AsyncUtils;
 import org.apache.servicecomb.foundation.vertx.http.HttpServletRequestEx;
 import org.apache.servicecomb.foundation.vertx.http.HttpServletResponseEx;
 import org.apache.servicecomb.foundation.vertx.stream.BufferOutputStream;
+import org.apache.servicecomb.swagger.invocation.InvocationType;
 import org.apache.servicecomb.swagger.invocation.Response;
 import org.springframework.stereotype.Component;
 
@@ -57,6 +60,16 @@ public class RestServerCodecFilter implements ProducerFilter {
     return NAME;
   }
 
+  @Override
+  public int getOrder(InvocationType invocationType, String microservice) {
+    return Filter.PRODUCER_SCHEDULE_FILTER_ORDER - 1000;
+  }
+
+  @Override
+  public boolean isEnabledForTransport(String transport) {
+    return Const.RESTFUL.equals(transport);
+  }
+
   @Override
   public CompletableFuture<Response> onFilter(Invocation invocation, FilterNode nextNode) {
     return CompletableFuture.completedFuture(invocation)
diff --git a/core/src/main/java/org/apache/servicecomb/core/Invocation.java b/core/src/main/java/org/apache/servicecomb/core/Invocation.java
index b1b48c7f3..8a2c9f855 100644
--- a/core/src/main/java/org/apache/servicecomb/core/Invocation.java
+++ b/core/src/main/java/org/apache/servicecomb/core/Invocation.java
@@ -27,7 +27,6 @@ import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicLong;
 
-import com.google.common.annotations.VisibleForTesting;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.servicecomb.core.definition.InvocationRuntimeType;
 import org.apache.servicecomb.core.definition.MicroserviceMeta;
@@ -60,6 +59,7 @@ import org.apache.servicecomb.swagger.invocation.SwaggerInvocation;
 import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
 
 import com.fasterxml.jackson.databind.JavaType;
+import com.google.common.annotations.VisibleForTesting;
 
 public class Invocation extends SwaggerInvocation {
   private static final Collection<TraceIdGenerator> TRACE_ID_GENERATORS = loadTraceIdGenerators();
@@ -149,6 +149,13 @@ public class Invocation extends SwaggerInvocation {
     traceIdLogger = new TraceIdLogger(this);
   }
 
+  public String getTransportName() {
+    if (endpoint == null || endpoint.getTransport() == null) {
+      return null;
+    }
+    return endpoint.getTransport().getName();
+  }
+
   public Transport getTransport() {
     if (endpoint == null) {
       throw new IllegalStateException(
diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/ConsumerFilter.java b/core/src/main/java/org/apache/servicecomb/core/filter/ConsumerFilter.java
index 2ede1f025..899286787 100644
--- a/core/src/main/java/org/apache/servicecomb/core/filter/ConsumerFilter.java
+++ b/core/src/main/java/org/apache/servicecomb/core/filter/ConsumerFilter.java
@@ -16,9 +16,6 @@
  */
 package org.apache.servicecomb.core.filter;
 
-import java.util.Collections;
-import java.util.List;
-
 import javax.annotation.Nonnull;
 
 import org.apache.servicecomb.swagger.invocation.InvocationType;
@@ -26,7 +23,7 @@ import org.apache.servicecomb.swagger.invocation.InvocationType;
 public interface ConsumerFilter extends Filter {
   @Nonnull
   @Override
-  default List<InvocationType> getInvocationTypes() {
-    return Collections.singletonList(InvocationType.CONSUMER);
+  default boolean isEnabledForInvocationType(InvocationType invocationType) {
+    return invocationType == InvocationType.CONSUMER;
   }
 }
diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/Filter.java b/core/src/main/java/org/apache/servicecomb/core/filter/Filter.java
index 6ea363132..46fd1f08f 100644
--- a/core/src/main/java/org/apache/servicecomb/core/filter/Filter.java
+++ b/core/src/main/java/org/apache/servicecomb/core/filter/Filter.java
@@ -16,8 +16,6 @@
  */
 package org.apache.servicecomb.core.filter;
 
-import java.util.Arrays;
-import java.util.List;
 import java.util.concurrent.CompletableFuture;
 
 import javax.annotation.Nonnull;
@@ -56,10 +54,27 @@ import org.apache.servicecomb.swagger.invocation.Response;
  * </pre>
  */
 public interface Filter {
-  default boolean isEnabled() {
+  int PRODUCER_SCHEDULE_FILTER_ORDER = -1;
+
+  int CONSUMER_LOAD_BALANCE_ORDER = -1;
+
+  default boolean isEnabledForInvocationType(InvocationType invocationType) {
+    return true;
+  }
+
+  default boolean isEnabledForTransport(String transport) {
+    return true;
+  }
+
+  default boolean isEnabledForMicroservice(String microservice) {
+    //TODO read configuration and check if filter enabled.
     return true;
   }
 
+  default int getOrder(InvocationType invocationType, String microservice) {
+    return 0;
+  }
+
   default boolean isInEventLoop() {
     return InvokerUtils.isInEventLoop();
   }
@@ -69,15 +84,6 @@ public interface Filter {
     throw new IllegalStateException("must provide filter name.");
   }
 
-  /**
-   *
-   * @return can be used for the specific invocation type
-   */
-  @Nonnull
-  default List<InvocationType> getInvocationTypes() {
-    return Arrays.asList(InvocationType.CONSUMER, InvocationType.PRODUCER);
-  }
-
   /**
    *
    * @param invocation invocation
diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/FilterChainsManager.java b/core/src/main/java/org/apache/servicecomb/core/filter/FilterChainsManager.java
index 962e37118..643fd4f03 100644
--- a/core/src/main/java/org/apache/servicecomb/core/filter/FilterChainsManager.java
+++ b/core/src/main/java/org/apache/servicecomb/core/filter/FilterChainsManager.java
@@ -20,30 +20,28 @@ import static org.apache.servicecomb.foundation.common.utils.StringBuilderUtils.
 import static org.apache.servicecomb.foundation.common.utils.StringBuilderUtils.deleteLast;
 
 import java.util.List;
-import java.util.Map.Entry;
 import java.util.stream.Collectors;
 
-import org.apache.servicecomb.core.filter.config.FilterChainsConfig;
 import org.apache.servicecomb.swagger.invocation.InvocationType;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
+import com.netflix.config.DynamicPropertyFactory;
+
 @Component
 public class FilterChainsManager {
-  private final FilterChainsConfig chainsConfig = new FilterChainsConfig();
-
-  private final InvocationFilterChains consumerChains = new InvocationFilterChains();
+  private final InvocationFilterChains consumerChains = new InvocationFilterChains(InvocationType.CONSUMER);
 
-  private final InvocationFilterChains producerChains = new InvocationFilterChains();
+  private final InvocationFilterChains producerChains = new InvocationFilterChains(InvocationType.PRODUCER);
 
   @Autowired
   public FilterChainsManager addFilters(List<Filter> filters) {
     for (Filter filter : filters) {
-      if (filter.getInvocationTypes().contains(InvocationType.CONSUMER)) {
+      if (filter.isEnabledForInvocationType(InvocationType.CONSUMER)) {
         consumerChains.addFilter(filter);
       }
 
-      if (filter.getInvocationTypes().contains(InvocationType.PRODUCER)) {
+      if (filter.isEnabledForInvocationType(InvocationType.PRODUCER)) {
         producerChains.addFilter(filter);
       }
     }
@@ -52,16 +50,12 @@ public class FilterChainsManager {
   }
 
   public FilterChainsManager init() {
-    chainsConfig.load();
-
-    consumerChains.resolve(chainsConfig.getResolver(), chainsConfig.getConsumer());
-    producerChains.resolve(chainsConfig.getResolver(), chainsConfig.getProducer());
-
     return this;
   }
 
   public boolean isEnabled() {
-    return chainsConfig.isEnabled();
+    return DynamicPropertyFactory.getInstance()
+        .getBooleanProperty("servicecomb.filter-chains.enabled", false).get();
   }
 
   public FilterNode findConsumerChain(String microserviceName) {
@@ -77,28 +71,16 @@ public class FilterChainsManager {
 
     appendLine(sb, "consumer: ");
     appendLine(sb, "  filters: %s", collectFilterNames(consumerChains));
-    collectChainsByInvocationType(sb, consumerChains);
 
     appendLine(sb, "producer: ");
     appendLine(sb, "  filters: %s", collectFilterNames(producerChains));
-    collectChainsByInvocationType(sb, producerChains);
 
     return deleteLast(sb, 1).toString();
   }
 
-  public List<String> collectFilterNames(InvocationFilterChains chains) {
+  private List<String> collectFilterNames(InvocationFilterChains chains) {
     return chains.getFilters().stream()
-        .filter(filter -> !(filter instanceof InternalFilter))
         .map(Filter::getName)
         .collect(Collectors.toList());
   }
-
-  private void collectChainsByInvocationType(StringBuilder sb, InvocationFilterChains chains) {
-    appendLine(sb, "  chains:");
-    appendLine(sb, "    framework: %s", chains.getResolvedFrameworkConfig());
-    appendLine(sb, "    default  : %s", chains.getResolvedDefaultConfig());
-    for (Entry<String, List<Object>> entry : chains.getResolvedMicroserviceConfig().entrySet()) {
-      appendLine(sb, "    %s: %s", entry.getKey(), entry.getValue());
-    }
-  }
 }
diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/FilterNode.java b/core/src/main/java/org/apache/servicecomb/core/filter/FilterNode.java
index bc6bda0a0..a1d605c0a 100644
--- a/core/src/main/java/org/apache/servicecomb/core/filter/FilterNode.java
+++ b/core/src/main/java/org/apache/servicecomb/core/filter/FilterNode.java
@@ -19,10 +19,8 @@ package org.apache.servicecomb.core.filter;
 import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.CompletableFuture;
-import java.util.stream.Collectors;
 
 import org.apache.servicecomb.core.Invocation;
-import org.apache.servicecomb.core.filter.impl.TransportFilters;
 import org.apache.servicecomb.foundation.common.utils.AsyncUtils;
 import org.apache.servicecomb.swagger.invocation.Response;
 
@@ -40,31 +38,17 @@ public class FilterNode {
 
   public static FilterNode buildChain(List<Filter> filters) {
     List<FilterNode> filterNodes = filters.stream()
-        .map(FilterNode::new)
-        .collect(Collectors.toList());
+        .map(FilterNode::new).toList();
 
     for (int idx = 0; idx < filterNodes.size() - 1; idx++) {
       FilterNode currentNode = filterNodes.get(idx);
       FilterNode nextNode = filterNodes.get(idx + 1);
       currentNode.setNextNode(nextNode);
-
-      if (currentNode.filter instanceof TransportFilters) {
-        mergeToChain((TransportFilters) currentNode.filter, nextNode);
-      }
     }
 
     return filterNodes.get(0);
   }
 
-  private static void mergeToChain(TransportFilters filter, FilterNode nextNode) {
-    for (FilterNode node : filter.getChainByTransport().values()) {
-      while (node.nextNode != null) {
-        node = node.nextNode;
-      }
-      node.nextNode = nextNode;
-    }
-  }
-
   private final Filter filter;
 
   private FilterNode nextNode;
@@ -78,7 +62,7 @@ public class FilterNode {
   }
 
   public CompletableFuture<Response> onFilter(Invocation invocation) {
-    if (!filter.isEnabled()) {
+    if (!filter.isEnabledForTransport(invocation.getTransportName())) {
       return nextNode.onFilter(invocation);
     }
 
diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/InternalFilter.java b/core/src/main/java/org/apache/servicecomb/core/filter/InternalFilter.java
deleted file mode 100644
index a79032def..000000000
--- a/core/src/main/java/org/apache/servicecomb/core/filter/InternalFilter.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * 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.core.filter;
-
-public interface InternalFilter extends Filter {
-}
diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/InvocationFilterChains.java b/core/src/main/java/org/apache/servicecomb/core/filter/InvocationFilterChains.java
index c71916647..c831b28d3 100644
--- a/core/src/main/java/org/apache/servicecomb/core/filter/InvocationFilterChains.java
+++ b/core/src/main/java/org/apache/servicecomb/core/filter/InvocationFilterChains.java
@@ -17,29 +17,24 @@
 package org.apache.servicecomb.core.filter;
 
 import java.util.Collection;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
-import java.util.function.Function;
 import java.util.stream.Collectors;
 
-import org.apache.servicecomb.core.filter.config.InvocationFilterChainsConfig;
-import org.apache.servicecomb.core.filter.config.TransportChainsConfig;
-import org.apache.servicecomb.core.filter.impl.TransportFilters;
+import org.apache.servicecomb.swagger.invocation.InvocationType;
 
 public class InvocationFilterChains {
   private final Map<String, Filter> filters = new HashMap<>();
 
-  private List<Object> resolvedFrameworkConfig;
-
-  private List<Object> resolvedDefaultConfig;
-
-  private final Map<String, List<Object>> resolvedMicroserviceConfig = new HashMap<>();
+  private final Map<String, FilterNode> microserviceChains = new HashMap<>();
 
-  private FilterNode defaultChain;
+  private final InvocationType invocationType;
 
-  private final Map<String, FilterNode> microserviceChains = new HashMap<>();
+  public InvocationFilterChains(InvocationType invocationType) {
+    this.invocationType = invocationType;
+  }
 
   public Collection<Filter> getFilters() {
     return filters.values();
@@ -49,65 +44,17 @@ public class InvocationFilterChains {
     filters.put(filter.getName(), filter);
   }
 
-  public List<Object> getResolvedFrameworkConfig() {
-    return resolvedFrameworkConfig;
-  }
-
-  public List<Object> getResolvedDefaultConfig() {
-    return resolvedDefaultConfig;
-  }
-
-  public Map<String, List<Object>> getResolvedMicroserviceConfig() {
-    return resolvedMicroserviceConfig;
-  }
-
-  public void resolve(Function<List<String>, List<Object>> resolver,
-      InvocationFilterChainsConfig config) {
-    resolvedFrameworkConfig = resolver.apply(config.getFrameworkChain());
-    resolvedDefaultConfig = resolver.apply(config.getDefaultChain());
-
-    defaultChain = createChain(resolvedDefaultConfig);
-    for (Entry<String, List<String>> entry : config.getMicroserviceChains().entrySet()) {
-      List<Object> resolveConfig = resolver.apply(entry.getValue());
-
-      resolvedMicroserviceConfig.put(entry.getKey(), resolveConfig);
-      microserviceChains.put(entry.getKey(), createChain(resolveConfig));
-    }
-  }
-
-  private <T> FilterNode createChain(List<T> chain) {
-    List<Filter> filters = createFilters(chain);
-    return FilterNode.buildChain(filters);
-  }
-
-  private <T> List<Filter> createFilters(List<T> chain) {
-    return chain.stream()
-        .map(this::findFilter)
-        .collect(Collectors.toList());
-  }
-
-  private Filter findFilter(Object filterConfig) {
-    if (filterConfig instanceof TransportChainsConfig) {
-      return createTransportFilter((TransportChainsConfig) filterConfig);
-    }
-
-    Filter filter = filters.get(filterConfig);
-    if (filter == null) {
-      throw new IllegalStateException("failed to find filter, name=" + filterConfig);
-    }
-    return filter;
-  }
-
-  private Filter createTransportFilter(TransportChainsConfig config) {
-    TransportFilters transportFilters = new TransportFilters();
-    for (Entry<String, List<String>> entry : config.getChainByTransport().entrySet()) {
-      List<Filter> filters = createFilters(entry.getValue());
-      transportFilters.getChainByTransport().put(entry.getKey(), FilterNode.buildChain(filters));
-    }
-    return transportFilters;
-  }
-
   public FilterNode findChain(String microserviceName) {
-    return microserviceChains.getOrDefault(microserviceName, defaultChain);
+    FilterNode filterNode = microserviceChains.get(microserviceName);
+    if (filterNode == null) {
+      List<Filter> serviceFilters = filters.entrySet().stream()
+          .filter(e -> e.getValue().isEnabledForMicroservice(microserviceName))
+          .map(e -> e.getValue())
+          .collect(Collectors.toList());
+      serviceFilters.sort(Comparator.comparingInt(a -> a.getOrder(invocationType, microserviceName)));
+      filterNode = FilterNode.buildChain(serviceFilters);
+      microserviceChains.put(microserviceName, filterNode);
+    }
+    return filterNode;
   }
 }
diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/ProducerFilter.java b/core/src/main/java/org/apache/servicecomb/core/filter/ProducerFilter.java
index 969e4252f..9d68af0d1 100644
--- a/core/src/main/java/org/apache/servicecomb/core/filter/ProducerFilter.java
+++ b/core/src/main/java/org/apache/servicecomb/core/filter/ProducerFilter.java
@@ -16,9 +16,6 @@
  */
 package org.apache.servicecomb.core.filter;
 
-import java.util.Collections;
-import java.util.List;
-
 import javax.annotation.Nonnull;
 
 import org.apache.servicecomb.swagger.invocation.InvocationType;
@@ -26,7 +23,7 @@ import org.apache.servicecomb.swagger.invocation.InvocationType;
 public interface ProducerFilter extends Filter {
   @Nonnull
   @Override
-  default List<InvocationType> getInvocationTypes() {
-    return Collections.singletonList(InvocationType.PRODUCER);
+  default boolean isEnabledForInvocationType(InvocationType invocationType) {
+    return invocationType == InvocationType.PRODUCER;
   }
 }
diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/config/AbstractFilterChainsConfig.java b/core/src/main/java/org/apache/servicecomb/core/filter/config/AbstractFilterChainsConfig.java
deleted file mode 100644
index 125724510..000000000
--- a/core/src/main/java/org/apache/servicecomb/core/filter/config/AbstractFilterChainsConfig.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.core.filter.config;
-
-import java.util.function.Consumer;
-
-import org.apache.commons.configuration.Configuration;
-
-import com.netflix.config.DynamicPropertyFactory;
-
-public class AbstractFilterChainsConfig {
-  public static final String ROOT = "servicecomb.filter-chains.";
-
-  protected final Configuration config = (Configuration) DynamicPropertyFactory.getBackingConfigurationSource();
-
-  protected void loadKeys(String root, Consumer<String> loadKey) {
-    config.getKeys(root).forEachRemaining(loadKey);
-  }
-}
diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/config/FilterChainsConfig.java b/core/src/main/java/org/apache/servicecomb/core/filter/config/FilterChainsConfig.java
deleted file mode 100644
index db364c2a9..000000000
--- a/core/src/main/java/org/apache/servicecomb/core/filter/config/FilterChainsConfig.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * 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.core.filter.config;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
-import org.apache.servicecomb.config.ConfigUtil;
-
-public class FilterChainsConfig extends AbstractFilterChainsConfig {
-  public static final String TRANSPORT_ROOT = ROOT + "transport";
-
-  public static final String DEFINITION_ROOT = ROOT + "definition";
-
-  // key is chain name
-  private final Map<String, TransportChainsConfig> transportChains = new HashMap<>();
-
-  private final Map<String, List<String>> definitions = new HashMap<>();
-
-  private InvocationFilterChainsConfig consumer;
-
-  private InvocationFilterChainsConfig producer;
-
-  private boolean enabled;
-
-  public void load() {
-    enabled = config.getBoolean(ROOT + "enabled", false);
-
-    loadKeys(TRANSPORT_ROOT, this::loadTransportChain);
-    loadKeys(DEFINITION_ROOT, this::loadDefinitionChain);
-
-    consumer = new InvocationFilterChainsConfig(ROOT + "consumer");
-    producer = new InvocationFilterChainsConfig(ROOT + "producer");
-  }
-
-  private void loadTransportChain(String qualifiedKey) {
-    String qualifiedName = qualifiedKey.substring(TRANSPORT_ROOT.length() + 1);
-    int dotIdx = qualifiedName.indexOf('.');
-    String chainName = qualifiedName.substring(0, dotIdx);
-    String transport = qualifiedName.substring(dotIdx + 1);
-
-    transportChains.computeIfAbsent(chainName, key -> new TransportChainsConfig())
-        .add(transport, ConfigUtil.getStringList(config, qualifiedKey));
-  }
-
-  private void loadDefinitionChain(String qualifiedKey) {
-    String chainName = qualifiedKey.substring(DEFINITION_ROOT.length() + 1);
-
-    definitions.put(chainName, ConfigUtil.getStringList(config, qualifiedKey));
-  }
-
-  public boolean isEnabled() {
-    return enabled;
-  }
-
-  public InvocationFilterChainsConfig getConsumer() {
-    return consumer;
-  }
-
-  public InvocationFilterChainsConfig getProducer() {
-    return producer;
-  }
-
-  public Function<List<String>, List<Object>> getResolver() {
-    return this::resolveChain;
-  }
-
-  private List<Object> resolveChain(List<String> chain) {
-    return chain.stream()
-        .flatMap(filterOrReference -> resolveFilterOrReference(filterOrReference).stream())
-        .collect(Collectors.toList());
-  }
-
-  private List<Object> resolveFilterOrReference(String filterOrReference) {
-    TransportChainsConfig transportChain = transportChains.get(filterOrReference);
-    if (transportChain != null) {
-      return Collections.singletonList(transportChain);
-    }
-
-    List<String> chain = definitions.get(filterOrReference);
-    if (chain == null) {
-      return Collections.singletonList(filterOrReference);
-    }
-
-    return resolveChain(chain);
-  }
-}
diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/config/InvocationFilterChainsConfig.java b/core/src/main/java/org/apache/servicecomb/core/filter/config/InvocationFilterChainsConfig.java
deleted file mode 100644
index 417aea5a7..000000000
--- a/core/src/main/java/org/apache/servicecomb/core/filter/config/InvocationFilterChainsConfig.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.core.filter.config;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.servicecomb.config.ConfigUtil;
-import org.springframework.util.CollectionUtils;
-
-public class InvocationFilterChainsConfig extends AbstractFilterChainsConfig {
-  private final String policiesRoot;
-
-  private final List<String> frameworkChain;
-
-  private final List<String> defaultChain;
-
-  private final Map<String, List<String>> microserviceChains = new HashMap<>();
-
-  public InvocationFilterChainsConfig(String root) {
-    frameworkChain = ConfigUtil.getStringList(config, root + ".framework");
-    defaultChain = loadDefaultChain(root);
-
-    policiesRoot = root + ".policies";
-    loadKeys(policiesRoot, this::loadPolicies);
-  }
-
-  private List<String> loadDefaultChain(String root) {
-    String defaultChainKey = root + ".default";
-    List<String> defaultChain = ConfigUtil.getStringList(config, defaultChainKey);
-    if (CollectionUtils.isEmpty(defaultChain) && config.getProperty(defaultChainKey) == null) {
-      defaultChain = frameworkChain;
-    }
-    return defaultChain;
-  }
-
-  private void loadPolicies(String qualifiedKey) {
-    String microserviceName = qualifiedKey.substring(policiesRoot.length() + 1);
-
-    microserviceChains.put(microserviceName, ConfigUtil.getStringList(config, qualifiedKey));
-  }
-
-  public List<String> getFrameworkChain() {
-    return frameworkChain;
-  }
-
-  public List<String> getDefaultChain() {
-    return defaultChain;
-  }
-
-  public Map<String, List<String>> getMicroserviceChains() {
-    return microserviceChains;
-  }
-}
diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/config/TransportChainsConfig.java b/core/src/main/java/org/apache/servicecomb/core/filter/config/TransportChainsConfig.java
deleted file mode 100644
index 7aef566e3..000000000
--- a/core/src/main/java/org/apache/servicecomb/core/filter/config/TransportChainsConfig.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.core.filter.config;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class TransportChainsConfig {
-  private final Map<String, List<String>> chainByTransport = new HashMap<>();
-
-  public Map<String, List<String>> getChainByTransport() {
-    return chainByTransport;
-  }
-
-  public TransportChainsConfig add(String transport, List<String> chain) {
-    chainByTransport.put(transport, chain);
-
-    return this;
-  }
-
-  @Override
-  public String toString() {
-    return chainByTransport.toString();
-  }
-}
diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/impl/EmptyFilter.java b/core/src/main/java/org/apache/servicecomb/core/filter/impl/EmptyFilter.java
index 95da754bc..2277b70f1 100644
--- a/core/src/main/java/org/apache/servicecomb/core/filter/impl/EmptyFilter.java
+++ b/core/src/main/java/org/apache/servicecomb/core/filter/impl/EmptyFilter.java
@@ -21,12 +21,12 @@ import java.util.concurrent.CompletableFuture;
 import javax.annotation.Nonnull;
 
 import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.core.filter.Filter;
 import org.apache.servicecomb.core.filter.FilterNode;
-import org.apache.servicecomb.core.filter.InternalFilter;
 import org.apache.servicecomb.swagger.invocation.Response;
 
 // just for test
-public class EmptyFilter implements InternalFilter {
+public class EmptyFilter implements Filter {
   @Nonnull
   @Override
   public String getName() {
diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/impl/ParameterValidatorFilter.java b/core/src/main/java/org/apache/servicecomb/core/filter/impl/ParameterValidatorFilter.java
index 4b2bcaba2..b7bde7395 100644
--- a/core/src/main/java/org/apache/servicecomb/core/filter/impl/ParameterValidatorFilter.java
+++ b/core/src/main/java/org/apache/servicecomb/core/filter/impl/ParameterValidatorFilter.java
@@ -29,10 +29,12 @@ import javax.validation.executable.ExecutableValidator;
 import javax.validation.groups.Default;
 
 import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.core.filter.Filter;
 import org.apache.servicecomb.core.filter.FilterNode;
 import org.apache.servicecomb.core.filter.ProducerFilter;
 import org.apache.servicecomb.foundation.common.utils.AsyncUtils;
 import org.apache.servicecomb.swagger.engine.SwaggerProducerOperation;
+import org.apache.servicecomb.swagger.invocation.InvocationType;
 import org.apache.servicecomb.swagger.invocation.Response;
 import org.hibernate.validator.HibernateValidator;
 import org.hibernate.validator.messageinterpolation.AbstractMessageInterpolator;
@@ -61,6 +63,11 @@ public class ParameterValidatorFilter implements ProducerFilter, InitializingBea
     return NAME;
   }
 
+  @Override
+  public int getOrder(InvocationType invocationType, String microservice) {
+    return Filter.PRODUCER_SCHEDULE_FILTER_ORDER + 1000;
+  }
+
   @Override
   public void afterPropertiesSet() {
     validator = createValidatorFactory()
diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/impl/ProducerOperationFilter.java b/core/src/main/java/org/apache/servicecomb/core/filter/impl/ProducerOperationFilter.java
index cb06081f5..83a4f5085 100644
--- a/core/src/main/java/org/apache/servicecomb/core/filter/impl/ProducerOperationFilter.java
+++ b/core/src/main/java/org/apache/servicecomb/core/filter/impl/ProducerOperationFilter.java
@@ -23,10 +23,12 @@ import javax.annotation.Nonnull;
 
 import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.core.exception.Exceptions;
+import org.apache.servicecomb.core.filter.Filter;
 import org.apache.servicecomb.core.filter.FilterNode;
 import org.apache.servicecomb.core.filter.ProducerFilter;
 import org.apache.servicecomb.foundation.common.utils.AsyncUtils;
 import org.apache.servicecomb.swagger.engine.SwaggerProducerOperation;
+import org.apache.servicecomb.swagger.invocation.InvocationType;
 import org.apache.servicecomb.swagger.invocation.Response;
 import org.apache.servicecomb.swagger.invocation.context.ContextUtils;
 import org.springframework.stereotype.Component;
@@ -41,6 +43,11 @@ public class ProducerOperationFilter implements ProducerFilter {
     return NAME;
   }
 
+  @Override
+  public int getOrder(InvocationType invocationType, String microservice) {
+    return Filter.PRODUCER_SCHEDULE_FILTER_ORDER + 1000;
+  }
+
   @Override
   public CompletableFuture<Response> onFilter(Invocation invocation, FilterNode nextNode) {
     invocation.onBusinessMethodStart();
diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/impl/ScheduleFilter.java b/core/src/main/java/org/apache/servicecomb/core/filter/impl/ScheduleFilter.java
index e144d81f0..898a47bf2 100644
--- a/core/src/main/java/org/apache/servicecomb/core/filter/impl/ScheduleFilter.java
+++ b/core/src/main/java/org/apache/servicecomb/core/filter/impl/ScheduleFilter.java
@@ -23,9 +23,11 @@ import javax.annotation.Nonnull;
 
 import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.core.exception.Exceptions;
+import org.apache.servicecomb.core.filter.Filter;
 import org.apache.servicecomb.core.filter.FilterNode;
 import org.apache.servicecomb.core.filter.ProducerFilter;
 import org.apache.servicecomb.core.invocation.InvocationStageTrace;
+import org.apache.servicecomb.swagger.invocation.InvocationType;
 import org.apache.servicecomb.swagger.invocation.Response;
 import org.springframework.stereotype.Component;
 
@@ -39,6 +41,11 @@ public class ScheduleFilter implements ProducerFilter {
     return NAME;
   }
 
+  @Override
+  public int getOrder(InvocationType invocationType, String microservice) {
+    return Filter.PRODUCER_SCHEDULE_FILTER_ORDER;
+  }
+
   @Override
   public CompletableFuture<Response> onFilter(Invocation invocation, FilterNode next) {
     invocation.getInvocationStageTrace().startSchedule();
diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/impl/SimpleLoadBalanceFilter.java b/core/src/main/java/org/apache/servicecomb/core/filter/impl/SimpleLoadBalanceFilter.java
index aa797caa0..fd753eef8 100644
--- a/core/src/main/java/org/apache/servicecomb/core/filter/impl/SimpleLoadBalanceFilter.java
+++ b/core/src/main/java/org/apache/servicecomb/core/filter/impl/SimpleLoadBalanceFilter.java
@@ -29,6 +29,7 @@ import org.apache.servicecomb.core.Endpoint;
 import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.core.exception.Exceptions;
 import org.apache.servicecomb.core.filter.ConsumerFilter;
+import org.apache.servicecomb.core.filter.Filter;
 import org.apache.servicecomb.core.filter.FilterNode;
 import org.apache.servicecomb.core.governance.RetryContext;
 import org.apache.servicecomb.core.handler.impl.SimpleLoadBalanceHandler;
@@ -38,6 +39,7 @@ import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx;
 import org.apache.servicecomb.registry.discovery.DiscoveryContext;
 import org.apache.servicecomb.registry.discovery.DiscoveryFilter;
 import org.apache.servicecomb.registry.discovery.DiscoveryTree;
+import org.apache.servicecomb.swagger.invocation.InvocationType;
 import org.apache.servicecomb.swagger.invocation.Response;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -157,6 +159,11 @@ public class SimpleLoadBalanceFilter implements ConsumerFilter {
     return NAME;
   }
 
+  @Override
+  public int getOrder(InvocationType invocationType, String microservice) {
+    return Filter.CONSUMER_LOAD_BALANCE_ORDER;
+  }
+
   @Override
   public CompletableFuture<Response> onFilter(Invocation invocation, FilterNode nextNode) {
     if (invocation.getEndpoint() != null) {
diff --git a/core/src/main/java/org/apache/servicecomb/core/filter/impl/TransportFilters.java b/core/src/main/java/org/apache/servicecomb/core/filter/impl/TransportFilters.java
deleted file mode 100644
index 0b9f145d9..000000000
--- a/core/src/main/java/org/apache/servicecomb/core/filter/impl/TransportFilters.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * 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.core.filter.impl;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.CompletableFuture;
-
-import javax.annotation.Nonnull;
-
-import org.apache.servicecomb.core.Invocation;
-import org.apache.servicecomb.core.filter.FilterNode;
-import org.apache.servicecomb.core.filter.InternalFilter;
-import org.apache.servicecomb.swagger.invocation.Response;
-import org.springframework.stereotype.Component;
-
-/**
- * Internal use only
- */
-@Component
-public class TransportFilters implements InternalFilter {
-  public static final String NAME = "transport-filters";
-
-  private final Map<String, FilterNode> chainByTransport = new HashMap<>();
-
-  @Nonnull
-  @Override
-  public String getName() {
-    return NAME;
-  }
-
-  public Map<String, FilterNode> getChainByTransport() {
-    return chainByTransport;
-  }
-
-  @Override
-  public CompletableFuture<Response> onFilter(Invocation invocation, FilterNode nextNode) {
-    FilterNode filterNode = chainByTransport.get(invocation.getTransport().getName());
-    if (filterNode == null) {
-      return nextNode.onFilter(invocation);
-    }
-
-    return filterNode.onFilter(invocation);
-  }
-}
diff --git a/core/src/test/java/org/apache/servicecomb/core/filter/FilterChainTest.java b/core/src/test/java/org/apache/servicecomb/core/filter/FilterChainTest.java
index aece3799a..0903cc03c 100644
--- a/core/src/test/java/org/apache/servicecomb/core/filter/FilterChainTest.java
+++ b/core/src/test/java/org/apache/servicecomb/core/filter/FilterChainTest.java
@@ -17,8 +17,6 @@
 
 package org.apache.servicecomb.core.filter;
 
-import static org.apache.servicecomb.core.Const.HIGHWAY;
-import static org.apache.servicecomb.core.Const.RESTFUL;
 import static org.apache.servicecomb.core.filter.FilterNode.buildChain;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.assertj.core.api.Assertions.catchThrowable;
@@ -34,11 +32,9 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
 import org.apache.servicecomb.core.Invocation;
-import org.apache.servicecomb.core.Transport;
 import org.apache.servicecomb.core.definition.OperationConfig;
 import org.apache.servicecomb.core.definition.OperationMeta;
 import org.apache.servicecomb.core.filter.impl.ScheduleFilter;
-import org.apache.servicecomb.core.filter.impl.TransportFilters;
 import org.apache.servicecomb.swagger.invocation.Response;
 import org.junit.BeforeClass;
 import org.junit.Test;
@@ -148,72 +144,9 @@ public class FilterChainTest {
     CompletableFuture<Response> future = buildChain(retryFilter, recordThreadFilter, exceptionFilter)
         .onFilter(invocation);
     assertThat(future)
-            .failsWithin(Duration.ofSeconds(1))
-            .withThrowableOfType(ExecutionException.class)
-            .withCauseExactlyInstanceOf(IOException.class)
-            .withMessage("java.io.IOException: net error");
-  }
-
-  @Test
-  public void should_build_chain_with_TransportFilters(@Mocked Transport transport)
-      throws ExecutionException, InterruptedException {
-    mockInvocation();
-    new Expectations() {
-      {
-        invocation.getTransport();
-        result = transport;
-      }
-    };
-    TransportFilters transportFilters = new TransportFilters();
-    transportFilters.getChainByTransport().put(RESTFUL, buildChain(recordThreadFilter));
-    transportFilters.getChainByTransport().put(HIGHWAY, buildChain(recordThreadFilter, scheduler, recordThreadFilter));
-
-    FilterNode chain = buildChain(transportFilters, recordThreadFilter);
-
-    checkRestChain(transport, chain);
-    checkHighwayChain(transport, chain);
-    checkUnknownTransportChain(transport, chain);
-  }
-
-  private void checkUnknownTransportChain(Transport transport, FilterNode chain)
-      throws ExecutionException, InterruptedException {
-    msg.clear();
-    new Expectations() {
-      {
-        transport.getName();
-        result = "abc";
-      }
-    };
-    chain.onFilter(invocation)
-        .get();
-    assertThat(msg).containsExactly("main");
-  }
-
-  private void checkRestChain(Transport transport, FilterNode chain)
-      throws InterruptedException, ExecutionException {
-    msg.clear();
-    new Expectations() {
-      {
-        transport.getName();
-        result = RESTFUL;
-      }
-    };
-    chain.onFilter(invocation)
-        .get();
-    assertThat(msg).containsExactly("main", "main");
-  }
-
-  private void checkHighwayChain(Transport transport, FilterNode chain)
-      throws InterruptedException, ExecutionException {
-    msg.clear();
-    new Expectations() {
-      {
-        transport.getName();
-        result = HIGHWAY;
-      }
-    };
-    chain.onFilter(invocation)
-        .get();
-    assertThat(msg).containsExactly("main", THREAD_NAME, THREAD_NAME);
+        .failsWithin(Duration.ofSeconds(1))
+        .withThrowableOfType(ExecutionException.class)
+        .withCauseExactlyInstanceOf(IOException.class)
+        .withMessage("java.io.IOException: net error");
   }
 }
diff --git a/core/src/test/java/org/apache/servicecomb/core/filter/SimpleRetryFilter.java b/core/src/test/java/org/apache/servicecomb/core/filter/SimpleRetryFilter.java
index ce54faf12..059277847 100644
--- a/core/src/test/java/org/apache/servicecomb/core/filter/SimpleRetryFilter.java
+++ b/core/src/test/java/org/apache/servicecomb/core/filter/SimpleRetryFilter.java
@@ -23,6 +23,7 @@ import javax.annotation.Nonnull;
 
 import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.core.exception.Exceptions;
+import org.apache.servicecomb.swagger.invocation.InvocationType;
 import org.apache.servicecomb.swagger.invocation.Response;
 
 public class SimpleRetryFilter implements ConsumerFilter {
@@ -34,6 +35,11 @@ public class SimpleRetryFilter implements ConsumerFilter {
     return "simple-retry";
   }
 
+  @Override
+  public int getOrder(InvocationType invocationType, String microservice) {
+    return Filter.CONSUMER_LOAD_BALANCE_ORDER - 900;
+  }
+
   public SimpleRetryFilter setMaxRetry(int maxRetry) {
     this.maxRetry = maxRetry;
     return this;
diff --git a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeAddHeaderFilter.java b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeAddHeaderFilter.java
index f6bb52140..bf196a6d9 100644
--- a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeAddHeaderFilter.java
+++ b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeAddHeaderFilter.java
@@ -22,7 +22,9 @@ import javax.annotation.Nonnull;
 
 import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.core.filter.ConsumerFilter;
+import org.apache.servicecomb.core.filter.Filter;
 import org.apache.servicecomb.core.filter.FilterNode;
+import org.apache.servicecomb.swagger.invocation.InvocationType;
 import org.apache.servicecomb.swagger.invocation.Response;
 import org.apache.servicecomb.transport.rest.client.RestClientTransportContext;
 import org.springframework.stereotype.Component;
@@ -40,10 +42,15 @@ public class EdgeAddHeaderFilter implements ConsumerFilter {
   }
 
   @Override
-  public boolean isEnabled() {
+  public boolean isEnabledForTransport(String transport) {
     return filter.enabled();
   }
 
+  @Override
+  public int getOrder(InvocationType invocationType, String microservice) {
+    return Filter.CONSUMER_LOAD_BALANCE_ORDER - 1000;
+  }
+
   @Override
   public CompletableFuture<Response> onFilter(Invocation invocation, FilterNode nextNode) {
     RestClientTransportContext transportContext = invocation.getTransportContext();
diff --git a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeServerCodecFilter.java b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeServerCodecFilter.java
index 71968af9c..ee6a1753b 100644
--- a/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeServerCodecFilter.java
+++ b/edge/edge-core/src/main/java/org/apache/servicecomb/edge/core/EdgeServerCodecFilter.java
@@ -16,14 +16,14 @@
  */
 package org.apache.servicecomb.edge.core;
 
-import java.util.Collections;
-import java.util.List;
 import java.util.concurrent.CompletableFuture;
 
 import javax.annotation.Nonnull;
 
 import org.apache.servicecomb.common.rest.filter.inner.RestServerCodecFilter;
+import org.apache.servicecomb.core.Const;
 import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.core.filter.Filter;
 import org.apache.servicecomb.core.filter.FilterNode;
 import org.apache.servicecomb.swagger.invocation.InvocationType;
 import org.apache.servicecomb.swagger.invocation.Response;
@@ -42,8 +42,18 @@ public class EdgeServerCodecFilter extends RestServerCodecFilter {
 
   @Nonnull
   @Override
-  public List<InvocationType> getInvocationTypes() {
-    return Collections.singletonList(InvocationType.CONSUMER);
+  public boolean isEnabledForInvocationType(InvocationType invocationType) {
+    return invocationType == InvocationType.CONSUMER;
+  }
+
+  @Override
+  public boolean isEnabledForTransport(String transport) {
+    return Const.RESTFUL.equals(transport);
+  }
+
+  @Override
+  public int getOrder(InvocationType invocationType, String microservice) {
+    return Filter.CONSUMER_LOAD_BALANCE_ORDER - 1000;
   }
 
   @Override
diff --git a/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayClientFilter.java b/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayClientFilter.java
index 77d17a449..a6cf2d85b 100644
--- a/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayClientFilter.java
+++ b/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayClientFilter.java
@@ -22,12 +22,15 @@ import javax.annotation.Nonnull;
 
 import org.apache.servicecomb.codec.protobuf.definition.OperationProtobuf;
 import org.apache.servicecomb.codec.protobuf.definition.ProtobufManager;
+import org.apache.servicecomb.core.Const;
 import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.core.exception.Exceptions;
 import org.apache.servicecomb.core.filter.ConsumerFilter;
+import org.apache.servicecomb.core.filter.Filter;
 import org.apache.servicecomb.core.filter.FilterNode;
 import org.apache.servicecomb.foundation.common.utils.AsyncUtils;
 import org.apache.servicecomb.foundation.vertx.client.tcp.TcpData;
+import org.apache.servicecomb.swagger.invocation.InvocationType;
 import org.apache.servicecomb.swagger.invocation.Response;
 import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
 import org.slf4j.Logger;
@@ -46,6 +49,16 @@ public class HighwayClientFilter implements ConsumerFilter {
     return NAME;
   }
 
+  @Override
+  public boolean isEnabledForTransport(String transport) {
+    return Const.HIGHWAY.equals(transport);
+  }
+
+  @Override
+  public int getOrder(InvocationType invocationType, String microservice) {
+    return Filter.CONSUMER_LOAD_BALANCE_ORDER + 1000;
+  }
+
   @Override
   public CompletableFuture<Response> onFilter(Invocation invocation, FilterNode nextNode) {
     LOGGER.debug("Sending request by highway, operation={}, endpoint={}.",
diff --git a/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayServerCodecFilter.java b/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayServerCodecFilter.java
index 01870a3f3..6905fa84e 100644
--- a/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayServerCodecFilter.java
+++ b/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayServerCodecFilter.java
@@ -24,10 +24,13 @@ import javax.annotation.Nonnull;
 
 import org.apache.servicecomb.codec.protobuf.definition.OperationProtobuf;
 import org.apache.servicecomb.codec.protobuf.definition.ResponseRootSerializer;
+import org.apache.servicecomb.core.Const;
 import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.core.filter.Filter;
 import org.apache.servicecomb.core.filter.FilterNode;
 import org.apache.servicecomb.core.filter.ProducerFilter;
 import org.apache.servicecomb.foundation.common.utils.AsyncUtils;
+import org.apache.servicecomb.swagger.invocation.InvocationType;
 import org.apache.servicecomb.swagger.invocation.Response;
 import org.apache.servicecomb.transport.highway.message.ResponseHeader;
 import org.springframework.stereotype.Component;
@@ -44,6 +47,16 @@ public class HighwayServerCodecFilter implements ProducerFilter {
     return NAME;
   }
 
+  @Override
+  public int getOrder(InvocationType invocationType, String microservice) {
+    return Filter.PRODUCER_SCHEDULE_FILTER_ORDER - 1000;
+  }
+
+  @Override
+  public boolean isEnabledForTransport(String transport) {
+    return Const.HIGHWAY.equals(transport);
+  }
+
   @Override
   public CompletableFuture<Response> onFilter(Invocation invocation, FilterNode nextNode) {
     return CompletableFuture.completedFuture(invocation)
diff --git a/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/RestClientCodecFilter.java b/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/RestClientCodecFilter.java
index 6a530f256..0ecd7569b 100644
--- a/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/RestClientCodecFilter.java
+++ b/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/RestClientCodecFilter.java
@@ -20,9 +20,12 @@ import java.util.concurrent.CompletableFuture;
 
 import javax.annotation.Nonnull;
 
+import org.apache.servicecomb.core.Const;
 import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.core.filter.ConsumerFilter;
+import org.apache.servicecomb.core.filter.Filter;
 import org.apache.servicecomb.core.filter.FilterNode;
+import org.apache.servicecomb.swagger.invocation.InvocationType;
 import org.apache.servicecomb.swagger.invocation.Response;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
@@ -45,6 +48,16 @@ public class RestClientCodecFilter implements ConsumerFilter {
     return NAME;
   }
 
+  @Override
+  public boolean isEnabledForTransport(String transport) {
+    return Const.RESTFUL.equals(transport);
+  }
+
+  @Override
+  public int getOrder(InvocationType invocationType, String microservice) {
+    return Filter.CONSUMER_LOAD_BALANCE_ORDER + 1000;
+  }
+
   @Autowired
   public RestClientCodecFilter setTransportContextFactory(RestClientTransportContextFactory transportContextFactory) {
     this.transportContextFactory = transportContextFactory;
diff --git a/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/RestClientSenderFilter.java b/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/RestClientSenderFilter.java
index 84e8baaa1..7b6eb9e1f 100644
--- a/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/RestClientSenderFilter.java
+++ b/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/RestClientSenderFilter.java
@@ -20,9 +20,12 @@ import java.util.concurrent.CompletableFuture;
 
 import javax.annotation.Nonnull;
 
+import org.apache.servicecomb.core.Const;
 import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.core.filter.ConsumerFilter;
+import org.apache.servicecomb.core.filter.Filter;
 import org.apache.servicecomb.core.filter.FilterNode;
+import org.apache.servicecomb.swagger.invocation.InvocationType;
 import org.apache.servicecomb.swagger.invocation.Response;
 import org.springframework.stereotype.Component;
 
@@ -36,6 +39,16 @@ public class RestClientSenderFilter implements ConsumerFilter {
     return NAME;
   }
 
+  @Override
+  public boolean isEnabledForTransport(String transport) {
+    return Const.RESTFUL.equals(transport);
+  }
+
+  @Override
+  public int getOrder(InvocationType invocationType, String microservice) {
+    return Filter.CONSUMER_LOAD_BALANCE_ORDER + 1010;
+  }
+
   @Override
   public CompletableFuture<Response> onFilter(Invocation invocation, FilterNode nextNode) {
     invocation.onStartSendRequest();