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 2022/11/12 06:55:55 UTC

[servicecomb-java-chassis] branch master updated: [SCB-2726] add TimeLimiter and Cache governance (#3474)

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 a9d8d301a [SCB-2726] add TimeLimiter and Cache governance (#3474)
a9d8d301a is described below

commit a9d8d301ae6fc1e67690fd9757f82803c2828bfa
Author: zzj8886 <11...@users.noreply.github.com>
AuthorDate: Sat Nov 12 14:55:48 2022 +0800

    [SCB-2726] add TimeLimiter and Cache governance (#3474)
---
 .../governance/GovernanceConfiguration.java        | 24 +++++++
 .../governance/handler/DisposableTimeLimiter.java  | 49 ++++++++++++++
 .../governance/handler/GovernanceCacheHandler.java | 68 ++++++++++++++++++++
 .../governance/handler/TimeLimiterHandler.java     | 74 ++++++++++++++++++++++
 .../governance/policy/GovernanceCachePolicy.java   | 64 +++++++++++++++++++
 .../governance/policy/TimeLimiterPolicy.java       | 45 +++++++++++++
 .../properties/GovernanceCacheProperties.java      | 36 +++++++++++
 .../properties/TimeLimiterProperties.java          | 37 +++++++++++
 .../governance/service/GovernanceCache.java        | 33 ++++++++++
 .../governance/service/GovernanceCacheImpl.java    | 52 +++++++++++++++
 .../governance/GovernanceCacheHandlerTest.java     | 54 ++++++++++++++++
 .../governance/GovernancePropertiesTest.java       | 71 ++++++++++++++++++++-
 .../governance/TimeLimiterHandlerTest.java         | 52 +++++++++++++++
 governance/src/test/resources/application.yaml     | 24 +++++++
 14 files changed, 682 insertions(+), 1 deletion(-)

diff --git a/governance/src/main/java/org/apache/servicecomb/governance/GovernanceConfiguration.java b/governance/src/main/java/org/apache/servicecomb/governance/GovernanceConfiguration.java
index efe058039..2b06b2172 100644
--- a/governance/src/main/java/org/apache/servicecomb/governance/GovernanceConfiguration.java
+++ b/governance/src/main/java/org/apache/servicecomb/governance/GovernanceConfiguration.java
@@ -22,6 +22,7 @@ import java.util.Map;
 import org.apache.servicecomb.governance.handler.BulkheadHandler;
 import org.apache.servicecomb.governance.handler.CircuitBreakerHandler;
 import org.apache.servicecomb.governance.handler.FaultInjectionHandler;
+import org.apache.servicecomb.governance.handler.GovernanceCacheHandler;
 import org.apache.servicecomb.governance.handler.IdentifierRateLimitingHandler;
 import org.apache.servicecomb.governance.handler.InstanceBulkheadHandler;
 import org.apache.servicecomb.governance.handler.InstanceIsolationHandler;
@@ -29,6 +30,7 @@ import org.apache.servicecomb.governance.handler.LoadBalanceHandler;
 import org.apache.servicecomb.governance.handler.MapperHandler;
 import org.apache.servicecomb.governance.handler.RateLimitingHandler;
 import org.apache.servicecomb.governance.handler.RetryHandler;
+import org.apache.servicecomb.governance.handler.TimeLimiterHandler;
 import org.apache.servicecomb.governance.handler.ext.AbstractCircuitBreakerExtension;
 import org.apache.servicecomb.governance.handler.ext.AbstractInstanceIsolationExtension;
 import org.apache.servicecomb.governance.handler.ext.AbstractRetryExtension;
@@ -40,6 +42,8 @@ import org.apache.servicecomb.governance.marker.operator.MatchOperator;
 import org.apache.servicecomb.governance.marker.operator.PrefixOperator;
 import org.apache.servicecomb.governance.marker.operator.SuffixOperator;
 import org.apache.servicecomb.governance.properties.BulkheadProperties;
+import org.apache.servicecomb.governance.properties.TimeLimiterProperties;
+import org.apache.servicecomb.governance.properties.GovernanceCacheProperties;
 import org.apache.servicecomb.governance.properties.CircuitBreakerProperties;
 import org.apache.servicecomb.governance.properties.FaultInjectionProperties;
 import org.apache.servicecomb.governance.properties.IdentifierRateLimitProperties;
@@ -101,6 +105,16 @@ public class GovernanceConfiguration {
     return new RetryProperties();
   }
 
+  @Bean
+  public TimeLimiterProperties timeLimiterProperties() {
+    return new TimeLimiterProperties();
+  }
+
+  @Bean
+  public GovernanceCacheProperties cacheProperties() {
+    return new GovernanceCacheProperties();
+  }
+
   @Bean
   public FaultInjectionProperties faultInjectionProperties() {
     return new FaultInjectionProperties();
@@ -161,6 +175,16 @@ public class GovernanceConfiguration {
     return new RetryHandler(retryProperties, retryExtension);
   }
 
+  @Bean
+  public TimeLimiterHandler timeLimiterHandler(TimeLimiterProperties timeLimiterProperties) {
+    return new TimeLimiterHandler(timeLimiterProperties);
+  }
+
+  @Bean
+  public GovernanceCacheHandler<String, Object> governanceCacheHandler(GovernanceCacheProperties cacheProperties) {
+    return new GovernanceCacheHandler<String, Object>(cacheProperties);
+  }
+
   @Bean
   public FaultInjectionHandler faultInjectionHandler(FaultInjectionProperties faultInjectionProperties) {
     return new FaultInjectionHandler(faultInjectionProperties);
diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/DisposableTimeLimiter.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/DisposableTimeLimiter.java
new file mode 100644
index 000000000..4a23b72d6
--- /dev/null
+++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/DisposableTimeLimiter.java
@@ -0,0 +1,49 @@
+/*
+ * 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.governance.handler;
+
+import io.github.resilience4j.timelimiter.TimeLimiter;
+import io.github.resilience4j.timelimiter.TimeLimiterRegistry;
+
+public class DisposableTimeLimiter extends Disposable<TimeLimiter> {
+  private final String key;
+
+  private final TimeLimiterRegistry timeLimiterRegistry;
+
+  private final TimeLimiter timeLimiter;
+
+  public DisposableTimeLimiter(String key, TimeLimiterRegistry registry, TimeLimiter timeLimiter) {
+    this.key = key;
+    this.timeLimiterRegistry = registry;
+    this.timeLimiter = timeLimiter;
+  }
+
+  @Override
+  public void dispose() {
+    timeLimiterRegistry.remove(key);
+  }
+
+  @Override
+  public TimeLimiter getValue() {
+    return timeLimiter;
+  }
+
+  @Override
+  public String getKey() {
+    return key;
+  }
+}
diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/GovernanceCacheHandler.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/GovernanceCacheHandler.java
new file mode 100644
index 000000000..88d96f937
--- /dev/null
+++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/GovernanceCacheHandler.java
@@ -0,0 +1,68 @@
+/*
+ * 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.governance.handler;
+
+import org.apache.servicecomb.governance.marker.GovernanceRequest;
+import org.apache.servicecomb.governance.policy.GovernanceCachePolicy;
+import org.apache.servicecomb.governance.properties.GovernanceCacheProperties;
+import org.apache.servicecomb.governance.service.GovernanceCache;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.time.Duration;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+
+public class GovernanceCacheHandler<K, V>
+    extends AbstractGovernanceHandler<GovernanceCache<K, V>, GovernanceCachePolicy> {
+  private static final Logger LOGGER = LoggerFactory.getLogger(GovernanceCacheHandler.class);
+
+  private final GovernanceCacheProperties cacheProperties;
+
+  public GovernanceCacheHandler(GovernanceCacheProperties cacheProperties) {
+    this.cacheProperties = cacheProperties;
+  }
+
+  @Override
+  public GovernanceCachePolicy matchPolicy(GovernanceRequest governanceRequest) {
+    return matchersManager.match(governanceRequest, cacheProperties.getParsedEntity());
+  }
+
+  @Override
+  protected String createKey(GovernanceRequest governanceRequest, GovernanceCachePolicy policy) {
+    return cacheProperties.getConfigKey() + "." + policy.getName();
+  }
+
+  @Override
+  protected Disposable<GovernanceCache<K, V>> createProcessor(String key, GovernanceRequest governanceRequest,
+      GovernanceCachePolicy policy) {
+    return getGovernanceCache(key, policy);
+  }
+
+  protected Disposable<GovernanceCache<K, V>> getGovernanceCache(String key, GovernanceCachePolicy policy) {
+    LOGGER.info("applying new policy {} for {}", key, policy.toString());
+    Cache<K,
+        V> cache = CacheBuilder.newBuilder()
+        .expireAfterWrite(Duration.parse(policy.getTtl()))
+        .maximumSize(policy.getMaximumSize())
+        .concurrencyLevel(policy.getConcurrencyLevel())
+        .build();
+    GovernanceCache<K, V> governanceCache = GovernanceCache.of(cache);
+    return new DisposableHolder<>(key, governanceCache);
+  }
+}
diff --git a/governance/src/main/java/org/apache/servicecomb/governance/handler/TimeLimiterHandler.java b/governance/src/main/java/org/apache/servicecomb/governance/handler/TimeLimiterHandler.java
new file mode 100644
index 000000000..357951bee
--- /dev/null
+++ b/governance/src/main/java/org/apache/servicecomb/governance/handler/TimeLimiterHandler.java
@@ -0,0 +1,74 @@
+/*
+ * 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.governance.handler;
+
+import io.github.resilience4j.micrometer.tagged.TaggedTimeLimiterMetrics;
+import io.github.resilience4j.micrometer.tagged.TimeLimiterMetricNames;
+import io.github.resilience4j.timelimiter.TimeLimiter;
+import io.github.resilience4j.timelimiter.TimeLimiterConfig;
+import io.github.resilience4j.timelimiter.TimeLimiterRegistry;
+
+import org.apache.servicecomb.governance.marker.GovernanceRequest;
+import org.apache.servicecomb.governance.policy.TimeLimiterPolicy;
+import org.apache.servicecomb.governance.properties.TimeLimiterProperties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.time.Duration;
+
+public class TimeLimiterHandler extends AbstractGovernanceHandler<TimeLimiter, TimeLimiterPolicy> {
+
+  private static final Logger LOGGER = LoggerFactory.getLogger(TimeLimiterHandler.class);
+
+  private final TimeLimiterProperties timeLimiterProperties;
+
+  public TimeLimiterHandler(TimeLimiterProperties timeLimiterProperties) {
+    this.timeLimiterProperties = timeLimiterProperties;
+  }
+
+  @Override
+  protected String createKey(GovernanceRequest governanceRequest, TimeLimiterPolicy policy) {
+    return timeLimiterProperties.getConfigKey() + "." + policy.getName();
+  }
+
+  @Override
+  public TimeLimiterPolicy matchPolicy(GovernanceRequest governanceRequest) {
+    return matchersManager.match(governanceRequest, timeLimiterProperties.getParsedEntity());
+  }
+
+  @Override
+  public Disposable<TimeLimiter> createProcessor(String key, GovernanceRequest governanceRequest,
+      TimeLimiterPolicy policy) {
+    return getTimeLimiter(key, policy);
+  }
+
+  private Disposable<TimeLimiter> getTimeLimiter(String key, TimeLimiterPolicy policy) {
+    LOGGER.info("applying new policy {} for {}", key, policy);
+    TimeLimiterConfig timeLimiterConfig = TimeLimiterConfig.custom()
+        .timeoutDuration(Duration.parse(policy.getTimeoutDuration()))
+        .cancelRunningFuture(policy.isCancelRunningFuture())
+        .build();
+    TimeLimiterRegistry timeLimiterRegistry = TimeLimiterRegistry.of(timeLimiterConfig);
+    if (meterRegistry != null) {
+      TaggedTimeLimiterMetrics.ofTimeLimiterRegistry(TimeLimiterMetricNames.custom()
+          .callsMetricName(timeLimiterProperties.getConfigKey() + ".calls")
+          .build(), timeLimiterRegistry).bindTo(meterRegistry);
+    }
+    return new DisposableTimeLimiter(key, timeLimiterRegistry, timeLimiterRegistry.timeLimiter(key));
+  }
+}
diff --git a/governance/src/main/java/org/apache/servicecomb/governance/policy/GovernanceCachePolicy.java b/governance/src/main/java/org/apache/servicecomb/governance/policy/GovernanceCachePolicy.java
new file mode 100644
index 000000000..719c9cf41
--- /dev/null
+++ b/governance/src/main/java/org/apache/servicecomb/governance/policy/GovernanceCachePolicy.java
@@ -0,0 +1,64 @@
+/*
+ * 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.governance.policy;
+
+import java.time.Duration;
+
+public class GovernanceCachePolicy extends AbstractPolicy {
+  public static final Duration DEFAULT_TTL = Duration.ofMillis(21600000);
+
+  public static final long DEFAULT_MAXIMUM_SIZE = 60000;
+
+  public static final int DEFAULT_CONCURRENCY_LEVEL = 8;
+
+  private String ttl = DEFAULT_TTL.toString();
+
+  private long maximumSize = DEFAULT_MAXIMUM_SIZE;
+
+  private int concurrencyLevel = DEFAULT_CONCURRENCY_LEVEL;
+
+  public String getTtl() {
+    return ttl;
+  }
+
+  public void setTtl(String ttl) {
+    this.ttl = stringOfDuration(ttl, DEFAULT_TTL);
+  }
+
+  public Long getMaximumSize() {
+    return maximumSize;
+  }
+
+  public void setMaximumSize(Long maximumSize) {
+    this.maximumSize = maximumSize;
+  }
+
+  public int getConcurrencyLevel() {
+    return concurrencyLevel;
+  }
+
+  public void setConcurrencyLevel(int concurrencyLevel) {
+    this.concurrencyLevel = concurrencyLevel;
+  }
+
+  @Override
+  public String toString() {
+    return "CachePolicy{" + "ttl=" + ttl + ",concurrencyLevel=" + concurrencyLevel + ", maximumSize=" + maximumSize
+        + '}';
+  }
+}
diff --git a/governance/src/main/java/org/apache/servicecomb/governance/policy/TimeLimiterPolicy.java b/governance/src/main/java/org/apache/servicecomb/governance/policy/TimeLimiterPolicy.java
new file mode 100644
index 000000000..e00300127
--- /dev/null
+++ b/governance/src/main/java/org/apache/servicecomb/governance/policy/TimeLimiterPolicy.java
@@ -0,0 +1,45 @@
+/*
+ * 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.governance.policy;
+
+import java.time.Duration;
+
+public class TimeLimiterPolicy extends AbstractPolicy {
+  public static final Duration DEFAULT_TIMEOUT_DURATION = Duration.ofMillis(1000);
+
+  public static final boolean DEFAULT_CANCEL_RUNNING_FUTURE = true;
+
+  private String timeoutDuration = DEFAULT_TIMEOUT_DURATION.toString();
+
+  private boolean cancelRunningFuture = DEFAULT_CANCEL_RUNNING_FUTURE;
+
+  public String getTimeoutDuration() {
+    return timeoutDuration;
+  }
+
+  public void setTimeoutDuration(String timeoutDuration) {
+    this.timeoutDuration = stringOfDuration(timeoutDuration, DEFAULT_TIMEOUT_DURATION);
+  }
+
+  public boolean isCancelRunningFuture() {
+    return cancelRunningFuture;
+  }
+
+  public void setCancelRunningFuture(boolean cancelRunningFuture) {
+    this.cancelRunningFuture = cancelRunningFuture;
+  }
+}
diff --git a/governance/src/main/java/org/apache/servicecomb/governance/properties/GovernanceCacheProperties.java b/governance/src/main/java/org/apache/servicecomb/governance/properties/GovernanceCacheProperties.java
new file mode 100644
index 000000000..9ae9a8daa
--- /dev/null
+++ b/governance/src/main/java/org/apache/servicecomb/governance/properties/GovernanceCacheProperties.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.governance.properties;
+
+import org.apache.servicecomb.governance.policy.GovernanceCachePolicy;
+
+public class GovernanceCacheProperties extends PolicyProperties<GovernanceCachePolicy> {
+  public static final String MATCH_CACHE_KEY = "servicecomb.cache";
+
+  public GovernanceCacheProperties() {
+    super(MATCH_CACHE_KEY);
+  }
+
+  public GovernanceCacheProperties(String key) {
+    super(key);
+  }
+
+  @Override
+  public Class<GovernanceCachePolicy> getEntityClass() {
+    return GovernanceCachePolicy.class;
+  }
+}
diff --git a/governance/src/main/java/org/apache/servicecomb/governance/properties/TimeLimiterProperties.java b/governance/src/main/java/org/apache/servicecomb/governance/properties/TimeLimiterProperties.java
new file mode 100644
index 000000000..daca14f57
--- /dev/null
+++ b/governance/src/main/java/org/apache/servicecomb/governance/properties/TimeLimiterProperties.java
@@ -0,0 +1,37 @@
+/*
+ * 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.governance.properties;
+
+
+import org.apache.servicecomb.governance.policy.TimeLimiterPolicy;
+
+public class TimeLimiterProperties extends PolicyProperties<TimeLimiterPolicy> {
+  public static final String MATCH_TIMELIMITER_KEY = "servicecomb.timeLimiter";
+
+  public TimeLimiterProperties() {
+    super(MATCH_TIMELIMITER_KEY);
+  }
+
+  public TimeLimiterProperties(String key) {
+    super(key);
+  }
+
+  @Override
+  public Class<TimeLimiterPolicy> getEntityClass() {
+    return TimeLimiterPolicy.class;
+  }
+}
diff --git a/governance/src/main/java/org/apache/servicecomb/governance/service/GovernanceCache.java b/governance/src/main/java/org/apache/servicecomb/governance/service/GovernanceCache.java
new file mode 100644
index 000000000..35014272f
--- /dev/null
+++ b/governance/src/main/java/org/apache/servicecomb/governance/service/GovernanceCache.java
@@ -0,0 +1,33 @@
+/*
+ * 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.governance.service;
+
+import com.google.common.cache.Cache;
+
+import java.util.Objects;
+
+public interface GovernanceCache<K, V> {
+  static <K, V> GovernanceCache<K, V> of(Cache<K, V> cache) {
+    Objects.requireNonNull(cache, "Cache must not be null");
+    return new GovernanceCacheImpl<>(cache);
+  }
+
+  V getValueFromCache(K cacheKey);
+
+  void putValueIntoCache(K cacheKey, V value);
+}
diff --git a/governance/src/main/java/org/apache/servicecomb/governance/service/GovernanceCacheImpl.java b/governance/src/main/java/org/apache/servicecomb/governance/service/GovernanceCacheImpl.java
new file mode 100644
index 000000000..a7dcfa5d4
--- /dev/null
+++ b/governance/src/main/java/org/apache/servicecomb/governance/service/GovernanceCacheImpl.java
@@ -0,0 +1,52 @@
+/*
+ * 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.governance.service;
+
+import com.google.common.cache.Cache;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class GovernanceCacheImpl<K, V> implements GovernanceCache<K, V> {
+
+  private static final Logger LOG = LoggerFactory.getLogger(GovernanceCacheImpl.class);
+
+  private final Cache<K, V> cache;
+
+  public GovernanceCacheImpl(Cache<K, V> cache) {
+    this.cache = cache;
+  }
+
+  public V getValueFromCache(K cacheKey) {
+    try {
+      return cache.getIfPresent(cacheKey);
+    } catch (Exception exception) {
+      LOG.warn("Failed to get a value from Cache", exception);
+      return null;
+    }
+  }
+
+  @Override
+  public void putValueIntoCache(K cacheKey, V value) {
+    try {
+      cache.put(cacheKey, value);
+    } catch (Exception exception) {
+      LOG.warn("Failed to put a value into Cache {}", exception);
+    }
+  }
+}
diff --git a/governance/src/test/java/org/apache/servicecomb/governance/GovernanceCacheHandlerTest.java b/governance/src/test/java/org/apache/servicecomb/governance/GovernanceCacheHandlerTest.java
new file mode 100644
index 000000000..3d1ee28cd
--- /dev/null
+++ b/governance/src/test/java/org/apache/servicecomb/governance/GovernanceCacheHandlerTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.governance;
+
+
+import org.apache.servicecomb.governance.handler.GovernanceCacheHandler;
+import org.apache.servicecomb.governance.marker.GovernanceRequest;
+import org.apache.servicecomb.governance.policy.GovernanceCachePolicy;
+import org.apache.servicecomb.governance.service.GovernanceCache;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ContextConfiguration;
+
+@SpringBootTest
+@ContextConfiguration(classes = {GovernanceConfiguration.class, MockConfiguration.class})
+public class GovernanceCacheHandlerTest {
+  private GovernanceCacheHandler<String, Object> governanceCacheHandler;
+
+  @Autowired
+  public void setInstanceIsolationHandler(@Autowired GovernanceCacheHandler<String, Object> governanceCacheHandler) {
+    this.governanceCacheHandler = governanceCacheHandler;
+  }
+
+  @Test
+  public void testMatchPriorityPolicy() {
+    GovernanceRequest request = new GovernanceRequest();
+    request.setUri("/governanceCache");
+    GovernanceCachePolicy policy = governanceCacheHandler.matchPolicy(request);
+    Assertions.assertEquals("demo-governanceCache", policy.getName());
+    GovernanceCache<String, Object> governanceCache = governanceCacheHandler.getActuator(request);
+    governanceCache.putValueIntoCache("governance", "Cache");
+    Object cache = governanceCache.getValueFromCache("governance");
+    Assertions.assertEquals("Cache", cache);
+    governanceCache.putValueIntoCache("response", null);
+    Object response = governanceCache.getValueFromCache("response");
+    Assertions.assertNull(response);
+  }
+}
diff --git a/governance/src/test/java/org/apache/servicecomb/governance/GovernancePropertiesTest.java b/governance/src/test/java/org/apache/servicecomb/governance/GovernancePropertiesTest.java
index 77902d848..d24329956 100644
--- a/governance/src/test/java/org/apache/servicecomb/governance/GovernancePropertiesTest.java
+++ b/governance/src/test/java/org/apache/servicecomb/governance/GovernancePropertiesTest.java
@@ -32,17 +32,21 @@ import org.apache.servicecomb.governance.policy.AbstractPolicy;
 import org.apache.servicecomb.governance.policy.BulkheadPolicy;
 import org.apache.servicecomb.governance.policy.CircuitBreakerPolicy;
 import org.apache.servicecomb.governance.policy.FaultInjectionPolicy;
+import org.apache.servicecomb.governance.policy.GovernanceCachePolicy;
 import org.apache.servicecomb.governance.policy.RateLimitingPolicy;
 import org.apache.servicecomb.governance.policy.RetryPolicy;
+import org.apache.servicecomb.governance.policy.TimeLimiterPolicy;
 import org.apache.servicecomb.governance.processor.injection.FaultInjectionConst;
 import org.apache.servicecomb.governance.properties.BulkheadProperties;
 import org.apache.servicecomb.governance.properties.CircuitBreakerProperties;
 import org.apache.servicecomb.governance.properties.FaultInjectionProperties;
+import org.apache.servicecomb.governance.properties.GovernanceCacheProperties;
 import org.apache.servicecomb.governance.properties.GovernanceProperties;
 import org.apache.servicecomb.governance.properties.InstanceIsolationProperties;
 import org.apache.servicecomb.governance.properties.MatchProperties;
 import org.apache.servicecomb.governance.properties.RateLimitProperties;
 import org.apache.servicecomb.governance.properties.RetryProperties;
+import org.apache.servicecomb.governance.properties.TimeLimiterProperties;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
@@ -65,6 +69,10 @@ public class GovernancePropertiesTest {
 
   private CircuitBreakerProperties circuitBreakerProperties;
 
+  private TimeLimiterProperties timeLimiterProperties;
+
+  private GovernanceCacheProperties governanceCacheProperties;
+
   private InstanceIsolationProperties instanceIsolationProperties;
 
   private RateLimitProperties rateLimitProperties;
@@ -95,6 +103,16 @@ public class GovernancePropertiesTest {
     this.circuitBreakerProperties = circuitBreakerProperties;
   }
 
+  @Autowired
+  public void setTimeLimiterProperties(TimeLimiterProperties timeLimiterProperties) {
+    this.timeLimiterProperties = timeLimiterProperties;
+  }
+
+  @Autowired
+  public void setGovernanceCacheProperties(GovernanceCacheProperties governanceCacheProperties) {
+    this.governanceCacheProperties = governanceCacheProperties;
+  }
+
   @Autowired
   public void setRateLimitProperties(RateLimitProperties rateLimitProperties) {
     this.rateLimitProperties = rateLimitProperties;
@@ -164,7 +182,7 @@ public class GovernancePropertiesTest {
 
   @Test
   public void test_all_bean_is_loaded() {
-    Assertions.assertEquals(14, propertiesList.size());
+    Assertions.assertEquals(16, propertiesList.size());
   }
 
   @Test
@@ -292,6 +310,57 @@ public class GovernancePropertiesTest {
     Assertions.assertEquals(3000, Duration.parse(policy.getMaxWaitDuration()).toMillis());
   }
 
+  @Test
+  public void test_timelimiter_properties_successfully_loaded() {
+    Map<String, TimeLimiterPolicy> policies = timeLimiterProperties.getParsedEntity();
+    Assertions.assertEquals(2, policies.size());
+    TimeLimiterPolicy timeLimiterPolicy = policies.get("demo-timeLimiter-other");
+    Assertions.assertEquals(2000, Duration.parse(timeLimiterPolicy.getTimeoutDuration()).toMillis());
+    Assertions.assertEquals(false, timeLimiterPolicy.isCancelRunningFuture());
+  }
+
+  @Test
+  public void test_timelimiter_properties_bound() {
+    dynamicValues.put("servicecomb.timeLimiter.name1", "rules:\n"
+        + "timeoutDuration: 5000\n"
+        + "cancelRunningFuture: false");
+
+    GovernanceEventManager.post(new GovernanceConfigurationChangedEvent(new HashSet<>(dynamicValues.keySet())));
+
+    Map<String, TimeLimiterPolicy> policies = timeLimiterProperties.getParsedEntity();
+    Assertions.assertEquals(3, policies.size());
+    TimeLimiterPolicy policy = policies.get("name1");
+    Assertions.assertEquals(false, policy.isCancelRunningFuture());
+    Assertions.assertEquals(5000, Duration.parse(policy.getTimeoutDuration()).toMillis());
+  }
+
+  @Test
+  public void test_governanceCache_properties_successfully_loaded() {
+    Map<String, GovernanceCachePolicy> policies = governanceCacheProperties.getParsedEntity();
+    Assertions.assertEquals(2, policies.size());
+    GovernanceCachePolicy governanceCachePolicy = policies.get("demo-governanceCache-other");
+    Assertions.assertEquals(15, governanceCachePolicy.getConcurrencyLevel());
+    Assertions.assertEquals(50000, governanceCachePolicy.getMaximumSize());
+    Assertions.assertEquals(666666, Duration.parse(governanceCachePolicy.getTtl()).toMillis());
+  }
+
+  @Test
+  public void test_governanceCache_properties_bound() {
+    dynamicValues.put("servicecomb.cache.name1", "rules:\n"
+        + "ttl: 3000000\n"
+        + "maximumSize: 2000\n"
+        + "concurrencyLevel: 6");
+
+    GovernanceEventManager.post(new GovernanceConfigurationChangedEvent(new HashSet<>(dynamicValues.keySet())));
+
+    Map<String, GovernanceCachePolicy> policies = governanceCacheProperties.getParsedEntity();
+    Assertions.assertEquals(3, policies.size());
+    GovernanceCachePolicy policy = policies.get("name1");
+    Assertions.assertEquals(3000000, Duration.parse(policy.getTtl()).toMillis());
+    Assertions.assertEquals(2000, policy.getMaximumSize());
+    Assertions.assertEquals(6, policy.getConcurrencyLevel());
+  }
+
   @Test
   public void test_circuit_breaker_properties_successfully_loaded() {
     Map<String, CircuitBreakerPolicy> policies = circuitBreakerProperties.getParsedEntity();
diff --git a/governance/src/test/java/org/apache/servicecomb/governance/TimeLimiterHandlerTest.java b/governance/src/test/java/org/apache/servicecomb/governance/TimeLimiterHandlerTest.java
new file mode 100644
index 000000000..5fd484f5e
--- /dev/null
+++ b/governance/src/test/java/org/apache/servicecomb/governance/TimeLimiterHandlerTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.governance;
+
+import java.time.Duration;
+
+import org.apache.servicecomb.governance.handler.TimeLimiterHandler;
+import org.apache.servicecomb.governance.marker.GovernanceRequest;
+import org.apache.servicecomb.governance.policy.TimeLimiterPolicy;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ContextConfiguration;
+
+import io.github.resilience4j.timelimiter.TimeLimiter;
+
+@SpringBootTest
+@ContextConfiguration(classes = {GovernanceConfiguration.class, MockConfiguration.class})
+public class TimeLimiterHandlerTest {
+  private TimeLimiterHandler timeLimiterHandler;
+
+  @Autowired
+  public void setInstanceIsolationHandler(TimeLimiterHandler timeLimiterHandler) {
+    this.timeLimiterHandler = timeLimiterHandler;
+  }
+
+  @Test
+  public void testMatchPriorityPolicy() {
+    GovernanceRequest request = new GovernanceRequest();
+    request.setUri("/timeLimiter");
+    TimeLimiterPolicy policy = timeLimiterHandler.matchPolicy(request);
+    Assertions.assertEquals("demo-timeLimiter", policy.getName());
+    TimeLimiter timeLimiter = timeLimiterHandler.getActuator(request);
+    Duration timeoutDuration = timeLimiter.getTimeLimiterConfig().getTimeoutDuration();
+    Assertions.assertEquals(2000, timeoutDuration.toMillis());
+  }
+}
diff --git a/governance/src/test/resources/application.yaml b/governance/src/test/resources/application.yaml
index 69c07171c..e6ba6c73b 100644
--- a/governance/src/test/resources/application.yaml
+++ b/governance/src/test/resources/application.yaml
@@ -17,6 +17,14 @@
 
 servicecomb:
   matchGroup:
+    demo-timeLimiter: |
+      matches:
+        - apiPath:
+            prefix: "/timeLimiter"
+    demo-governanceCache: |
+      matches:
+        - apiPath:
+            prefix: "/governanceCache"
     demo-loadbalance-random: |
       matches:
         - serviceName: "loadrandom"
@@ -99,6 +107,22 @@ servicecomb:
     demo-rateLimiting-servicename: |
       rate: 1
       identifier: test
+  timeLimiter:
+    demo-timeLimiter: |
+      timeoutDuration: 2000
+      cancelRunningFuture: true
+    demo-timeLimiter-other: |
+      timeoutDuration: 2000
+      cancelRunningFuture: false
+  cache:
+    demo-governanceCache: |
+      ttl: 36000000
+      maximumSize: 50000
+      concurrencyLevel: 10
+    demo-governanceCache-other: |
+      ttl: 666666
+      maximumSize: 50000
+      concurrencyLevel: 15
   retry:
     demo-retry: |
       maxAttempts: 3