You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by wu...@apache.org on 2021/03/26 06:59:15 UTC

[servicecomb-java-chassis] branch master updated (00bc846 -> 0b46b0f)

This is an automated email from the ASF dual-hosted git repository.

wujimin pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git.


    from 00bc846  [SCB-2242] fix org.apache.servicecomb.core.definition.MicroserviceVersionsMeta#MicroserviceVersionsMeta bug of OOM (#2320)
     new c018bed  [SCB-2216]breakpoints testing for fast timeout of execution
     new 0b46b0f  [SCB-2216]fix review comments

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../common/rest/AbstractRestInvocation.java        |  20 ++-
 .../java/org/apache/servicecomb/core/Const.java    |   6 +
 .../org/apache/servicecomb/core/Invocation.java    |  45 ++++--
 .../core/definition/OperationConfig.java           |  21 +++
 ...ent.java => InvocationBusinessFinishEvent.java} |   5 +-
 ...vent.java => InvocationHandlersStartEvent.java} |   7 +-
 ...t.java => InvocationStartSendRequestEvent.java} |   7 +-
 ...Event.java => InvocationTimeoutCheckEvent.java} |   7 +-
 .../servicecomb/core/exception/ExceptionCodes.java |   1 +
 .../core/filter/impl/ScheduleFilter.java           |   2 +-
 .../invocation/InvocationTimeoutBootListener.java  | 159 +++++++++++++++++++++
 .../core/provider/consumer/InvokerUtils.java       |   7 +-
 .../core/definition/OperationConfigTest.java       |   9 ++
 .../src/main/resources/microservice.yaml           |   3 +
 .../src/main/resources/microservice.yaml           |   5 +-
 .../servicecomb/demo/CommonSchemaInterface.java    |  23 +--
 .../java/org/apache/servicecomb/demo/TestMgr.java  |   4 +
 .../client/TestSpringMVCCommonSchemaInterface.java |  76 ++++++++++
 .../demo/springmvc/client/TestUploadSchema.java    |   2 +
 .../src/main/resources/microservice.yaml           |   1 -
 .../springmvc/server/ProducerTestsAfterBootup.java |   4 +-
 .../server/SpringMVCCommonSchemaInterface.java     |  60 ++++++++
 .../demo/springmvc/server/UploadSchema.java        |   4 +
 .../src/main/resources/microservice.yaml           |   6 +
 .../foundation/common/event/SimpleSubscriber.java  |   2 +-
 .../bizkeeper/FallbackPolicyManager.java           |   6 +-
 .../bizkeeper/TestFallbackPolicyManager.java       |   8 +-
 .../transport/highway/HighwayClient.java           |   2 +-
 .../transport/highway/HighwayClientFilter.java     |   2 +-
 .../transport/highway/HighwayCodec.java            |   1 -
 .../transport/highway/HighwayServerConnection.java |   2 +
 .../transport/highway/HighwayServerInvoke.java     |   7 +-
 .../transport/highway/TestHighwayClient.java       |   4 -
 .../transport/highway/TestHighwayCodec.java        |   6 +-
 .../transport/rest/client/RestClientSender.java    |   2 +-
 .../rest/client/http/RestClientInvocation.java     |   6 +-
 .../rest/client/http/TestRestClientInvocation.java |   3 -
 37 files changed, 455 insertions(+), 80 deletions(-)
 copy core/src/main/java/org/apache/servicecomb/core/event/{InvocationStartEvent.java => InvocationBusinessFinishEvent.java} (86%)
 copy core/src/main/java/org/apache/servicecomb/core/event/{InvocationStartEvent.java => InvocationHandlersStartEvent.java} (87%)
 copy core/src/main/java/org/apache/servicecomb/core/event/{InvocationStartEvent.java => InvocationStartSendRequestEvent.java} (86%)
 copy core/src/main/java/org/apache/servicecomb/core/event/{InvocationStartEvent.java => InvocationTimeoutCheckEvent.java} (87%)
 create mode 100644 core/src/main/java/org/apache/servicecomb/core/invocation/InvocationTimeoutBootListener.java
 copy integration-tests/it-producer/src/main/java/org/apache/servicecomb/it/schema/TransportContextSchema.java => demo/demo-schema/src/main/java/org/apache/servicecomb/demo/CommonSchemaInterface.java (59%)
 create mode 100644 demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestSpringMVCCommonSchemaInterface.java
 create mode 100644 demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SpringMVCCommonSchemaInterface.java

[servicecomb-java-chassis] 01/02: [SCB-2216]breakpoints testing for fast timeout of execution

Posted by wu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

wujimin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git

commit c018bed9051cd8d7c27c07ec1824bc554d409eb0
Author: liubao68 <bi...@qq.com>
AuthorDate: Sat Mar 20 15:07:28 2021 +0800

    [SCB-2216]breakpoints testing for fast timeout of execution
---
 .../common/rest/AbstractRestInvocation.java        |  20 ++-
 .../java/org/apache/servicecomb/core/Const.java    |   6 +
 .../org/apache/servicecomb/core/Invocation.java    |  45 ++++--
 .../core/definition/OperationConfig.java           |  21 +++
 .../InvocationBusinessFinishEvent.java}            |  14 +-
 .../InvocationHandlersStartEvent.java}             |  16 +--
 .../InvocationStartSendRequestEvent.java}          |  16 +--
 .../InvocationTimeoutCheckEvent.java}              |  16 +--
 .../servicecomb/core/exception/ExceptionCodes.java |   1 +
 .../core/filter/impl/ScheduleFilter.java           |   2 +-
 .../invocation/InvocationTimeoutBootListener.java  | 159 +++++++++++++++++++++
 .../core/provider/consumer/InvokerUtils.java       |   7 +-
 .../core/definition/OperationConfigTest.java       |   9 ++
 .../src/main/resources/microservice.yaml           |   3 +
 .../src/main/resources/microservice.yaml           |   5 +-
 .../servicecomb/demo/CommonSchemaInterface.java    |  36 +++++
 .../java/org/apache/servicecomb/demo/TestMgr.java  |   4 +
 .../client/TestSpringMVCCommonSchemaInterface.java |  76 ++++++++++
 .../demo/springmvc/client/TestUploadSchema.java    |   2 +
 .../src/main/resources/microservice.yaml           |   1 -
 .../springmvc/server/ProducerTestsAfterBootup.java |   4 +-
 .../server/SpringMVCCommonSchemaInterface.java     |  60 ++++++++
 .../demo/springmvc/server/UploadSchema.java        |   4 +
 .../src/main/resources/microservice.yaml           |   6 +
 .../foundation/common/event/SimpleSubscriber.java  |   2 +-
 .../bizkeeper/FallbackPolicyManager.java           |   6 +-
 .../bizkeeper/TestFallbackPolicyManager.java       |   8 +-
 .../transport/highway/HighwayClient.java           |   2 +-
 .../transport/highway/HighwayCodec.java            |   1 -
 .../transport/highway/HighwayServerConnection.java |   2 +
 .../transport/highway/HighwayServerInvoke.java     |   7 +-
 .../transport/highway/TestHighwayClient.java       |   4 -
 .../transport/highway/TestHighwayCodec.java        |   6 +-
 .../rest/client/RestClientSenderFilter.java        |   2 +
 .../rest/client/http/RestClientInvocation.java     |   6 +-
 .../rest/client/http/TestRestClientInvocation.java |   3 -
 36 files changed, 493 insertions(+), 89 deletions(-)

diff --git a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/AbstractRestInvocation.java b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/AbstractRestInvocation.java
index 2304022..5041d6c 100644
--- a/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/AbstractRestInvocation.java
+++ b/common/common-rest/src/main/java/org/apache/servicecomb/common/rest/AbstractRestInvocation.java
@@ -126,10 +126,6 @@ public abstract class AbstractRestInvocation {
       return;
     }
 
-    invocation.onStart(requestEx, start);
-    invocation.getInvocationStageTrace().startSchedule();
-    OperationMeta operationMeta = restOperationMeta.getOperationMeta();
-
     try {
       this.setContext();
     } catch (Exception e) {
@@ -137,6 +133,10 @@ public abstract class AbstractRestInvocation {
       sendFailResponse(e);
       return;
     }
+    
+    invocation.onStart(requestEx, start);
+    invocation.getInvocationStageTrace().startSchedule();
+    OperationMeta operationMeta = restOperationMeta.getOperationMeta();
 
     Holder<Boolean> qpsFlowControlReject = checkQpsFlowControl(operationMeta);
     if (qpsFlowControlReject.value) {
@@ -160,8 +160,11 @@ public abstract class AbstractRestInvocation {
             }
 
             runOnExecutor();
+          } catch (InvocationException e) {
+            LOGGER.error("Invocation failed, cause={}", e.getMessage());
+            sendFailResponse(e);
           } catch (Throwable e) {
-            LOGGER.error("rest server onRequest error", e);
+            LOGGER.error("Processing rest server request error", e);
             sendFailResponse(e);
           }
         }
@@ -217,8 +220,11 @@ public abstract class AbstractRestInvocation {
       }
 
       doInvoke();
+    } catch (InvocationException e) {
+      LOGGER.error("Invocation failed, cause={}", e.getMessage());
+      sendFailResponse(e);
     } catch (Throwable e) {
-      LOGGER.error("unknown rest exception.", e);
+      LOGGER.error("Processing rest server request error", e);
       sendFailResponse(e);
     }
   }
@@ -241,7 +247,7 @@ public abstract class AbstractRestInvocation {
   }
 
   protected void doInvoke() throws Throwable {
-    invocation.getInvocationStageTrace().startHandlersRequest();
+    invocation.onStartHandlersRequest();
     invocation.next(resp -> sendResponseQuietly(resp));
   }
 
diff --git a/core/src/main/java/org/apache/servicecomb/core/Const.java b/core/src/main/java/org/apache/servicecomb/core/Const.java
index fc90ac0..e4940aa 100644
--- a/core/src/main/java/org/apache/servicecomb/core/Const.java
+++ b/core/src/main/java/org/apache/servicecomb/core/Const.java
@@ -25,6 +25,12 @@ public final class Const {
 
   public static final String CSE_CONTEXT = "x-cse-context";
 
+  public static final String CONTEXT_TIME_ELAPSED = "x-scb-time";
+
+  public static final String CONTEXT_TIMED_OUT = "x-scb-timed-out";
+
+  public static final String CONTEXT_TIME_CURRENT = "x-scb-time-current";
+
   public static final String RESTFUL = "rest";
 
   public static final String HIGHWAY = "highway";
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 88f42bc..30fe533 100644
--- a/core/src/main/java/org/apache/servicecomb/core/Invocation.java
+++ b/core/src/main/java/org/apache/servicecomb/core/Invocation.java
@@ -32,13 +32,17 @@ import org.apache.servicecomb.core.definition.InvocationRuntimeType;
 import org.apache.servicecomb.core.definition.MicroserviceMeta;
 import org.apache.servicecomb.core.definition.OperationMeta;
 import org.apache.servicecomb.core.definition.SchemaMeta;
+import org.apache.servicecomb.core.event.InvocationBusinessFinishEvent;
 import org.apache.servicecomb.core.event.InvocationBusinessMethodFinishEvent;
 import org.apache.servicecomb.core.event.InvocationBusinessMethodStartEvent;
 import org.apache.servicecomb.core.event.InvocationEncodeResponseStartEvent;
 import org.apache.servicecomb.core.event.InvocationFinishEvent;
+import org.apache.servicecomb.core.event.InvocationHandlersStartEvent;
 import org.apache.servicecomb.core.event.InvocationRunInExecutorFinishEvent;
 import org.apache.servicecomb.core.event.InvocationRunInExecutorStartEvent;
 import org.apache.servicecomb.core.event.InvocationStartEvent;
+import org.apache.servicecomb.core.event.InvocationStartSendRequestEvent;
+import org.apache.servicecomb.core.event.InvocationTimeoutCheckEvent;
 import org.apache.servicecomb.core.invocation.InvocationStageTrace;
 import org.apache.servicecomb.core.provider.consumer.InvokerUtils;
 import org.apache.servicecomb.core.provider.consumer.ReferenceConfig;
@@ -52,6 +56,7 @@ import org.apache.servicecomb.swagger.invocation.AsyncResponse;
 import org.apache.servicecomb.swagger.invocation.InvocationType;
 import org.apache.servicecomb.swagger.invocation.Response;
 import org.apache.servicecomb.swagger.invocation.SwaggerInvocation;
+import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
 
 import com.fasterxml.jackson.databind.JavaType;
 
@@ -136,16 +141,6 @@ public class Invocation extends SwaggerInvocation {
     return getContext(traceIdName);
   }
 
-  @Deprecated
-  public long getStartTime() {
-    return invocationStageTrace.getStart();
-  }
-
-  @Deprecated
-  public long getStartExecutionTime() {
-    return invocationStageTrace.getStartExecution();
-  }
-
   public Invocation() {
     // An empty invocation, used to mock or some other scenario do not need operation information.
     traceIdLogger = new TraceIdLogger(this);
@@ -276,10 +271,6 @@ public class Invocation extends SwaggerInvocation {
     return producerArguments = args;
   }
 
-  public void clearProducerArguments() {
-    producerArguments = null;
-  }
-
   public Endpoint getEndpoint() {
     return endpoint;
   }
@@ -411,6 +402,16 @@ public class Invocation extends SwaggerInvocation {
     EventManager.post(new InvocationRunInExecutorFinishEvent(this));
   }
 
+  public void onStartHandlersRequest() {
+    invocationStageTrace.startHandlersRequest();
+    EventManager.post(new InvocationHandlersStartEvent(this));
+  }
+
+  public void onStartSendRequest() {
+    invocationStageTrace.startSend();
+    EventManager.post(new InvocationStartSendRequestEvent(this));
+  }
+
   @Override
   public void onBusinessMethodStart() {
     invocationStageTrace.startBusinessMethod();
@@ -429,6 +430,7 @@ public class Invocation extends SwaggerInvocation {
   @Override
   public void onBusinessFinish() {
     invocationStageTrace.finishBusiness();
+    EventManager.post(new InvocationBusinessFinishEvent(this));
   }
 
   public void onFinish(Response response) {
@@ -482,4 +484,19 @@ public class Invocation extends SwaggerInvocation {
 
     return future;
   }
+
+  /**
+   * Check if invocation is timeout.
+   *
+   * NOTICE: this method only trigger event to ask the target checker to do the real check. So this method
+   * will only take effect when timeout checker is enabled.
+   *
+   * e.g. InvocationTimeoutBootListener.ENABLE_TIMEOUT_CHECK is enabled.
+   *
+   * @throws InvocationException if timeout, throw an exception. Will not throw exception twice if this method called
+   *  after timeout.
+   */
+  public void ensureInvocationNotTimeout() throws InvocationException {
+    EventManager.post(new InvocationTimeoutCheckEvent(this));
+  }
 }
diff --git a/core/src/main/java/org/apache/servicecomb/core/definition/OperationConfig.java b/core/src/main/java/org/apache/servicecomb/core/definition/OperationConfig.java
index ccbbb68..c210efd 100644
--- a/core/src/main/java/org/apache/servicecomb/core/definition/OperationConfig.java
+++ b/core/src/main/java/org/apache/servicecomb/core/definition/OperationConfig.java
@@ -65,6 +65,14 @@ public class OperationConfig {
   private long msRequestTimeout;
 
   /**
+   * Invocation timeout.
+   */
+  @InjectProperty(keys = {"invocation.${op-any-priority}.timeout", "invocation.timeout"}, defaultValue = "-1")
+  private long msInvocationTimeout;
+
+  private long nanoInvocationTimeout;
+
+  /**
    * whether to remove certain headers from the 3rd party invocations
    */
   @InjectProperty(keys = {"request.clientRequestHeaderFilterEnabled${consumer-op-priority}"}, defaultValue = "true")
@@ -178,6 +186,19 @@ public class OperationConfig {
     return nanoRestRequestWaitInPoolTimeout;
   }
 
+  public long getMsInvocationTimeout() {
+    return msInvocationTimeout;
+  }
+
+  public void setMsInvocationTimeout(long msInvocationTimeout) {
+    this.msInvocationTimeout = msInvocationTimeout;
+    this.nanoInvocationTimeout = TimeUnit.MILLISECONDS.toNanos(msInvocationTimeout);
+  }
+
+  public long getNanoInvocationTimeout() {
+    return this.nanoInvocationTimeout;
+  }
+
   public boolean isClientRequestHeaderFilterEnabled() {
     return clientRequestHeaderFilterEnabled;
   }
diff --git a/core/src/main/java/org/apache/servicecomb/core/exception/ExceptionCodes.java b/core/src/main/java/org/apache/servicecomb/core/event/InvocationBusinessFinishEvent.java
similarity index 72%
copy from core/src/main/java/org/apache/servicecomb/core/exception/ExceptionCodes.java
copy to core/src/main/java/org/apache/servicecomb/core/event/InvocationBusinessFinishEvent.java
index f28b4e6..2c3fe13 100644
--- a/core/src/main/java/org/apache/servicecomb/core/exception/ExceptionCodes.java
+++ b/core/src/main/java/org/apache/servicecomb/core/event/InvocationBusinessFinishEvent.java
@@ -14,13 +14,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.servicecomb.core.exception;
 
-public interface ExceptionCodes {
-  String GENERIC_CLIENT = "SCB.00000000";
-  String LB_ADDRESS_NOT_FOUND = "SCB.00000001";
-  String NOT_DEFINED_ANY_SCHEMA = "SCB.00000002";
-  String DEFAULT_VALIDATE = "SCB.00000003";
+package org.apache.servicecomb.core.event;
 
-  String GENERIC_SERVER = "SCB.50000000";
+import org.apache.servicecomb.core.Invocation;
+
+public class InvocationBusinessFinishEvent extends InvocationBaseEvent {
+  public InvocationBusinessFinishEvent(Invocation invocation) {
+    super(invocation);
+  }
 }
diff --git a/core/src/main/java/org/apache/servicecomb/core/exception/ExceptionCodes.java b/core/src/main/java/org/apache/servicecomb/core/event/InvocationHandlersStartEvent.java
similarity index 72%
copy from core/src/main/java/org/apache/servicecomb/core/exception/ExceptionCodes.java
copy to core/src/main/java/org/apache/servicecomb/core/event/InvocationHandlersStartEvent.java
index f28b4e6..a064b16 100644
--- a/core/src/main/java/org/apache/servicecomb/core/exception/ExceptionCodes.java
+++ b/core/src/main/java/org/apache/servicecomb/core/event/InvocationHandlersStartEvent.java
@@ -14,13 +14,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.servicecomb.core.exception;
 
-public interface ExceptionCodes {
-  String GENERIC_CLIENT = "SCB.00000000";
-  String LB_ADDRESS_NOT_FOUND = "SCB.00000001";
-  String NOT_DEFINED_ANY_SCHEMA = "SCB.00000002";
-  String DEFAULT_VALIDATE = "SCB.00000003";
+package org.apache.servicecomb.core.event;
 
-  String GENERIC_SERVER = "SCB.50000000";
-}
+import org.apache.servicecomb.core.Invocation;
+
+public class InvocationHandlersStartEvent extends InvocationBaseEvent {
+  public InvocationHandlersStartEvent(Invocation invocation) {
+    super(invocation);
+  }
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/servicecomb/core/exception/ExceptionCodes.java b/core/src/main/java/org/apache/servicecomb/core/event/InvocationStartSendRequestEvent.java
similarity index 72%
copy from core/src/main/java/org/apache/servicecomb/core/exception/ExceptionCodes.java
copy to core/src/main/java/org/apache/servicecomb/core/event/InvocationStartSendRequestEvent.java
index f28b4e6..a5bd8c8 100644
--- a/core/src/main/java/org/apache/servicecomb/core/exception/ExceptionCodes.java
+++ b/core/src/main/java/org/apache/servicecomb/core/event/InvocationStartSendRequestEvent.java
@@ -14,13 +14,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.servicecomb.core.exception;
 
-public interface ExceptionCodes {
-  String GENERIC_CLIENT = "SCB.00000000";
-  String LB_ADDRESS_NOT_FOUND = "SCB.00000001";
-  String NOT_DEFINED_ANY_SCHEMA = "SCB.00000002";
-  String DEFAULT_VALIDATE = "SCB.00000003";
+package org.apache.servicecomb.core.event;
 
-  String GENERIC_SERVER = "SCB.50000000";
-}
+import org.apache.servicecomb.core.Invocation;
+
+public class InvocationStartSendRequestEvent extends InvocationBaseEvent {
+  public InvocationStartSendRequestEvent(Invocation invocation) {
+    super(invocation);
+  }
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/servicecomb/core/exception/ExceptionCodes.java b/core/src/main/java/org/apache/servicecomb/core/event/InvocationTimeoutCheckEvent.java
similarity index 72%
copy from core/src/main/java/org/apache/servicecomb/core/exception/ExceptionCodes.java
copy to core/src/main/java/org/apache/servicecomb/core/event/InvocationTimeoutCheckEvent.java
index f28b4e6..168081e 100644
--- a/core/src/main/java/org/apache/servicecomb/core/exception/ExceptionCodes.java
+++ b/core/src/main/java/org/apache/servicecomb/core/event/InvocationTimeoutCheckEvent.java
@@ -14,13 +14,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.servicecomb.core.exception;
 
-public interface ExceptionCodes {
-  String GENERIC_CLIENT = "SCB.00000000";
-  String LB_ADDRESS_NOT_FOUND = "SCB.00000001";
-  String NOT_DEFINED_ANY_SCHEMA = "SCB.00000002";
-  String DEFAULT_VALIDATE = "SCB.00000003";
+package org.apache.servicecomb.core.event;
 
-  String GENERIC_SERVER = "SCB.50000000";
-}
+import org.apache.servicecomb.core.Invocation;
+
+public class InvocationTimeoutCheckEvent extends InvocationBaseEvent {
+  public InvocationTimeoutCheckEvent(Invocation invocation) {
+    super(invocation);
+  }
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/servicecomb/core/exception/ExceptionCodes.java b/core/src/main/java/org/apache/servicecomb/core/exception/ExceptionCodes.java
index f28b4e6..4c2c508 100644
--- a/core/src/main/java/org/apache/servicecomb/core/exception/ExceptionCodes.java
+++ b/core/src/main/java/org/apache/servicecomb/core/exception/ExceptionCodes.java
@@ -21,6 +21,7 @@ public interface ExceptionCodes {
   String LB_ADDRESS_NOT_FOUND = "SCB.00000001";
   String NOT_DEFINED_ANY_SCHEMA = "SCB.00000002";
   String DEFAULT_VALIDATE = "SCB.00000003";
+  String INVOCATION_TIMEOUT = "SCB.00000004";
 
   String GENERIC_SERVER = "SCB.50000000";
 }
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 a07ff75..e144d81 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
@@ -53,7 +53,7 @@ public class ScheduleFilter implements ProducerFilter {
     try {
       InvocationStageTrace trace = invocation.getInvocationStageTrace();
       trace.startServerFiltersRequest();
-      trace.startHandlersRequest();
+      invocation.onStartHandlersRequest();
 
       checkInQueueTimeout(invocation);
 
diff --git a/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationTimeoutBootListener.java b/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationTimeoutBootListener.java
new file mode 100644
index 0000000..3aa3327
--- /dev/null
+++ b/core/src/main/java/org/apache/servicecomb/core/invocation/InvocationTimeoutBootListener.java
@@ -0,0 +1,159 @@
+/*
+ * 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.invocation;
+
+import static javax.ws.rs.core.Response.Status.REQUEST_TIMEOUT;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.servicecomb.core.BootListener;
+import org.apache.servicecomb.core.Const;
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.core.event.InvocationBusinessFinishEvent;
+import org.apache.servicecomb.core.event.InvocationBusinessMethodStartEvent;
+import org.apache.servicecomb.core.event.InvocationFinishEvent;
+import org.apache.servicecomb.core.event.InvocationHandlersStartEvent;
+import org.apache.servicecomb.core.event.InvocationRunInExecutorStartEvent;
+import org.apache.servicecomb.core.event.InvocationStartEvent;
+import org.apache.servicecomb.core.event.InvocationStartSendRequestEvent;
+import org.apache.servicecomb.core.event.InvocationTimeoutCheckEvent;
+import org.apache.servicecomb.core.exception.ExceptionCodes;
+import org.apache.servicecomb.foundation.common.event.EnableExceptionPropagation;
+import org.apache.servicecomb.foundation.common.event.EventManager;
+import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import com.google.common.eventbus.Subscribe;
+import com.netflix.config.DynamicPropertyFactory;
+
+@Component
+public class InvocationTimeoutBootListener implements BootListener {
+  private static final Logger LOGGER = LoggerFactory.getLogger(InvocationTimeoutBootListener.class);
+  
+  public static final String ENABLE_TIMEOUT_CHECK = "servicecomb.invocation.enableTimeoutCheck";
+
+  public static boolean timeoutCheckEnabled() {
+    return DynamicPropertyFactory.getInstance().getBooleanProperty
+        (ENABLE_TIMEOUT_CHECK, true).get();
+  }
+
+  @Override
+  public void onAfterRegistry(BootEvent event) {
+    if (timeoutCheckEnabled()) {
+      EventManager.getEventBus().register(this);
+    }
+  }
+
+  @Subscribe
+  public void onInvocationStartEvent(InvocationStartEvent event) {
+    Invocation invocation = event.getInvocation();
+
+    // not initialized
+    // 1. when first time received request
+    // 2. when first time send request not a user thread
+    // initialized
+    // 1. send request in the progress of processing request
+    if (invocation.getLocalContext(Const.CONTEXT_TIME_CURRENT) == null) {
+      invocation.addLocalContext(Const.CONTEXT_TIME_CURRENT, invocation.getInvocationStageTrace().getStart());
+    }
+
+    if (invocation.getLocalContext(Const.CONTEXT_TIME_ELAPSED) == null) {
+      String elapsed = invocation.getContext(Const.CONTEXT_TIME_ELAPSED);
+      if (StringUtils.isEmpty(elapsed)) {
+        invocation.addLocalContext(Const.CONTEXT_TIME_ELAPSED, 0L);
+        return;
+      }
+
+      try {
+        invocation.addLocalContext(Const.CONTEXT_TIME_ELAPSED, Long.parseLong(elapsed));
+      } catch (NumberFormatException e) {
+        LOGGER.error("Not expected number format exception, attacker?");
+        invocation.addLocalContext(Const.CONTEXT_TIME_ELAPSED, 0L);
+      }
+    }
+  }
+
+  @Subscribe
+  @EnableExceptionPropagation
+  public void onInvocationTimeoutCheckEvent(InvocationTimeoutCheckEvent event) {
+    ensureInvocationNotTimeout(event.getInvocation());
+  }
+
+  /**
+   * check if invocation is timeout.
+   *
+   * @throws InvocationException if timeout, throw an exception. Will not throw exception twice if this method called
+   *  after timeout.
+   */
+  private void ensureInvocationNotTimeout(Invocation invocation) {
+    if (invocation.getOperationMeta().getConfig().getNanoInvocationTimeout() > 0 && calculateElapsedTime(invocation) >
+        invocation.getOperationMeta().getConfig().getNanoInvocationTimeout()) {
+      if (invocation.getLocalContext(Const.CONTEXT_TIMED_OUT) != null) {
+        // already timed out, do not throw exception again
+        return;
+      }
+      invocation.addLocalContext(Const.CONTEXT_TIMED_OUT, true);
+      throw new InvocationException(REQUEST_TIMEOUT,
+          ExceptionCodes.INVOCATION_TIMEOUT, "Invocation Timeout.");
+    }
+  }
+
+  private long calculateElapsedTime(Invocation invocation) {
+    return System.nanoTime() - (long) invocation.getLocalContext(Const.CONTEXT_TIME_CURRENT)
+        + (long) invocation.getLocalContext(Const.CONTEXT_TIME_ELAPSED);
+  }
+
+  @Subscribe
+  @EnableExceptionPropagation
+  public void onInvocationRunInExecutorStartEvent(InvocationRunInExecutorStartEvent event) {
+    ensureInvocationNotTimeout(event.getInvocation());
+  }
+
+  @Subscribe
+  @EnableExceptionPropagation
+  public void onInvocationHandlersStartEvent(InvocationHandlersStartEvent event) {
+    ensureInvocationNotTimeout(event.getInvocation());
+  }
+
+  @Subscribe
+  @EnableExceptionPropagation
+  public void onInvocationBusinessMethodStartEvent(InvocationBusinessMethodStartEvent event) {
+    ensureInvocationNotTimeout(event.getInvocation());
+  }
+
+  @Subscribe
+  @EnableExceptionPropagation
+  public void onInvocationBusinessFinishEvent(InvocationBusinessFinishEvent event) {
+    ensureInvocationNotTimeout(event.getInvocation());
+  }
+
+  @Subscribe
+  @EnableExceptionPropagation
+  public void onInvocationStartSendRequestEvent(InvocationStartSendRequestEvent event) {
+    Invocation invocation = event.getInvocation();
+    ensureInvocationNotTimeout(invocation);
+    invocation.addContext(Const.CONTEXT_TIME_ELAPSED, Long.toString(calculateElapsedTime(invocation)));
+  }
+
+  @Subscribe
+  @EnableExceptionPropagation
+  public void onInvocationFinishEvent(InvocationFinishEvent event) {
+    ensureInvocationNotTimeout(event.getInvocation());
+  }
+}
diff --git a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/InvokerUtils.java b/core/src/main/java/org/apache/servicecomb/core/provider/consumer/InvokerUtils.java
index c14cc24..09b4337 100644
--- a/core/src/main/java/org/apache/servicecomb/core/provider/consumer/InvokerUtils.java
+++ b/core/src/main/java/org/apache/servicecomb/core/provider/consumer/InvokerUtils.java
@@ -154,7 +154,7 @@ public final class InvokerUtils {
       SyncResponseExecutor respExecutor = new SyncResponseExecutor();
       invocation.setResponseExecutor(respExecutor);
 
-      invocation.getInvocationStageTrace().startHandlersRequest();
+      invocation.onStartHandlersRequest();
       invocation.next(respExecutor::setResponse);
 
       Response response = respExecutor.waitResponse();
@@ -187,7 +187,7 @@ public final class InvokerUtils {
       ReactiveResponseExecutor respExecutor = new ReactiveResponseExecutor();
       invocation.setResponseExecutor(respExecutor);
 
-      invocation.getInvocationStageTrace().startHandlersRequest();
+      invocation.onStartHandlersRequest();
       invocation.next(ar -> {
         ContextUtils.setInvocationContext(invocation.getParentContext());
         try {
@@ -225,8 +225,7 @@ public final class InvokerUtils {
    */
   public static CompletableFuture<Response> invoke(Invocation invocation) {
     invocation.onStart(null, System.nanoTime());
-    invocation.getInvocationStageTrace().startHandlersRequest();
-
+    invocation.onStartHandlersRequest();
     return invocation.getMicroserviceMeta().getFilterChain()
         .onFilter(invocation)
         .exceptionally(throwable -> convertException(invocation, throwable))
diff --git a/core/src/test/java/org/apache/servicecomb/core/definition/OperationConfigTest.java b/core/src/test/java/org/apache/servicecomb/core/definition/OperationConfigTest.java
index 1745dfc..dc8076b 100644
--- a/core/src/test/java/org/apache/servicecomb/core/definition/OperationConfigTest.java
+++ b/core/src/test/java/org/apache/servicecomb/core/definition/OperationConfigTest.java
@@ -58,5 +58,14 @@ class OperationConfigTest {
       long nano = TimeUnit.MILLISECONDS.toNanos(2);
       assertThat(config.getNanoRequestWaitInPoolTimeout("abc")).isEqualTo(nano);
     }
+
+    @Test
+    void should_get_invocation_timeout_value() {
+      config.setMsInvocationTimeout(1);
+
+      long nano = TimeUnit.MILLISECONDS.toNanos(1);
+      assertThat(config.getNanoInvocationTimeout()).isEqualTo(nano);
+      assertThat(config.getMsInvocationTimeout()).isEqualTo(1);
+    }
   }
 }
\ No newline at end of file
diff --git a/demo/demo-jaxrs/jaxrs-client/src/main/resources/microservice.yaml b/demo/demo-jaxrs/jaxrs-client/src/main/resources/microservice.yaml
index 89a8e48..fd46e82 100644
--- a/demo/demo-jaxrs/jaxrs-client/src/main/resources/microservice.yaml
+++ b/demo/demo-jaxrs/jaxrs-client/src/main/resources/microservice.yaml
@@ -43,6 +43,9 @@ servicecomb:
         add:
           timeout: 1000
 
+  invocation:
+    enableTimeoutCheck: false
+
 # test configurations. you can choose any implementation. default using local.
 
   # using nacos configuration
diff --git a/demo/demo-jaxrs/jaxrs-server/src/main/resources/microservice.yaml b/demo/demo-jaxrs/jaxrs-server/src/main/resources/microservice.yaml
index d6da5b2..2eda948 100644
--- a/demo/demo-jaxrs/jaxrs-server/src/main/resources/microservice.yaml
+++ b/demo/demo-jaxrs/jaxrs-server/src/main/resources/microservice.yaml
@@ -36,4 +36,7 @@ servicecomb:
   codec:
     printErrorMessage: true
 
-  executors.Provider.ReactiveSchema: servicecomb.executor.reactive
\ No newline at end of file
+  executors.Provider.ReactiveSchema: servicecomb.executor.reactive
+
+  invocation:
+    enableTimeoutCheck: false
\ No newline at end of file
diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/CommonSchemaInterface.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/CommonSchemaInterface.java
new file mode 100644
index 0000000..0b50fa6
--- /dev/null
+++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/CommonSchemaInterface.java
@@ -0,0 +1,36 @@
+/*
+ * 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.demo;
+
+import org.apache.servicecomb.swagger.invocation.context.InvocationContext;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import io.swagger.annotations.ApiOperation;
+
+@RequestMapping("/CommonSchemaInterface")
+public interface CommonSchemaInterface {
+  @GetMapping(path = "testInvocationTimeout")
+  String testInvocationTimeout(@RequestParam("timeout") long timeout, @RequestParam("name") String name);
+
+  @GetMapping(path = "testInvocationTimeoutWithInvocation")
+  @ApiOperation(value = "testInvocationTimeoutWithInvocation", nickname = "testInvocationTimeoutWithInvocation")
+  String testInvocationTimeout(InvocationContext context, @RequestParam("timeout") long timeout,
+      @RequestParam("name") String name);
+}
diff --git a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/TestMgr.java b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/TestMgr.java
index ede3da4..eb80dc6 100644
--- a/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/TestMgr.java
+++ b/demo/demo-schema/src/main/java/org/apache/servicecomb/demo/TestMgr.java
@@ -73,6 +73,10 @@ public class TestMgr {
     }
   }
 
+  public static void fail(String desc) {
+    failed(desc, new Exception(desc));
+  }
+
   public static void failed(String desc, Throwable e) {
     checkes.incrementAndGet();
 
diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestSpringMVCCommonSchemaInterface.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestSpringMVCCommonSchemaInterface.java
new file mode 100644
index 0000000..e45da0d
--- /dev/null
+++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestSpringMVCCommonSchemaInterface.java
@@ -0,0 +1,76 @@
+/*
+ * 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.demo.springmvc.client;
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.servicecomb.core.Const;
+import org.apache.servicecomb.demo.CategorizedTestCase;
+import org.apache.servicecomb.demo.CommonSchemaInterface;
+import org.apache.servicecomb.demo.TestMgr;
+import org.apache.servicecomb.provider.pojo.RpcReference;
+import org.apache.servicecomb.swagger.invocation.context.InvocationContext;
+import org.apache.servicecomb.swagger.invocation.exception.CommonExceptionData;
+import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
+import org.springframework.stereotype.Component;
+
+@Component
+public class TestSpringMVCCommonSchemaInterface implements CategorizedTestCase {
+  @RpcReference(schemaId = "SpringMVCCommonSchemaInterface", microserviceName = "springmvc")
+  private CommonSchemaInterface client;
+
+  public void testAllTransport() throws Exception {
+    testInvocationTimeoutInServer();
+    testInvocationTimeoutInServerUserCheck();
+    testInvocationAlreadyTimeoutInClient();
+  }
+
+  private void testInvocationTimeoutInServerUserCheck() {
+    try {
+      InvocationContext context = new InvocationContext();
+      client.testInvocationTimeout(context, 1001, "customized");
+      TestMgr.fail("should timeout");
+    } catch (InvocationException e) {
+      TestMgr.check(408, e.getStatusCode());
+      TestMgr.check("Invocation Timeout.", ((CommonExceptionData) e.getErrorData()).getMessage());
+    }
+  }
+
+  private void testInvocationAlreadyTimeoutInClient() {
+    try {
+      InvocationContext context = new InvocationContext();
+      context.addLocalContext(Const.CONTEXT_TIME_CURRENT, System.nanoTime());
+      context.addLocalContext(Const.CONTEXT_TIME_ELAPSED, TimeUnit.SECONDS.toNanos(1));
+      client.testInvocationTimeout(context, 1, "hello");
+      TestMgr.fail("should timeout");
+    } catch (InvocationException e) {
+      TestMgr.check(408, e.getStatusCode());
+      TestMgr.check("Invocation Timeout.", ((CommonExceptionData) e.getErrorData()).getMessage());
+    }
+  }
+
+  private void testInvocationTimeoutInServer() {
+    try {
+      client.testInvocationTimeout(1001, "hello");
+      TestMgr.fail("should timeout");
+    } catch (InvocationException e) {
+      TestMgr.check(408, e.getStatusCode());
+      TestMgr.check("Invocation Timeout.", ((CommonExceptionData) e.getErrorData()).getMessage());
+    }
+  }
+}
diff --git a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestUploadSchema.java b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestUploadSchema.java
index cebd61c..c43f8e2 100644
--- a/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestUploadSchema.java
+++ b/demo/demo-springmvc/springmvc-client/src/main/java/org/apache/servicecomb/demo/springmvc/client/TestUploadSchema.java
@@ -78,5 +78,7 @@ public class TestUploadSchema implements CategorizedTestCase {
 
     String result = template.postForObject("servicecomb://springmvc/upload/fileUpload", entity, String.class);
     TestMgr.check(result, "success");
+
+    files.forEach(file -> file.delete());
   }
 }
diff --git a/demo/demo-springmvc/springmvc-client/src/main/resources/microservice.yaml b/demo/demo-springmvc/springmvc-client/src/main/resources/microservice.yaml
index cc63f46..efd5bdf 100644
--- a/demo/demo-springmvc/springmvc-client/src/main/resources/microservice.yaml
+++ b/demo/demo-springmvc/springmvc-client/src/main/resources/microservice.yaml
@@ -34,7 +34,6 @@ servicecomb:
         pull:
           interval: 90
         watch: true
-      autodiscovery: true
   # can download config center from https://cse-bucket.obs.myhwclouds.com/LocalCSE/Local-CSE-1.0.0.zip to test dynamic config
   config:
     client:
diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/ProducerTestsAfterBootup.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/ProducerTestsAfterBootup.java
index 5ce24df..e36dcd7 100644
--- a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/ProducerTestsAfterBootup.java
+++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/ProducerTestsAfterBootup.java
@@ -91,9 +91,9 @@ public class ProducerTestsAfterBootup implements BootListener {
 
   public void testRegisteredBasePath() {
     if (DynamicPropertyFactory.getInstance().getBooleanProperty("servicecomb.test.vert.transport", true).get()) {
-      TestMgr.check(18, RegistrationManager.INSTANCE.getMicroservice().getPaths().size());	
+      TestMgr.check(19, RegistrationManager.INSTANCE.getMicroservice().getPaths().size());
     } else {	
-      TestMgr.check(19, RegistrationManager.INSTANCE.getMicroservice().getPaths().size());	
+      TestMgr.check(20, RegistrationManager.INSTANCE.getMicroservice().getPaths().size());
     }	
   }
 
diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SpringMVCCommonSchemaInterface.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SpringMVCCommonSchemaInterface.java
new file mode 100644
index 0000000..4fa5b73
--- /dev/null
+++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/SpringMVCCommonSchemaInterface.java
@@ -0,0 +1,60 @@
+/*
+ * 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.demo.springmvc.server;
+
+import javax.ws.rs.core.Response.Status;
+
+import org.apache.servicecomb.core.Invocation;
+import org.apache.servicecomb.demo.CommonSchemaInterface;
+import org.apache.servicecomb.provider.rest.common.RestSchema;
+import org.apache.servicecomb.swagger.invocation.context.InvocationContext;
+import org.apache.servicecomb.swagger.invocation.exception.InvocationException;
+
+@RestSchema(schemaId = "SpringMVCCommonSchemaInterface", schemaInterface = CommonSchemaInterface.class)
+public class SpringMVCCommonSchemaInterface implements CommonSchemaInterface {
+  @Override
+  public String testInvocationTimeout(long timeout, String name) {
+    try {
+      Thread.sleep(timeout);
+    } catch (InterruptedException e) {
+
+    }
+
+    return name;
+  }
+
+  @Override
+  public String testInvocationTimeout(InvocationContext context, long timeout,
+      String name) {
+
+    if ("customized".equals(name)) {
+      try {
+        Thread.sleep(timeout);
+      } catch (InterruptedException e) {
+
+      }
+
+      Invocation invocation = (Invocation) context;
+      invocation.ensureInvocationNotTimeout();
+
+      throw new InvocationException(Status.BAD_REQUEST, "not expected result");
+    }
+
+    return testInvocationTimeout(timeout, name);
+  }
+}
diff --git a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/UploadSchema.java b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/UploadSchema.java
index 24ec3f2..110ccd8 100644
--- a/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/UploadSchema.java
+++ b/demo/demo-springmvc/springmvc-server/src/main/java/org/apache/servicecomb/demo/springmvc/server/UploadSchema.java
@@ -19,6 +19,7 @@ package org.apache.servicecomb.demo.springmvc.server;
 
 import java.io.File;
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.UUID;
 
@@ -39,12 +40,15 @@ public class UploadSchema {
   public String fileUpload(@RequestPart(name = "files") List<MultipartFile> files) {
     try {
       String fileName = UUID.randomUUID().toString();
+      List<File> savedFiles = new ArrayList<>();
       int index = 0;
       for (MultipartFile file : files) {
         File tempFile = new File("random-server-" + fileName + index);
+        savedFiles.add(tempFile);
         file.transferTo(tempFile);
         index++;
       }
+      savedFiles.forEach(file -> file.delete());
       return "success";
     } catch (IOException e) {
       return "failed";
diff --git a/demo/demo-springmvc/springmvc-server/src/main/resources/microservice.yaml b/demo/demo-springmvc/springmvc-server/src/main/resources/microservice.yaml
index 4ebec70..ef9141d 100644
--- a/demo/demo-springmvc/springmvc-server/src/main/resources/microservice.yaml
+++ b/demo/demo-springmvc/springmvc-server/src/main/resources/microservice.yaml
@@ -60,6 +60,12 @@ servicecomb:
       compression: true
   highway:
     address: 0.0.0.0:7070?sslEnabled=true
+  invocation:
+    SpringMVCCommonSchemaInterface:
+      testInvocationTimeout:
+        timeout: 1000
+      testInvocationTimeoutWithInvocation:
+        timeout: 1000
   handler:
     chain:
       Provider:
diff --git a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/SimpleSubscriber.java b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/SimpleSubscriber.java
index e209f44..561974c 100644
--- a/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/SimpleSubscriber.java
+++ b/foundations/foundation-common/src/main/java/org/apache/servicecomb/foundation/common/event/SimpleSubscriber.java
@@ -107,9 +107,9 @@ public class SimpleSubscriber {
       dispatcher.accept(event);
     } catch (Throwable e) {
       if (enableExceptionPropagation) {
-        LOGGER.error("event process should not throw error. ", e);
         throw e;
       }
+      LOGGER.error("Event process should not throw exception when @EnableExceptionPropagation not set. ", e);
     }
   }
 
diff --git a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/FallbackPolicyManager.java b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/FallbackPolicyManager.java
index 88f502a..03da31d 100644
--- a/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/FallbackPolicyManager.java
+++ b/handlers/handler-bizkeeper/src/main/java/org/apache/servicecomb/bizkeeper/FallbackPolicyManager.java
@@ -41,11 +41,7 @@ public class FallbackPolicyManager {
     if (policy != null) {
       return policy.getFallbackResponse(invocation, error);
     } else {
-      return Response.failResp(invocation.getInvocationType(),
-          BizkeeperExceptionUtils
-              .createBizkeeperException(BizkeeperExceptionUtils.SERVICECOMB_BIZKEEPER_FALLBACK,
-                  error,
-                  invocation.getOperationMeta().getMicroserviceQualifiedName()));
+      return Response.failResp(invocation.getInvocationType(), error);
     }
   }
 
diff --git a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestFallbackPolicyManager.java b/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestFallbackPolicyManager.java
index 4860146..a9c0f70 100644
--- a/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestFallbackPolicyManager.java
+++ b/handlers/handler-bizkeeper/src/test/java/org/apache/servicecomb/bizkeeper/TestFallbackPolicyManager.java
@@ -16,6 +16,8 @@
  */
 package org.apache.servicecomb.bizkeeper;
 
+import javax.ws.rs.core.Response.Status;
+
 import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.core.definition.OperationMeta;
 import org.apache.servicecomb.core.exception.CseException;
@@ -134,8 +136,8 @@ public class TestFallbackPolicyManager {
         result = "unknown";
       }
     };
-    Assert.assertEquals(CseException.class,
-        ((Exception) FallbackPolicyManager.getFallbackResponse("Consumer", null, invocation).getResult()).getCause()
-            .getClass());
+    Assert.assertEquals(InvocationException.class,
+        ((Exception) FallbackPolicyManager.getFallbackResponse("Consumer", new InvocationException(
+            Status.TOO_MANY_REQUESTS, ""), invocation).getResult()).getClass());
   }
 }
diff --git a/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayClient.java b/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayClient.java
index 630a095..cbf233a 100644
--- a/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayClient.java
+++ b/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayClient.java
@@ -87,7 +87,7 @@ public class HighwayClient {
 
   public void send(Invocation invocation, AsyncResponse asyncResp) throws Exception {
     invocation.getInvocationStageTrace().startClientFiltersRequest();
-    invocation.getInvocationStageTrace().startSend();
+    invocation.onStartSendRequest();
 
     HighwayClientConnection tcpClient = findClientPool(invocation);
 
diff --git a/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayCodec.java b/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayCodec.java
index ac2bb96..937a62b 100644
--- a/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayCodec.java
+++ b/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayCodec.java
@@ -81,7 +81,6 @@ public final class HighwayCodec {
     Map<String, Object> swaggerArguments = requestDeserializer.deserialize(bodyBuffer.getBytes());
     addPrimitiveTypeDefaultValues(invocation, swaggerArguments);
     invocation.setSwaggerArguments(swaggerArguments);
-    invocation.mergeContext(header.getContext());
   }
 
   public static RequestHeader readRequestHeader(Buffer headerBuffer) throws Exception {
diff --git a/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayServerConnection.java b/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayServerConnection.java
index bb50fbc..a646f7a 100644
--- a/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayServerConnection.java
+++ b/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayServerConnection.java
@@ -156,6 +156,8 @@ public class HighwayServerConnection extends TcpServerConnection implements TcpB
         .setOperationProtobuf(ProtobufManager.getOrCreateOperation(invocation));
     invocation.setTransportContext(transportContext);
 
+    invocation.mergeContext(header.getContext());
+
     return CompletableFuture.completedFuture(invocation);
   }
 }
diff --git a/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayServerInvoke.java b/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayServerInvoke.java
index 2ffe63b..c88e90d 100644
--- a/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayServerInvoke.java
+++ b/transports/transport-highway/src/main/java/org/apache/servicecomb/transport/highway/HighwayServerInvoke.java
@@ -128,7 +128,7 @@ public class HighwayServerInvoke {
     HighwayCodec.decodeRequest(invocation, header, operationProtobuf, bodyBuffer);
     invocation.getHandlerContext().put(Const.REMOTE_ADDRESS, this.connection.getNetSocket().remoteAddress());
 
-    invocation.getInvocationStageTrace().startHandlersRequest();
+    invocation.onStartHandlersRequest();
     invocation.next(response -> sendResponse(invocation.getContext(), response));
   }
 
@@ -180,14 +180,11 @@ public class HighwayServerInvoke {
           .setBodyBuffer(bodyBuffer)
           .setOperationProtobuf(ProtobufManager.getOrCreateOperation(invocation));
       invocation.setTransportContext(transportContext);
+      invocation.mergeContext(header.getContext());
 
       invocation.onStart(null, start);
       invocation.getInvocationStageTrace().startSchedule();
 
-      // copied from HighwayCodec#decodeRequest()
-      // for temporary qps enhance purpose, we'll remove it when handler mechanism is refactored
-      invocation.mergeContext(header.getContext());
-
       Holder<Boolean> qpsFlowControlReject = checkQpsFlowControl(operationMeta);
       if (qpsFlowControlReject.value) {
         return;
diff --git a/transports/transport-highway/src/test/java/org/apache/servicecomb/transport/highway/TestHighwayClient.java b/transports/transport-highway/src/test/java/org/apache/servicecomb/transport/highway/TestHighwayClient.java
index baaef46..ad8a29f 100644
--- a/transports/transport-highway/src/test/java/org/apache/servicecomb/transport/highway/TestHighwayClient.java
+++ b/transports/transport-highway/src/test/java/org/apache/servicecomb/transport/highway/TestHighwayClient.java
@@ -195,11 +195,9 @@ public class TestHighwayClient {
     Object result = doTestSend(vertx, pool, tcpClient, Response.ok("ok"));
 
     Assert.assertEquals("ok", result);
-    Assert.assertEquals(nanoTime, invocationStageTrace.getStartClientFiltersRequest());
     Assert.assertEquals(nanoTime, invocationStageTrace.getStartClientFiltersResponse());
     Assert.assertEquals(nanoTime, invocationStageTrace.getFinishClientFiltersResponse());
 
-    Assert.assertEquals(nanoTime, invocationStageTrace.getStartSend());
     Assert.assertEquals(nanoTime, invocationStageTrace.getFinishGetConnection());
     Assert.assertEquals(nanoTime, invocationStageTrace.getFinishWriteToBuffer());
     Assert.assertEquals(nanoTime, invocationStageTrace.getFinishReceiveResponse());
@@ -218,7 +216,6 @@ public class TestHighwayClient {
     Object result = doTestSend(vertx, pool, tcpClient, new InvocationException(Status.BAD_REQUEST, (Object) "failed"));
 
     Assert.assertEquals("failed", ((InvocationException) result).getErrorData());
-    Assert.assertEquals(nanoTime, invocationStageTrace.getStartClientFiltersRequest());
     Assert.assertEquals(nanoTime, invocationStageTrace.getStartClientFiltersResponse());
     Assert.assertEquals(nanoTime, invocationStageTrace.getFinishClientFiltersResponse());
   }
@@ -239,7 +236,6 @@ public class TestHighwayClient {
         null);
 
     Assert.assertEquals("failed", ((InvocationException) result).getErrorData());
-    Assert.assertEquals(nanoTime, invocationStageTrace.getStartClientFiltersRequest());
     Assert.assertEquals(nanoTime, invocationStageTrace.getStartClientFiltersResponse());
     Assert.assertEquals(nanoTime, invocationStageTrace.getFinishClientFiltersResponse());
   }
diff --git a/transports/transport-highway/src/test/java/org/apache/servicecomb/transport/highway/TestHighwayCodec.java b/transports/transport-highway/src/test/java/org/apache/servicecomb/transport/highway/TestHighwayCodec.java
index a990eca..a91b576 100644
--- a/transports/transport-highway/src/test/java/org/apache/servicecomb/transport/highway/TestHighwayCodec.java
+++ b/transports/transport-highway/src/test/java/org/apache/servicecomb/transport/highway/TestHighwayCodec.java
@@ -116,7 +116,9 @@ public class TestHighwayCodec {
 
 
   @Test
-  public void testDecodeRequestTraceId(@Mocked Endpoint endpoint) throws Exception {
+  public void test_decode_request_successful_and_not_copy_header(@Mocked Endpoint endpoint) throws Exception {
+    // test decode request not thrown exception and not copy header
+    // header should copied before invocation start.
     commonMock();
 
     Invocation invocation = new Invocation(endpoint, operationMeta, null);
@@ -132,7 +134,7 @@ public class TestHighwayCodec {
 
     context.put("X-B3-traceId", "test2");
     HighwayCodec.decodeRequest(invocation, headers, operationProtobuf, bodyBuffer);
-    Assert.assertEquals("test2", invocation.getContext("X-B3-traceId"));
+    Assert.assertEquals("test1", invocation.getContext("X-B3-traceId"));
   }
 
   @Test
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 d5c2bd4..84e8baa 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
@@ -38,6 +38,8 @@ public class RestClientSenderFilter implements ConsumerFilter {
 
   @Override
   public CompletableFuture<Response> onFilter(Invocation invocation, FilterNode nextNode) {
+    invocation.onStartSendRequest();
+
     CompletableFuture<Response> future = new RestClientSender(invocation)
         .send();
 
diff --git a/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/http/RestClientInvocation.java b/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/http/RestClientInvocation.java
index 1cb5837..70a2ce7 100644
--- a/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/http/RestClientInvocation.java
+++ b/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/http/RestClientInvocation.java
@@ -26,6 +26,7 @@ import org.apache.servicecomb.common.rest.RestConst;
 import org.apache.servicecomb.common.rest.codec.param.RestClientRequestImpl;
 import org.apache.servicecomb.common.rest.definition.RestOperationMeta;
 import org.apache.servicecomb.common.rest.filter.HttpClientFilter;
+import org.apache.servicecomb.core.Const;
 import org.apache.servicecomb.core.Invocation;
 import org.apache.servicecomb.core.definition.OperationConfig;
 import org.apache.servicecomb.core.definition.OperationMeta;
@@ -126,7 +127,7 @@ public class RestClientInvocation {
     });
 
     // 从业务线程转移到网络线程中去发送
-    invocation.getInvocationStageTrace().startSend();
+    invocation.onStartSendRequest();
     httpClientWithContext.runOnContext(httpClient -> {
       clientRequest.setTimeout(operationMeta.getConfig().getMsRequestTimeout());
       processServiceCombHeaders(invocation, operationMeta);
@@ -300,8 +301,7 @@ public class RestClientInvocation {
 
   protected void setCseContext() {
     try {
-      String cseContext = JsonUtils.writeValueAsString(invocation.getContext());
-      clientRequest.putHeader(org.apache.servicecomb.core.Const.CSE_CONTEXT, cseContext);
+      clientRequest.putHeader(Const.CSE_CONTEXT, JsonUtils.writeValueAsString(invocation.getContext()));
     } catch (Throwable e) {
       invocation.getTraceIdLogger().error(LOGGER, "Failed to encode and set cseContext, message={}."
           , ExceptionUtils.getExceptionMessageWithoutTrace(e));
diff --git a/transports/transport-rest/transport-rest-client/src/test/java/org/apache/servicecomb/transport/rest/client/http/TestRestClientInvocation.java b/transports/transport-rest/transport-rest-client/src/test/java/org/apache/servicecomb/transport/rest/client/http/TestRestClientInvocation.java
index fd29183..dde6a22 100644
--- a/transports/transport-rest/transport-rest-client/src/test/java/org/apache/servicecomb/transport/rest/client/http/TestRestClientInvocation.java
+++ b/transports/transport-rest/transport-rest-client/src/test/java/org/apache/servicecomb/transport/rest/client/http/TestRestClientInvocation.java
@@ -191,7 +191,6 @@ public class TestRestClientInvocation {
     Assert.assertEquals(TARGET_MICROSERVICE_NAME, headers.get(org.apache.servicecomb.core.Const.TARGET_MICROSERVICE));
     Assert.assertEquals("{}", headers.get(org.apache.servicecomb.core.Const.CSE_CONTEXT));
     Assert.assertEquals(nanoTime, invocation.getInvocationStageTrace().getStartClientFiltersRequest());
-    Assert.assertEquals(nanoTime, invocation.getInvocationStageTrace().getStartSend());
   }
 
   @Test
@@ -207,7 +206,6 @@ public class TestRestClientInvocation {
     Assert.assertSame(resp, response);
     Assert.assertThat(headers.names(), Matchers.empty());
     Assert.assertEquals(nanoTime, invocation.getInvocationStageTrace().getStartClientFiltersRequest());
-    Assert.assertEquals(nanoTime, invocation.getInvocationStageTrace().getStartSend());
   }
 
   @Test
@@ -228,7 +226,6 @@ public class TestRestClientInvocation {
     Assert.assertEquals(TARGET_MICROSERVICE_NAME, headers.get(org.apache.servicecomb.core.Const.TARGET_MICROSERVICE));
     Assert.assertEquals("{}", headers.get(org.apache.servicecomb.core.Const.CSE_CONTEXT));
     Assert.assertEquals(nanoTime, invocation.getInvocationStageTrace().getStartClientFiltersRequest());
-    Assert.assertEquals(nanoTime, invocation.getInvocationStageTrace().getStartSend());
     operationConfig.setClientRequestHeaderFilterEnabled(true);
   }
 

[servicecomb-java-chassis] 02/02: [SCB-2216]fix review comments

Posted by wu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

wujimin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-java-chassis.git

commit 0b46b0fabc1c9f5aa1905ce0697d02e389e31b92
Author: liubao68 <bi...@qq.com>
AuthorDate: Fri Mar 26 09:33:38 2021 +0800

    [SCB-2216]fix review comments
---
 .../org/apache/servicecomb/transport/highway/HighwayClientFilter.java   | 2 +-
 .../org/apache/servicecomb/transport/rest/client/RestClientSender.java  | 2 +-
 .../servicecomb/transport/rest/client/RestClientSenderFilter.java       | 2 --
 3 files changed, 2 insertions(+), 4 deletions(-)

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 fdd7a3e..ccebe79 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
@@ -62,7 +62,7 @@ public class HighwayClientFilter implements ConsumerFilter {
   }
 
   protected CompletableFuture<TcpData> send(Invocation invocation, OperationProtobuf operationProtobuf) {
-    invocation.getInvocationStageTrace().startSend();
+    invocation.onStartSendRequest();
 
     HighwayClient highwayClient = ((HighwayTransport) invocation.getTransport()).getHighwayClient();
     HighwayClientPackage clientPackage = highwayClient.createClientPackage(invocation, operationProtobuf);
diff --git a/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/RestClientSender.java b/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/RestClientSender.java
index caa62b4..558245e 100644
--- a/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/RestClientSender.java
+++ b/transports/transport-rest/transport-rest-client/src/main/java/org/apache/servicecomb/transport/rest/client/RestClientSender.java
@@ -65,7 +65,7 @@ public class RestClientSender {
 
   @SuppressWarnings("deprecation")
   public CompletableFuture<Response> send() {
-    invocation.getInvocationStageTrace().startSend();
+    invocation.onStartSendRequest();
 
     httpClientRequest.exceptionHandler(future::completeExceptionally);
     httpClientRequest.handler(this::processResponse);
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 84e8baa..d5c2bd4 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
@@ -38,8 +38,6 @@ public class RestClientSenderFilter implements ConsumerFilter {
 
   @Override
   public CompletableFuture<Response> onFilter(Invocation invocation, FilterNode nextNode) {
-    invocation.onStartSendRequest();
-
     CompletableFuture<Response> future = new RestClientSender(invocation)
         .send();