Repository: alibaba/Sentinel
Pull request #2517 (2021-12-31 07:08:52)

Release 1.8.3
<!--  Thanks for submitting a pull request! Here are some tips for you:
1. Please make sure you have read and understood the contributing guidelines: https://github.com/alibaba/Sentinel/blob/master/CONTRIBUTING.md
2. Please make sure the PR has a corresponding issue.
-->

### Describe what this PR does / why we need it

Release 1.8.3 version (to `release-1.8` branch).


Patch:
diff --git a/README.md b/README.md
index 243cf309..8c39188d 100755
--- a/README.md
+++ b/README.md
@@ -7,7 +7,6 @@
 [![Maven Central](https://img.shields.io/maven-central/v/com.alibaba.csp/sentinel-core.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:com.alibaba.csp%20AND%20a:sentinel-core)
 [![License](https://img.shields.io/badge/license-Apache%202-4EB1BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)
 [![Gitter](https://badges.gitter.im/alibaba/Sentinel.svg)](https://gitter.im/alibaba/Sentinel)
-[![Maintainability](https://cloud.quality-gate.com/dashboard/api/badge?projectName=alibaba_Sentinel&branchName=master)](https://cloud.quality-gate.com/dashboard/branches/7825#overview)
 
 ## Introduction
 
@@ -61,7 +60,7 @@ If you're using Maven, just add the following dependency in `pom.xml`.
 <dependency>
     <groupId>com.alibaba.csp</groupId>
     <artifactId>sentinel-core</artifactId>
-    <version>1.8.2</version>
+    <version>1.8.3</version>
 </dependency>
 ```
 
diff --git a/doc/awesome-sentinel.md b/doc/awesome-sentinel.md
index 6ad8686a..68a1db37 100644
--- a/doc/awesome-sentinel.md
+++ b/doc/awesome-sentinel.md
@@ -40,7 +40,7 @@ You can also add to [sentinel-group/sentinel-awesome](https://github.com/sentine
 
 ## Blog Posts
 
-- [Sentinel 为 Dubbo 服务保驾护航](http://dubbo.apache.org/zh-cn/blog/sentinel-introduction-for-dubbo.html) by [Eric Zhao](https://github.com/sczyh30)
+- [Sentinel 为 Dubbo 服务保驾护航](https://dubbo.apache.org/zh/blog/2018/07/27/sentinel-为-dubbo-服务保驾护航) by [Eric Zhao](https://github.com/sczyh30)
 - [在生产环境中使用 Sentinel 控制台](https://github.com/alibaba/Sentinel/wiki/在生产环境中使用-Sentinel) by [Eric Zhao](https://github.com/sczyh30)
 - [Sentinel 与 Hystrix 的对比](https://sentinelguard.io/zh-cn/blog/sentinel-vs-hystrix.html) by [Eric Zhao](https://github.com/sczyh30)
 - [Guideline: 从 Hystrix 迁移到 Sentinel](https://sentinelguard.io/zh-cn/blog/guideline-migrate-from-hystrix-to-sentinel.html) by [Eric Zhao](https://github.com/sczyh30)
diff --git a/pom.xml b/pom.xml
index c46c48cd..6cd332d0 100755
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
 
     <groupId>com.alibaba.csp</groupId>
     <artifactId>sentinel-parent</artifactId>
-    <version>1.8.2</version>
+    <version>1.8.3</version>
     <packaging>pom</packaging>
 
     <name>${project.artifactId}</name>
@@ -164,7 +164,13 @@
                 <artifactId>sentinel-adapter</artifactId>
                 <version>${project.version}</version>
             </dependency>
-
+            
+            <dependency>
+                <groupId>com.alibaba.csp</groupId>
+                <artifactId>sentinel-metric-exporter</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            
             <dependency>
                 <groupId>com.alibaba</groupId>
                 <artifactId>fastjson</artifactId>
diff --git a/sentinel-adapter/pom.xml b/sentinel-adapter/pom.xml
index 57b6ce7b..be6426a4 100755
--- a/sentinel-adapter/pom.xml
+++ b/sentinel-adapter/pom.xml
@@ -7,7 +7,7 @@
     <parent>
         <groupId>com.alibaba.csp</groupId>
         <artifactId>sentinel-parent</artifactId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <artifactId>sentinel-adapter</artifactId>
     <packaging>pom</packaging>
diff --git a/sentinel-adapter/sentinel-apache-dubbo-adapter/pom.xml b/sentinel-adapter/sentinel-apache-dubbo-adapter/pom.xml
index 85df5b5c..c1d1893d 100644
--- a/sentinel-adapter/sentinel-apache-dubbo-adapter/pom.xml
+++ b/sentinel-adapter/sentinel-apache-dubbo-adapter/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-adapter</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -15,7 +15,7 @@
     <properties>
         <java.source.version>1.8</java.source.version>
         <java.target.version>1.8</java.target.version>
-        <apache.dubbo.version>2.7.5</apache.dubbo.version>
+        <apache.dubbo.version>2.7.13</apache.dubbo.version>
     </properties>
 
     <dependencies>
diff --git a/sentinel-adapter/sentinel-apache-httpclient-adapter/pom.xml b/sentinel-adapter/sentinel-apache-httpclient-adapter/pom.xml
index 2f02ac55..a5f29271 100644
--- a/sentinel-adapter/sentinel-apache-httpclient-adapter/pom.xml
+++ b/sentinel-adapter/sentinel-apache-httpclient-adapter/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-adapter</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-adapter/sentinel-api-gateway-adapter-common/pom.xml b/sentinel-adapter/sentinel-api-gateway-adapter-common/pom.xml
index c3ec83fb..540310cc 100644
--- a/sentinel-adapter/sentinel-api-gateway-adapter-common/pom.xml
+++ b/sentinel-adapter/sentinel-api-gateway-adapter-common/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-adapter</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-adapter/sentinel-dubbo-adapter/pom.xml b/sentinel-adapter/sentinel-dubbo-adapter/pom.xml
index 796973b3..20b5c2b8 100755
--- a/sentinel-adapter/sentinel-dubbo-adapter/pom.xml
+++ b/sentinel-adapter/sentinel-dubbo-adapter/pom.xml
@@ -6,7 +6,7 @@
     <parent>
         <groupId>com.alibaba.csp</groupId>
         <artifactId>sentinel-adapter</artifactId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>sentinel-dubbo-adapter</artifactId>
diff --git a/sentinel-adapter/sentinel-grpc-adapter/pom.xml b/sentinel-adapter/sentinel-grpc-adapter/pom.xml
index 53b8606d..aecb3aa7 100755
--- a/sentinel-adapter/sentinel-grpc-adapter/pom.xml
+++ b/sentinel-adapter/sentinel-grpc-adapter/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-adapter</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>sentinel-grpc-adapter</artifactId>
diff --git a/sentinel-adapter/sentinel-jax-rs-adapter/pom.xml b/sentinel-adapter/sentinel-jax-rs-adapter/pom.xml
index 0b6f7eb9..4af0f82f 100755
--- a/sentinel-adapter/sentinel-jax-rs-adapter/pom.xml
+++ b/sentinel-adapter/sentinel-jax-rs-adapter/pom.xml
@@ -6,7 +6,7 @@
     <parent>
         <groupId>com.alibaba.csp</groupId>
         <artifactId>sentinel-adapter</artifactId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
 
     <artifactId>sentinel-jax-rs-adapter</artifactId>
diff --git a/sentinel-adapter/sentinel-motan-adapter/pom.xml b/sentinel-adapter/sentinel-motan-adapter/pom.xml
index 158a0f3f..c9e1d626 100644
--- a/sentinel-adapter/sentinel-motan-adapter/pom.xml
+++ b/sentinel-adapter/sentinel-motan-adapter/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-adapter</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>sentinel-motan-adapter</artifactId>
diff --git a/sentinel-adapter/sentinel-okhttp-adapter/pom.xml b/sentinel-adapter/sentinel-okhttp-adapter/pom.xml
index 092568a7..021ea230 100644
--- a/sentinel-adapter/sentinel-okhttp-adapter/pom.xml
+++ b/sentinel-adapter/sentinel-okhttp-adapter/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-adapter</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-adapter/sentinel-quarkus-adapter/pom.xml b/sentinel-adapter/sentinel-quarkus-adapter/pom.xml
index 6c66785f..a6736c3e 100755
--- a/sentinel-adapter/sentinel-quarkus-adapter/pom.xml
+++ b/sentinel-adapter/sentinel-quarkus-adapter/pom.xml
@@ -6,7 +6,7 @@
     <parent>
         <groupId>com.alibaba.csp</groupId>
         <artifactId>sentinel-adapter</artifactId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
 
     <artifactId>sentinel-quarkus-adapter-parent</artifactId>
diff --git a/sentinel-adapter/sentinel-quarkus-adapter/sentinel-annotation-quarkus-adapter-deployment/pom.xml b/sentinel-adapter/sentinel-quarkus-adapter/sentinel-annotation-quarkus-adapter-deployment/pom.xml
index 25835482..a4ffbd47 100644
--- a/sentinel-adapter/sentinel-quarkus-adapter/sentinel-annotation-quarkus-adapter-deployment/pom.xml
+++ b/sentinel-adapter/sentinel-quarkus-adapter/sentinel-annotation-quarkus-adapter-deployment/pom.xml
@@ -6,7 +6,7 @@
     <parent>
         <groupId>com.alibaba.csp</groupId>
         <artifactId>sentinel-quarkus-adapter-parent</artifactId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
 
diff --git a/sentinel-adapter/sentinel-quarkus-adapter/sentinel-annotation-quarkus-adapter-runtime/pom.xml b/sentinel-adapter/sentinel-quarkus-adapter/sentinel-annotation-quarkus-adapter-runtime/pom.xml
index 61d77cb4..8021be40 100644
--- a/sentinel-adapter/sentinel-quarkus-adapter/sentinel-annotation-quarkus-adapter-runtime/pom.xml
+++ b/sentinel-adapter/sentinel-quarkus-adapter/sentinel-annotation-quarkus-adapter-runtime/pom.xml
@@ -6,7 +6,7 @@
     <parent>
         <groupId>com.alibaba.csp</groupId>
         <artifactId>sentinel-quarkus-adapter-parent</artifactId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
 
diff --git a/sentinel-adapter/sentinel-quarkus-adapter/sentinel-jax-rs-quarkus-adapter-deployment/pom.xml b/sentinel-adapter/sentinel-quarkus-adapter/sentinel-jax-rs-quarkus-adapter-deployment/pom.xml
index 566ab0c8..dd433c23 100644
--- a/sentinel-adapter/sentinel-quarkus-adapter/sentinel-jax-rs-quarkus-adapter-deployment/pom.xml
+++ b/sentinel-adapter/sentinel-quarkus-adapter/sentinel-jax-rs-quarkus-adapter-deployment/pom.xml
@@ -6,7 +6,7 @@
     <parent>
         <groupId>com.alibaba.csp</groupId>
         <artifactId>sentinel-quarkus-adapter-parent</artifactId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
 
diff --git a/sentinel-adapter/sentinel-quarkus-adapter/sentinel-jax-rs-quarkus-adapter-runtime/pom.xml b/sentinel-adapter/sentinel-quarkus-adapter/sentinel-jax-rs-quarkus-adapter-runtime/pom.xml
index 1e7de01a..55f14b9e 100644
--- a/sentinel-adapter/sentinel-quarkus-adapter/sentinel-jax-rs-quarkus-adapter-runtime/pom.xml
+++ b/sentinel-adapter/sentinel-quarkus-adapter/sentinel-jax-rs-quarkus-adapter-runtime/pom.xml
@@ -6,7 +6,7 @@
     <parent>
         <groupId>com.alibaba.csp</groupId>
         <artifactId>sentinel-quarkus-adapter-parent</artifactId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
 
diff --git a/sentinel-adapter/sentinel-quarkus-adapter/sentinel-native-image-quarkus-adapter-deployment/pom.xml b/sentinel-adapter/sentinel-quarkus-adapter/sentinel-native-image-quarkus-adapter-deployment/pom.xml
index ed348c80..55113e1e 100644
--- a/sentinel-adapter/sentinel-quarkus-adapter/sentinel-native-image-quarkus-adapter-deployment/pom.xml
+++ b/sentinel-adapter/sentinel-quarkus-adapter/sentinel-native-image-quarkus-adapter-deployment/pom.xml
@@ -6,7 +6,7 @@
     <parent>
         <groupId>com.alibaba.csp</groupId>
         <artifactId>sentinel-quarkus-adapter-parent</artifactId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
 
diff --git a/sentinel-adapter/sentinel-quarkus-adapter/sentinel-native-image-quarkus-adapter-runtime/pom.xml b/sentinel-adapter/sentinel-quarkus-adapter/sentinel-native-image-quarkus-adapter-runtime/pom.xml
index 5efa9274..a67d4a5c 100644
--- a/sentinel-adapter/sentinel-quarkus-adapter/sentinel-native-image-quarkus-adapter-runtime/pom.xml
+++ b/sentinel-adapter/sentinel-quarkus-adapter/sentinel-native-image-quarkus-adapter-runtime/pom.xml
@@ -6,7 +6,7 @@
     <parent>
         <groupId>com.alibaba.csp</groupId>
         <artifactId>sentinel-quarkus-adapter-parent</artifactId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
         <relativePath>../pom.xml</relativePath>
     </parent>
 
diff --git a/sentinel-adapter/sentinel-reactor-adapter/pom.xml b/sentinel-adapter/sentinel-reactor-adapter/pom.xml
index dd53a1e4..d49f33a5 100644
--- a/sentinel-adapter/sentinel-reactor-adapter/pom.xml
+++ b/sentinel-adapter/sentinel-reactor-adapter/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-adapter</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-adapter/sentinel-sofa-rpc-adapter/pom.xml b/sentinel-adapter/sentinel-sofa-rpc-adapter/pom.xml
index 8e7afa47..3ff05147 100644
--- a/sentinel-adapter/sentinel-sofa-rpc-adapter/pom.xml
+++ b/sentinel-adapter/sentinel-sofa-rpc-adapter/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-adapter</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-adapter/sentinel-spring-cloud-gateway-adapter/pom.xml b/sentinel-adapter/sentinel-spring-cloud-gateway-adapter/pom.xml
index 8cd84f70..d5766293 100644
--- a/sentinel-adapter/sentinel-spring-cloud-gateway-adapter/pom.xml
+++ b/sentinel-adapter/sentinel-spring-cloud-gateway-adapter/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-adapter</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-adapter/sentinel-spring-cloud-gateway-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/sc/api/GatewayApiMatcherManager.java b/sentinel-adapter/sentinel-spring-cloud-gateway-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/sc/api/GatewayApiMatcherManager.java
index 5c1567ca..7ba47b66 100644
--- a/sentinel-adapter/sentinel-spring-cloud-gateway-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/sc/api/GatewayApiMatcherManager.java
+++ b/sentinel-adapter/sentinel-spring-cloud-gateway-adapter/src/main/java/com/alibaba/csp/sentinel/adapter/gateway/sc/api/GatewayApiMatcherManager.java
@@ -15,23 +15,23 @@
  */
 package com.alibaba.csp.sentinel.adapter.gateway.sc.api;
 
+import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition;
+import com.alibaba.csp.sentinel.adapter.gateway.sc.api.matcher.WebExchangeApiMatcher;
+
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
 import java.util.stream.Collectors;
 
-import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition;
-import com.alibaba.csp.sentinel.adapter.gateway.sc.api.matcher.WebExchangeApiMatcher;
-
 /**
  * @author Eric Zhao
  * @since 1.6.0
  */
 public final class GatewayApiMatcherManager {
 
-    private static final Map<String, WebExchangeApiMatcher> API_MATCHER_MAP = new ConcurrentHashMap<>();
+    private static volatile Map<String, WebExchangeApiMatcher> API_MATCHER_MAP = new HashMap<>();
 
     public static Map<String, WebExchangeApiMatcher> getApiMatcherMap() {
         return Collections.unmodifiableMap(API_MATCHER_MAP);
@@ -50,15 +50,12 @@ public final class GatewayApiMatcherManager {
     }
 
     static synchronized void loadApiDefinitions(/*@Valid*/ Set<ApiDefinition> definitions) {
-        if (definitions == null || definitions.isEmpty()) {
-            API_MATCHER_MAP.clear();
-            return;
+        Map<String, WebExchangeApiMatcher> apiMatcherMap = new HashMap<>();
+        for (ApiDefinition definition : definitions) {
+            apiMatcherMap.put(definition.getApiName(), new WebExchangeApiMatcher(definition));
         }
-        definitions.forEach(GatewayApiMatcherManager::addApiDefinition);
-    }
 
-    static void addApiDefinition(ApiDefinition definition) {
-        API_MATCHER_MAP.put(definition.getApiName(), new WebExchangeApiMatcher(definition));
+        API_MATCHER_MAP = apiMatcherMap;
     }
 
     private GatewayApiMatcherManager() {}
diff --git a/sentinel-adapter/sentinel-spring-webflux-adapter/pom.xml b/sentinel-adapter/sentinel-spring-webflux-adapter/pom.xml
index b39cfaa7..07eaad14 100644
--- a/sentinel-adapter/sentinel-spring-webflux-adapter/pom.xml
+++ b/sentinel-adapter/sentinel-spring-webflux-adapter/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-adapter</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-adapter/sentinel-spring-webmvc-adapter/pom.xml b/sentinel-adapter/sentinel-spring-webmvc-adapter/pom.xml
index c6dbee65..73b7eff9 100644
--- a/sentinel-adapter/sentinel-spring-webmvc-adapter/pom.xml
+++ b/sentinel-adapter/sentinel-spring-webmvc-adapter/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <groupId>com.alibaba.csp</groupId>
         <artifactId>sentinel-adapter</artifactId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-adapter/sentinel-web-servlet/pom.xml b/sentinel-adapter/sentinel-web-servlet/pom.xml
index dd7b660d..7c3eccce 100755
--- a/sentinel-adapter/sentinel-web-servlet/pom.xml
+++ b/sentinel-adapter/sentinel-web-servlet/pom.xml
@@ -6,7 +6,7 @@
     <parent>
         <groupId>com.alibaba.csp</groupId>
         <artifactId>sentinel-adapter</artifactId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
 
     <artifactId>sentinel-web-servlet</artifactId>
diff --git a/sentinel-adapter/sentinel-zuul-adapter/pom.xml b/sentinel-adapter/sentinel-zuul-adapter/pom.xml
index da37725c..ed972c8a 100755
--- a/sentinel-adapter/sentinel-zuul-adapter/pom.xml
+++ b/sentinel-adapter/sentinel-zuul-adapter/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-adapter</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>sentinel-zuul-adapter</artifactId>
diff --git a/sentinel-adapter/sentinel-zuul2-adapter/pom.xml b/sentinel-adapter/sentinel-zuul2-adapter/pom.xml
index 230a8976..3e885c47 100644
--- a/sentinel-adapter/sentinel-zuul2-adapter/pom.xml
+++ b/sentinel-adapter/sentinel-zuul2-adapter/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-adapter</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-benchmark/pom.xml b/sentinel-benchmark/pom.xml
index 0d35de33..deb427fc 100644
--- a/sentinel-benchmark/pom.xml
+++ b/sentinel-benchmark/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-parent</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-cluster/pom.xml b/sentinel-cluster/pom.xml
index 2b42a860..e776c075 100644
--- a/sentinel-cluster/pom.xml
+++ b/sentinel-cluster/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-parent</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <packaging>pom</packaging>
diff --git a/sentinel-cluster/sentinel-cluster-client-default/pom.xml b/sentinel-cluster/sentinel-cluster-client-default/pom.xml
index fca8abd8..3a479a57 100644
--- a/sentinel-cluster/sentinel-cluster-client-default/pom.xml
+++ b/sentinel-cluster/sentinel-cluster-client-default/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-cluster</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-cluster/sentinel-cluster-common-default/pom.xml b/sentinel-cluster/sentinel-cluster-common-default/pom.xml
index 36fc6d72..a497f181 100644
--- a/sentinel-cluster/sentinel-cluster-common-default/pom.xml
+++ b/sentinel-cluster/sentinel-cluster-common-default/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-cluster</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-cluster/sentinel-cluster-server-default/pom.xml b/sentinel-cluster/sentinel-cluster-server-default/pom.xml
index db2ddb15..6dc62b96 100644
--- a/sentinel-cluster/sentinel-cluster-server-default/pom.xml
+++ b/sentinel-cluster/sentinel-cluster-server-default/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-cluster</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-cluster/sentinel-cluster-server-envoy-rls/pom.xml b/sentinel-cluster/sentinel-cluster-server-envoy-rls/pom.xml
index d6fbec75..1186c374 100644
--- a/sentinel-cluster/sentinel-cluster-server-envoy-rls/pom.xml
+++ b/sentinel-cluster/sentinel-cluster-server-envoy-rls/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-cluster</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-cluster/sentinel-cluster-server-envoy-rls/sample/k8s/README.md b/sentinel-cluster/sentinel-cluster-server-envoy-rls/sample/k8s/README.md
index 3fd58ba8..245e43a8 100644
--- a/sentinel-cluster/sentinel-cluster-server-envoy-rls/sample/k8s/README.md
+++ b/sentinel-cluster/sentinel-cluster-server-envoy-rls/sample/k8s/README.md
@@ -91,6 +91,12 @@ After preparing the yaml template, you may deploy the Envoy instance:
 kubectl apply -f sample/k8s/envoy.yml
 ```
 
+for v3 api：
+
+```bash
+kubectl apply -f sample/k8s/envoy-v3-api.yml
+```
+
 ## Test the rate limiting
 
 Now it's show time! We could visit the URL `envoy-service:10000/json` in K8S pods.
diff --git a/sentinel-cluster/sentinel-cluster-server-envoy-rls/sample/k8s/envoy-v3-api.yaml b/sentinel-cluster/sentinel-cluster-server-envoy-rls/sample/k8s/envoy-v3-api.yaml
new file mode 100644
index 00000000..124c9864
--- /dev/null
+++ b/sentinel-cluster/sentinel-cluster-server-envoy-rls/sample/k8s/envoy-v3-api.yaml
@@ -0,0 +1,141 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: envoy-cm-17
+data:
+  envoy-yml: |-
+    admin:
+      access_log_path: /tmp/admin_access.log
+      address:
+        socket_address:
+          protocol: TCP
+          address: 127.0.0.1
+          port_value: 9901
+    static_resources:
+      listeners:
+      - name: listener_0
+        address:
+          socket_address:
+            protocol: TCP
+            address: 0.0.0.0
+            port_value: 10000
+        filter_chains:
+        - filters:
+          - name: envoy.filters.network.http_connection_manager
+            typed_config:
+              "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
+              stat_prefix: ingress_http
+              route_config:
+                name: local_route
+                virtual_hosts:
+                - name: local_service
+                  domains: ["*"]
+                  routes:
+                  - match:
+                      prefix: "/"
+                    route:
+                      cluster: service_httpbin
+                    typed_per_filter_config:
+                      envoy.filters.http.dynamic_forward_proxy:
+                        "@type": type.googleapis.com/envoy.extensions.filters.http.dynamic_forward_proxy.v3.PerRouteConfig
+                        host_rewrite_literal: httpbin.org
+                  rate_limits:
+                    - stage: 0
+                      actions:
+                        - {destination_cluster: {}}
+              http_filters:
+                - name: envoy.filters.http.ratelimit
+                  typed_config:
+                    "@type": type.googleapis.com/envoy.extensions.filters.http.ratelimit.v3.RateLimit
+                    domain: foo
+                    request_type: external
+                    failure_mode_deny: false
+                    stage: 0
+                    rate_limit_service:
+                      grpc_service:
+                        envoy_grpc:
+                          cluster_name: rate_limit_cluster
+                        timeout: 2s
+                      transport_api_version: V3
+                - name: envoy.filters.http.router
+                  typed_config:
+                    "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
+      clusters:
+      - name: service_httpbin
+        connect_timeout: 0.5s
+        type: LOGICAL_DNS
+        # Comment out the following line to test on v6 networks
+        dns_lookup_family: V4_ONLY
+        lb_policy: ROUND_ROBIN
+        load_assignment:
+          cluster_name: service_httpbin
+          endpoints:
+          - lb_endpoints:
+            - endpoint:
+                address:
+                  socket_address:
+                    address: httpbin.org
+                    port_value: 80
+      - name: rate_limit_cluster
+        type: STRICT_DNS
+        connect_timeout: 10s
+        lb_policy: ROUND_ROBIN
+        http2_protocol_options: {}
+        load_assignment:
+          cluster_name: rate_limit_cluster
+          endpoints:
+          - lb_endpoints:
+            - endpoint:
+                address:
+                  socket_address:
+                    address: sentinel-rls-service
+                    port_value: 10245
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: envoy-deployment-basic-17
+  labels:
+    app: envoy-17
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: envoy-17
+  template:
+    metadata:
+      labels:
+        app: envoy-17
+    spec:
+      containers:
+        - name: envoy
+          image: envoyproxy/envoy:v1.17.3
+          ports:
+            - containerPort: 10000
+          command: ["envoy"]
+          args: ["-c", "/tmp/envoy/envoy.yaml"]
+          volumeMounts:
+            - name: envoy-config
+              mountPath: /tmp/envoy
+      volumes:
+        - name: envoy-config
+          configMap:
+            name: envoy-cm-17
+            items:
+              - key: envoy-yml
+                path: envoy.yaml
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: envoy-service-17
+  labels:
+    name: envoy-service-17
+spec:
+  type: NodePort
+  ports:
+    - port: 10000
+      targetPort: 10000
+      protocol: TCP
+  selector:
+    app: envoy-17
diff --git a/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/java/com/alibaba/csp/sentinel/cluster/server/envoy/rls/SentinelRlsGrpcServer.java b/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/java/com/alibaba/csp/sentinel/cluster/server/envoy/rls/SentinelRlsGrpcServer.java
index 459540ad..4f49edb0 100644
--- a/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/java/com/alibaba/csp/sentinel/cluster/server/envoy/rls/SentinelRlsGrpcServer.java
+++ b/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/java/com/alibaba/csp/sentinel/cluster/server/envoy/rls/SentinelRlsGrpcServer.java
@@ -31,7 +31,9 @@ public class SentinelRlsGrpcServer {
 
     public SentinelRlsGrpcServer(int port) {
         ServerBuilder<?> builder = ServerBuilder.forPort(port)
+            .addService(new com.alibaba.csp.sentinel.cluster.server.envoy.rls.service.v3.SentinelEnvoyRlsServiceImpl())
             .addService(new SentinelEnvoyRlsServiceImpl());
+
         server = builder.build();
     }
 
diff --git a/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/java/com/alibaba/csp/sentinel/cluster/server/envoy/rls/service/v3/SentinelEnvoyRlsServiceImpl.java b/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/java/com/alibaba/csp/sentinel/cluster/server/envoy/rls/service/v3/SentinelEnvoyRlsServiceImpl.java
new file mode 100644
index 00000000..f776c204
--- /dev/null
+++ b/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/java/com/alibaba/csp/sentinel/cluster/server/envoy/rls/service/v3/SentinelEnvoyRlsServiceImpl.java
@@ -0,0 +1,118 @@
+package com.alibaba.csp.sentinel.cluster.server.envoy.rls.service.v3;
+
+import com.alibaba.csp.sentinel.cluster.TokenResult;
+import com.alibaba.csp.sentinel.cluster.TokenResultStatus;
+import com.alibaba.csp.sentinel.cluster.flow.rule.ClusterFlowRuleManager;
+import com.alibaba.csp.sentinel.cluster.server.envoy.rls.flow.SimpleClusterFlowChecker;
+import com.alibaba.csp.sentinel.cluster.server.envoy.rls.log.RlsAccessLogger;
+import com.alibaba.csp.sentinel.cluster.server.envoy.rls.rule.EnvoySentinelRuleConverter;
+import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
+import com.alibaba.csp.sentinel.util.function.Tuple2;
+import com.google.protobuf.TextFormat;
+import io.envoyproxy.envoy.extensions.common.ratelimit.v3.RateLimitDescriptor;
+import io.envoyproxy.envoy.service.ratelimit.v3.RateLimitRequest;
+import io.envoyproxy.envoy.service.ratelimit.v3.RateLimitResponse;
+import io.envoyproxy.envoy.service.ratelimit.v3.RateLimitResponse.Code;
+import io.envoyproxy.envoy.service.ratelimit.v3.RateLimitResponse.RateLimit;
+import io.envoyproxy.envoy.service.ratelimit.v3.RateLimitResponse.DescriptorStatus;
+import io.envoyproxy.envoy.service.ratelimit.v3.RateLimitServiceGrpc;
+import io.grpc.stub.StreamObserver;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.alibaba.csp.sentinel.cluster.server.envoy.rls.rule.EnvoySentinelRuleConverter.SEPARATOR;
+
+/**
+ * gRPC限流入口，实现envoy rls v3 api
+ *
+ * @author Winjay chan
+ * @date 2021/8/4
+ */
+public class SentinelEnvoyRlsServiceImpl extends RateLimitServiceGrpc.RateLimitServiceImplBase {
+    @Override
+    public void shouldRateLimit(RateLimitRequest request, StreamObserver<RateLimitResponse> responseObserver) {
+        int acquireCount = request.getHitsAddend();
+        if (acquireCount < 0) {
+            responseObserver.onError(new IllegalArgumentException(
+                    "acquireCount should be positive, but actual: " + acquireCount));
+            return;
+        }
+        if (acquireCount == 0) {
+            // Not present, use the default "1" by default.
+            acquireCount = 1;
+        }
+
+        String domain = request.getDomain();
+        boolean blocked = false;
+        List<DescriptorStatus> statusList = new ArrayList<>(request.getDescriptorsCount());
+        for (RateLimitDescriptor descriptor : request.getDescriptorsList()) {
+            Tuple2<FlowRule, TokenResult> t = checkToken(domain, descriptor, acquireCount);
+            TokenResult r = t.r2;
+
+            printAccessLogIfNecessary(domain, descriptor, r);
+
+            if (r.getStatus() == TokenResultStatus.NO_RULE_EXISTS) {
+                // If the rule of the descriptor is absent, the request will pass directly.
+                r.setStatus(TokenResultStatus.OK);
+            }
+
+            if (!blocked && r.getStatus() != TokenResultStatus.OK) {
+                blocked = true;
+            }
+
+            Code statusCode = r.getStatus() == TokenResultStatus.OK ? Code.OK : Code.OVER_LIMIT;
+            DescriptorStatus.Builder descriptorStatusBuilder = DescriptorStatus.newBuilder()
+                    .setCode(statusCode);
+            if (t.r1 != null) {
+                descriptorStatusBuilder
+                        .setCurrentLimit(RateLimit.newBuilder().setUnit(RateLimit.Unit.SECOND)
+                                .setRequestsPerUnit((int)t.r1.getCount())
+                                .build())
+                        .setLimitRemaining(r.getRemaining());
+            }
+            statusList.add(descriptorStatusBuilder.build());
+        }
+
+        Code overallStatus = blocked ? Code.OVER_LIMIT :Code.OK;
+        RateLimitResponse response = RateLimitResponse.newBuilder()
+                .setOverallCode(overallStatus)
+                .addAllStatuses(statusList)
+                .build();
+
+        responseObserver.onNext(response);
+        responseObserver.onCompleted();
+    }
+
+    private void printAccessLogIfNecessary(String domain, RateLimitDescriptor descriptor, TokenResult result) {
+        if (!RlsAccessLogger.isEnabled()) {
+            return;
+        }
+        String message = new StringBuilder("[RlsAccessLog] domain=").append(domain)
+                .append(", descriptor=").append(TextFormat.shortDebugString(descriptor))
+                .append(", checkStatus=").append(result.getStatus())
+                .append(", remaining=").append(result.getRemaining())
+                .toString();
+        RlsAccessLogger.log(message);
+    }
+
+    protected Tuple2<FlowRule, TokenResult> checkToken(String domain, RateLimitDescriptor descriptor, int acquireCount) {
+        long ruleId = EnvoySentinelRuleConverter.generateFlowId(generateKey(domain, descriptor));
+
+        FlowRule rule = ClusterFlowRuleManager.getFlowRuleById(ruleId);
+        if (rule == null) {
+            // Pass if the target rule is absent.
+            return Tuple2.of(null, new TokenResult(TokenResultStatus.NO_RULE_EXISTS));
+        }
+        // If the rule is present, it should be valid.
+        return Tuple2.of(rule, SimpleClusterFlowChecker.acquireClusterToken(rule, acquireCount));
+    }
+
+    private String generateKey(String domain, RateLimitDescriptor descriptor) {
+        StringBuilder sb = new StringBuilder(domain);
+        for (RateLimitDescriptor.Entry resource : descriptor.getEntriesList()) {
+            sb.append(SEPARATOR).append(resource.getKey()).append(SEPARATOR).append(resource.getValue());
+        }
+        return sb.toString();
+    }
+}
diff --git a/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/envoy/config/core/v3/base.proto b/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/envoy/config/core/v3/base.proto
new file mode 100644
index 00000000..48cd25fa
--- /dev/null
+++ b/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/envoy/config/core/v3/base.proto
@@ -0,0 +1,33 @@
+syntax = "proto3";
+
+package envoy.config.core.v3;
+
+import "udpa/annotations/status.proto";
+import "udpa/annotations/versioning.proto";
+import "validate/validate.proto";
+
+option java_package = "io.envoyproxy.envoy.config.core.v3";
+option java_outer_classname = "BaseProto";
+option java_multiple_files = true;
+option (udpa.annotations.file_status).package_version_status = ACTIVE;
+
+
+
+// Header name/value pair.
+message HeaderValue {
+  option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.core.HeaderValue";
+
+  // Header name.
+  string key = 1
+      [(validate.rules).string =
+           {min_len: 1 max_bytes: 16384 well_known_regex: HTTP_HEADER_NAME strict: false}];
+
+  // Header value.
+  //
+  // The same :ref:`format specifier <config_access_log_format>` as used for
+  // :ref:`HTTP access logging <config_access_log>` applies here, however
+  // unknown header values are replaced with the empty string instead of `-`.
+  string value = 2 [
+    (validate.rules).string = {max_bytes: 16384 well_known_regex: HTTP_HEADER_VALUE strict: false}
+  ];
+}
diff --git a/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/envoy/extensions/common/ratelimit/v3/ratelimit.proto b/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/envoy/extensions/common/ratelimit/v3/ratelimit.proto
new file mode 100644
index 00000000..1047582d
--- /dev/null
+++ b/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/envoy/extensions/common/ratelimit/v3/ratelimit.proto
@@ -0,0 +1,94 @@
+syntax = "proto3";
+
+package envoy.extensions.common.ratelimit.v3;
+
+import "envoy/type/v3/ratelimit_unit.proto";
+//
+import "udpa/annotations/status.proto";
+import "udpa/annotations/versioning.proto";
+import "validate/validate.proto";
+
+option java_package = "io.envoyproxy.envoy.extensions.common.ratelimit.v3";
+option java_outer_classname = "RatelimitProto";
+option java_multiple_files = true;
+option (udpa.annotations.file_status).package_version_status = ACTIVE;
+
+// [#protodoc-title: Common rate limit components]
+
+// A RateLimitDescriptor is a list of hierarchical entries that are used by the service to
+// determine the final rate limit key and overall allowed limit. Here are some examples of how
+// they might be used for the domain "envoy".
+//
+// .. code-block:: cpp
+//
+//   ["authenticated": "false"], ["remote_address": "10.0.0.1"]
+//
+// What it does: Limits all unauthenticated traffic for the IP address 10.0.0.1. The
+// configuration supplies a default limit for the *remote_address* key. If there is a desire to
+// raise the limit for 10.0.0.1 or block it entirely it can be specified directly in the
+// configuration.
+//
+// .. code-block:: cpp
+//
+//   ["authenticated": "false"], ["path": "/foo/bar"]
+//
+// What it does: Limits all unauthenticated traffic globally for a specific path (or prefix if
+// configured that way in the service).
+//
+// .. code-block:: cpp
+//
+//   ["authenticated": "false"], ["path": "/foo/bar"], ["remote_address": "10.0.0.1"]
+//
+// What it does: Limits unauthenticated traffic to a specific path for a specific IP address.
+// Like (1) we can raise/block specific IP addresses if we want with an override configuration.
+//
+// .. code-block:: cpp
+//
+//   ["authenticated": "true"], ["client_id": "foo"]
+//
+// What it does: Limits all traffic for an authenticated client "foo"
+//
+// .. code-block:: cpp
+//
+//   ["authenticated": "true"], ["client_id": "foo"], ["path": "/foo/bar"]
+//
+// What it does: Limits traffic to a specific path for an authenticated client "foo"
+//
+// The idea behind the API is that (1)/(2)/(3) and (4)/(5) can be sent in 1 request if desired.
+// This enables building complex application scenarios with a generic backend.
+//
+// Optionally the descriptor can contain a limit override under a "limit" key, that specifies
+// the number of requests per unit to use instead of the number configured in the
+// rate limiting service.
+message RateLimitDescriptor {
+  option (udpa.annotations.versioning).previous_message_type =
+      "envoy.api.v2.ratelimit.RateLimitDescriptor";
+
+  message Entry {
+    option (udpa.annotations.versioning).previous_message_type =
+        "envoy.api.v2.ratelimit.RateLimitDescriptor.Entry";
+
+    // Descriptor key.
+    string key = 1 [(validate.rules).string = {min_len: 1}];
+
+    // Descriptor value.
+    string value = 2 [(validate.rules).string = {min_len: 1}];
+  }
+
+  // Override rate limit to apply to this descriptor instead of the limit
+  // configured in the rate limit service. See :ref:`rate limit override
+  // <config_http_filters_rate_limit_rate_limit_override>` for more information.
+  message RateLimitOverride {
+    // The number of requests per unit of time.
+    uint32 requests_per_unit = 1;
+
+    // The unit of time.
+    type.v3.RateLimitUnit unit = 2 [(validate.rules).enum = {defined_only: true}];
+  }
+
+  // Descriptor entries.
+  repeated Entry entries = 1 [(validate.rules).repeated = {min_items: 1}];
+
+  // Optional rate limit override to supply to the ratelimit service.
+  RateLimitOverride limit = 2;
+}
diff --git a/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/envoy/service/ratelimit/v3/rls.proto b/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/envoy/service/ratelimit/v3/rls.proto
new file mode 100644
index 00000000..c2823cf7
--- /dev/null
+++ b/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/envoy/service/ratelimit/v3/rls.proto
@@ -0,0 +1,196 @@
+syntax = "proto3";
+
+package envoy.service.ratelimit.v3;
+
+import "envoy/config/core/v3/base.proto";
+import "envoy/extensions/common/ratelimit/v3/ratelimit.proto";
+
+import "google/protobuf/duration.proto";
+import "google/protobuf/struct.proto";
+import "google/protobuf/timestamp.proto";
+//
+import "udpa/annotations/status.proto";
+import "udpa/annotations/versioning.proto";
+import "validate/validate.proto";
+
+option java_package = "io.envoyproxy.envoy.service.ratelimit.v3";
+option java_outer_classname = "RlsProto";
+option java_multiple_files = true;
+option java_generic_services = true;
+option (udpa.annotations.file_status).package_version_status = ACTIVE;
+
+// [#protodoc-title: Rate Limit Service (RLS)]
+
+service RateLimitService {
+  // Determine whether rate limiting should take place.
+  rpc ShouldRateLimit(RateLimitRequest) returns (RateLimitResponse) {
+  }
+}
+
+// Main message for a rate limit request. The rate limit service is designed to be fully generic
+// in the sense that it can operate on arbitrary hierarchical key/value pairs. The loaded
+// configuration will parse the request and find the most specific limit to apply. In addition,
+// a RateLimitRequest can contain multiple "descriptors" to limit on. When multiple descriptors
+// are provided, the server will limit on *ALL* of them and return an OVER_LIMIT response if any
+// of them are over limit. This enables more complex application level rate limiting scenarios
+// if desired.
+message RateLimitRequest {
+  option (udpa.annotations.versioning).previous_message_type =
+      "envoy.service.ratelimit.v2.RateLimitRequest";
+
+  // All rate limit requests must specify a domain. This enables the configuration to be per
+  // application without fear of overlap. E.g., "envoy".
+  string domain = 1;
+
+  // All rate limit requests must specify at least one RateLimitDescriptor. Each descriptor is
+  // processed by the service (see below). If any of the descriptors are over limit, the entire
+  // request is considered to be over limit.
+  repeated envoy.extensions.common.ratelimit.v3.RateLimitDescriptor descriptors = 2;
+
+  // Rate limit requests can optionally specify the number of hits a request adds to the matched
+  // limit. If the value is not set in the message, a request increases the matched limit by 1.
+  uint32 hits_addend = 3;
+}
+
+// A response from a ShouldRateLimit call.
+// [#next-free-field: 7]
+message RateLimitResponse {
+  option (udpa.annotations.versioning).previous_message_type =
+      "envoy.service.ratelimit.v2.RateLimitResponse";
+
+  enum Code {
+    // The response code is not known.
+    UNKNOWN = 0;
+
+    // The response code to notify that the number of requests are under limit.
+    OK = 1;
+
+    // The response code to notify that the number of requests are over limit.
+    OVER_LIMIT = 2;
+  }
+
+  // Defines an actual rate limit in terms of requests per unit of time and the unit itself.
+  message RateLimit {
+    option (udpa.annotations.versioning).previous_message_type =
+        "envoy.service.ratelimit.v2.RateLimitResponse.RateLimit";
+
+    // Identifies the unit of of time for rate limit.
+    // [#comment: replace by envoy/type/v3/ratelimit_unit.proto in v4]
+    enum Unit {
+      // The time unit is not known.
+      UNKNOWN = 0;
+
+      // The time unit representing a second.
+      SECOND = 1;
+
+      // The time unit representing a minute.
+      MINUTE = 2;
+
+      // The time unit representing an hour.
+      HOUR = 3;
+
+      // The time unit representing a day.
+      DAY = 4;
+    }
+
+    // A name or description of this limit.
+    string name = 3;
+
+    // The number of requests per unit of time.
+    uint32 requests_per_unit = 1;
+
+    // The unit of time.
+    Unit unit = 2;
+  }
+
+  // Cacheable quota for responses, see documentation for the :ref:`quota
+  // <envoy_v3_api_field_service.ratelimit.v3.RateLimitResponse.DescriptorStatus.quota>` field.
+  // [#not-implemented-hide:]
+  message Quota {
+    // Number of matching requests granted in quota. Must be 1 or more.
+    uint32 requests = 1 [(validate.rules).uint32 = {gt: 0}];
+
+    oneof expiration_specifier {
+      // Point in time at which the quota expires.
+      google.protobuf.Timestamp valid_until = 2;
+    }
+  }
+
+  // [#next-free-field: 6]
+  message DescriptorStatus {
+    option (udpa.annotations.versioning).previous_message_type =
+        "envoy.service.ratelimit.v2.RateLimitResponse.DescriptorStatus";
+
+    // The response code for an individual descriptor.
+    Code code = 1;
+
+    // The current limit as configured by the server. Useful for debugging, etc.
+    RateLimit current_limit = 2;
+
+    // The limit remaining in the current time unit.
+    uint32 limit_remaining = 3;
+
+    // Duration until reset of the current limit window.
+    google.protobuf.Duration duration_until_reset = 4;
+
+    // Quota granted for the descriptor. This is a certain number of requests over a period of time.
+    // The client may cache this result and apply the effective RateLimitResponse to future matching
+    // requests containing a matching descriptor without querying rate limit service.
+    //
+    // Quota is available for a request if its descriptor set has cached quota available for all
+    // descriptors.
+    //
+    // If quota is available, a RLS request will not be made and the quota will be reduced by 1 for
+    // all matching descriptors.
+    //
+    // If there is not sufficient quota, there are three cases:
+    // 1. A cached entry exists for a RLS descriptor that is out-of-quota, but not expired.
+    //    In this case, the request will be treated as OVER_LIMIT.
+    // 2. Some RLS descriptors have a cached entry that has valid quota but some RLS descriptors
+    //    have no cached entry. This will trigger a new RLS request.
+    //    When the result is returned, a single unit will be consumed from the quota for all
+    //    matching descriptors.
+    //    If the server did not provide a quota, such as the quota message is empty for some of
+    //    the descriptors, then the request admission is determined by the
+    //    :ref:`overall_code <envoy_v3_api_field_service.ratelimit.v3.RateLimitResponse.overall_code>`.
+    // 3. All RLS descriptors lack a cached entry, this will trigger a new RLS request,
+    //    When the result is returned, a single unit will be consumed from the quota for all
+    //    matching descriptors.
+    //    If the server did not provide a quota, such as the quota message is empty for some of
+    //    the descriptors, then the request admission is determined by the
+    //    :ref:`overall_code <envoy_v3_api_field_service.ratelimit.v3.RateLimitResponse.overall_code>`.
+    //
+    // When quota expires due to timeout, a new RLS request will also be made.
+    // The implementation may choose to preemptively query the rate limit server for more quota on or
+    // before expiration or before the available quota runs out.
+    // [#not-implemented-hide:]
+    Quota quota = 5;
+  }
+
+  // The overall response code which takes into account all of the descriptors that were passed
+  // in the RateLimitRequest message.
+  Code overall_code = 1;
+
+  // A list of DescriptorStatus messages which matches the length of the descriptor list passed
+  // in the RateLimitRequest. This can be used by the caller to determine which individual
+  // descriptors failed and/or what the currently configured limits are for all of them.
+  repeated DescriptorStatus statuses = 2;
+
+  // A list of headers to add to the response
+  repeated config.core.v3.HeaderValue response_headers_to_add = 3;
+
+  // A list of headers to add to the request when forwarded
+  repeated config.core.v3.HeaderValue request_headers_to_add = 4;
+
+  // A response body to send to the downstream client when the response code is not OK.
+  bytes raw_body = 5;
+
+  // Optional response metadata that will be emitted as dynamic metadata to be consumed by the next
+  // filter. This metadata lives in a namespace specified by the canonical name of extension filter
+  // that requires it:
+  //
+  // - :ref:`envoy.filters.http.ratelimit <config_http_filters_ratelimit_dynamic_metadata>` for HTTP filter.
+  // - :ref:`envoy.filters.network.ratelimit <config_network_filters_ratelimit_dynamic_metadata>` for network filter.
+  // - :ref:`envoy.filters.thrift.rate_limit <config_thrift_filters_rate_limit_dynamic_metadata>` for Thrift filter.
+  google.protobuf.Struct dynamic_metadata = 6;
+}
\ No newline at end of file
diff --git a/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/envoy/type/v3/ratelimit_unit.proto b/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/envoy/type/v3/ratelimit_unit.proto
new file mode 100644
index 00000000..a3fb27ff
--- /dev/null
+++ b/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/envoy/type/v3/ratelimit_unit.proto
@@ -0,0 +1,30 @@
+syntax = "proto3";
+
+package envoy.type.v3;
+
+import "udpa/annotations/status.proto";
+
+option java_package = "io.envoyproxy.envoy.type.v3";
+option java_outer_classname = "RatelimitUnitProto";
+option java_multiple_files = true;
+option (udpa.annotations.file_status).package_version_status = ACTIVE;
+
+// [#protodoc-title: Ratelimit Time Unit]
+
+// Identifies the unit of of time for rate limit.
+enum RateLimitUnit {
+  // The time unit is not known.
+  UNKNOWN = 0;
+
+  // The time unit representing a second.
+  SECOND = 1;
+
+  // The time unit representing a minute.
+  MINUTE = 2;
+
+  // The time unit representing an hour.
+  HOUR = 3;
+
+  // The time unit representing a day.
+  DAY = 4;
+}
diff --git a/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/udpa/annotations/BUILD b/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/udpa/annotations/BUILD
new file mode 100644
index 00000000..b8846b03
--- /dev/null
+++ b/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/udpa/annotations/BUILD
@@ -0,0 +1,5 @@
+load("//bazel:api_build_system.bzl", "udpa_proto_package")
+
+licenses(["notice"])  # Apache 2
+
+udpa_proto_package()
diff --git a/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/udpa/annotations/migrate.proto b/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/udpa/annotations/migrate.proto
new file mode 100644
index 00000000..1c42a640
--- /dev/null
+++ b/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/udpa/annotations/migrate.proto
@@ -0,0 +1,49 @@
+syntax = "proto3";
+
+package udpa.annotations;
+
+import "google/protobuf/descriptor.proto";
+
+// Magic number in this file derived from top 28bit of SHA256 digest of
+// "udpa.annotation.migrate".
+
+extend google.protobuf.MessageOptions {
+  MigrateAnnotation message_migrate = 171962766;
+}
+
+extend google.protobuf.FieldOptions {
+  FieldMigrateAnnotation field_migrate = 171962766;
+}
+
+extend google.protobuf.EnumOptions {
+  MigrateAnnotation enum_migrate = 171962766;
+}
+
+extend google.protobuf.EnumValueOptions {
+  MigrateAnnotation enum_value_migrate = 171962766;
+}
+
+extend google.protobuf.FileOptions {
+  FileMigrateAnnotation file_migrate = 171962766;
+}
+
+message MigrateAnnotation {
+  // Rename the message/enum/enum value in next version.
+  string rename = 1;
+}
+
+message FieldMigrateAnnotation {
+  // Rename the field in next version.
+  string rename = 1;
+
+  // Add the field to a named oneof in next version. If this already exists, the
+  // field will join its siblings under the oneof, otherwise a new oneof will be
+  // created with the given name.
+  string oneof_promotion = 2;
+}
+
+message FileMigrateAnnotation {
+  // Move all types in the file to another package, this implies changing proto
+  // file path.
+  string move_to_package = 2;
+}
diff --git a/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/udpa/annotations/security.proto b/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/udpa/annotations/security.proto
new file mode 100644
index 00000000..7191fe30
--- /dev/null
+++ b/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/udpa/annotations/security.proto
@@ -0,0 +1,31 @@
+syntax = "proto3";
+
+package udpa.annotations;
+
+import "udpa/annotations/status.proto";
+
+import "google/protobuf/any.proto";
+import "google/protobuf/descriptor.proto";
+
+import "validate/validate.proto";
+
+// All annotations in this file are experimental and subject to change. Their
+// only consumer today is the Envoy APIs and SecuritAnnotationValidator protoc
+// plugin in this repository.
+option (udpa.annotations.file_status).work_in_progress = true;
+
+extend google.protobuf.FieldOptions {
+  // Magic number is the 28 most significant bits in the sha256sum of
+  // "udpa.annotations.security".
+  FieldSecurityAnnotation security = 11122993;
+}
+
+// These annotations indicate metadata for the purpose of understanding the
+// security significance of fields.
+message FieldSecurityAnnotation {
+  // Field should be set in the presence of untrusted downstreams.
+  bool configure_for_untrusted_downstream = 1;
+
+  // Field should be set in the presence of untrusted upstreams.
+  bool configure_for_untrusted_upstream = 2;
+}
diff --git a/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/udpa/annotations/sensitive.proto b/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/udpa/annotations/sensitive.proto
new file mode 100644
index 00000000..8dc921f2
--- /dev/null
+++ b/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/udpa/annotations/sensitive.proto
@@ -0,0 +1,14 @@
+syntax = "proto3";
+
+package udpa.annotations;
+
+import "google/protobuf/descriptor.proto";
+
+extend google.protobuf.FieldOptions {
+  // Magic number is the 28 most significant bits in the sha256sum of "udpa.annotations.sensitive".
+  // When set to true, `sensitive` indicates that this field contains sensitive data, such as
+  // personally identifiable information, passwords, or private keys, and should be redacted for
+  // display by tools aware of this annotation. Note that that this has no effect on standard
+  // Protobuf functions such as `TextFormat::PrintToString`.
+  bool sensitive = 76569463;
+}
diff --git a/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/udpa/annotations/status.proto b/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/udpa/annotations/status.proto
new file mode 100644
index 00000000..9832ffd3
--- /dev/null
+++ b/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/udpa/annotations/status.proto
@@ -0,0 +1,34 @@
+syntax = "proto3";
+
+package udpa.annotations;
+
+import "google/protobuf/descriptor.proto";
+
+// Magic number in this file derived from top 28bit of SHA256 digest of
+// "udpa.annotation.status".
+extend google.protobuf.FileOptions {
+  StatusAnnotation file_status = 222707719;
+}
+
+enum PackageVersionStatus {
+  // Unknown package version status.
+  UNKNOWN = 0;
+
+  // This version of the package is frozen.
+  FROZEN = 1;
+
+  // This version of the package is the active development version.
+  ACTIVE = 2;
+
+  // This version of the package is the candidate for the next major version. It
+  // is typically machine generated from the active development version.
+  NEXT_MAJOR_VERSION_CANDIDATE = 3;
+}
+
+message StatusAnnotation {
+  // The entity is work-in-progress and subject to breaking changes.
+  bool work_in_progress = 1;
+
+  // The entity belongs to a package with the given version status.
+  PackageVersionStatus package_version_status = 2;
+}
diff --git a/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/udpa/annotations/versioning.proto b/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/udpa/annotations/versioning.proto
new file mode 100644
index 00000000..16f6dc30
--- /dev/null
+++ b/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/udpa/annotations/versioning.proto
@@ -0,0 +1,17 @@
+syntax = "proto3";
+
+package udpa.annotations;
+
+import "google/protobuf/descriptor.proto";
+
+extend google.protobuf.MessageOptions {
+  // Magic number derived from 0x78 ('x') 0x44 ('D') 0x53 ('S')
+  VersioningAnnotation versioning = 7881811;
+}
+
+message VersioningAnnotation {
+  // Track the previous message type. E.g. this message might be
+  // udpa.foo.v3alpha.Foo and it was previously udpa.bar.v2.Bar. This
+  // information is consumed by UDPA via proto descriptors.
+  string previous_message_type = 1;
+}
diff --git a/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/validate/validate.proto b/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/validate/validate.proto
index b6625513..167ebdfb 100644
--- a/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/validate/validate.proto
+++ b/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/main/proto/validate/validate.proto
@@ -1,8 +1,8 @@
 syntax = "proto2";
 package validate;
 
-option go_package = "github.com/lyft/protoc-gen-validate/validate";
-option java_package = "com.lyft.pgv.validate";
+option go_package = "github.com/envoyproxy/protoc-gen-validate/validate";
+option java_package = "io.envoyproxy.pgv.validate";
 
 import "google/protobuf/descriptor.proto";
 import "google/protobuf/duration.proto";
@@ -12,26 +12,29 @@ import "google/protobuf/timestamp.proto";
 extend google.protobuf.MessageOptions {
     // Disabled nullifies any validation rules for this message, including any
     // message fields associated with it that do support validation.
-    optional bool disabled = 919191;
+    optional bool disabled = 1071;
+    // Ignore skips generation of validation methods for this message.
+    optional bool ignored = 1072;
 }
 
 // Validation rules applied at the oneof level
 extend google.protobuf.OneofOptions {
     // Required ensures that exactly one the field options in a oneof is set;
     // validation fails if no fields in the oneof are set.
-    optional bool required = 919191;
+    optional bool required = 1071;
 }
 
 // Validation rules applied at the field level
 extend google.protobuf.FieldOptions {
     // Rules specify the validations to be performed on this field. By default,
     // no validation is performed against a field.
-    optional FieldRules rules = 919191;
+    optional FieldRules rules = 1071;
 }
 
 // FieldRules encapsulates the rules for each type of field. Depending on the
 // field, the correct set should be used to ensure proper validations.
 message FieldRules {
+    optional MessageRules message = 17;
     oneof type {
         // Scalar Field Types
         FloatRules    float    = 1;
@@ -52,7 +55,6 @@ message FieldRules {
 
         // Complex Field Types
         EnumRules     enum     = 16;
-        MessageRules  message  = 17;
         RepeatedRules repeated = 18;
         MapRules      map      = 19;
 
@@ -93,6 +95,10 @@ message FloatRules {
     // NotIn specifies that this field cannot be equal to one of the specified
     // values
     repeated float not_in = 7;
+
+    // IgnoreEmpty specifies that the validation rules of this field should be
+    // evaluated only if the field is not empty
+    optional bool ignore_empty = 8;
 }
 
 // DoubleRules describes the constraints applied to `double` values
@@ -125,6 +131,10 @@ message DoubleRules {
     // NotIn specifies that this field cannot be equal to one of the specified
     // values
     repeated double not_in = 7;
+
+    // IgnoreEmpty specifies that the validation rules of this field should be
+    // evaluated only if the field is not empty
+    optional bool ignore_empty = 8;
 }
 
 // Int32Rules describes the constraints applied to `int32` values
@@ -157,6 +167,10 @@ message Int32Rules {
     // NotIn specifies that this field cannot be equal to one of the specified
     // values
     repeated int32 not_in = 7;
+
+    // IgnoreEmpty specifies that the validation rules of this field should be
+    // evaluated only if the field is not empty
+    optional bool ignore_empty = 8;
 }
 
 // Int64Rules describes the constraints applied to `int64` values
@@ -189,6 +203,10 @@ message Int64Rules {
     // NotIn specifies that this field cannot be equal to one of the specified
     // values
     repeated int64 not_in = 7;
+
+    // IgnoreEmpty specifies that the validation rules of this field should be
+    // evaluated only if the field is not empty
+    optional bool ignore_empty = 8;
 }
 
 // UInt32Rules describes the constraints applied to `uint32` values
@@ -221,6 +239,10 @@ message UInt32Rules {
     // NotIn specifies that this field cannot be equal to one of the specified
     // values
     repeated uint32 not_in = 7;
+
+    // IgnoreEmpty specifies that the validation rules of this field should be
+    // evaluated only if the field is not empty
+    optional bool ignore_empty = 8;
 }
 
 // UInt64Rules describes the constraints applied to `uint64` values
@@ -253,6 +275,10 @@ message UInt64Rules {
     // NotIn specifies that this field cannot be equal to one of the specified
     // values
     repeated uint64 not_in = 7;
+
+    // IgnoreEmpty specifies that the validation rules of this field should be
+    // evaluated only if the field is not empty
+    optional bool ignore_empty = 8;
 }
 
 // SInt32Rules describes the constraints applied to `sint32` values
@@ -285,6 +311,10 @@ message SInt32Rules {
     // NotIn specifies that this field cannot be equal to one of the specified
     // values
     repeated sint32 not_in = 7;
+
+    // IgnoreEmpty specifies that the validation rules of this field should be
+    // evaluated only if the field is not empty
+    optional bool ignore_empty = 8;
 }
 
 // SInt64Rules describes the constraints applied to `sint64` values
@@ -317,6 +347,10 @@ message SInt64Rules {
     // NotIn specifies that this field cannot be equal to one of the specified
     // values
     repeated sint64 not_in = 7;
+
+    // IgnoreEmpty specifies that the validation rules of this field should be
+    // evaluated only if the field is not empty
+    optional bool ignore_empty = 8;
 }
 
 // Fixed32Rules describes the constraints applied to `fixed32` values
@@ -349,6 +383,10 @@ message Fixed32Rules {
     // NotIn specifies that this field cannot be equal to one of the specified
     // values
     repeated fixed32 not_in = 7;
+
+    // IgnoreEmpty specifies that the validation rules of this field should be
+    // evaluated only if the field is not empty
+    optional bool ignore_empty = 8;
 }
 
 // Fixed64Rules describes the constraints applied to `fixed64` values
@@ -381,6 +419,10 @@ message Fixed64Rules {
     // NotIn specifies that this field cannot be equal to one of the specified
     // values
     repeated fixed64 not_in = 7;
+
+    // IgnoreEmpty specifies that the validation rules of this field should be
+    // evaluated only if the field is not empty
+    optional bool ignore_empty = 8;
 }
 
 // SFixed32Rules describes the constraints applied to `sfixed32` values
@@ -413,6 +455,10 @@ message SFixed32Rules {
     // NotIn specifies that this field cannot be equal to one of the specified
     // values
     repeated sfixed32 not_in = 7;
+
+    // IgnoreEmpty specifies that the validation rules of this field should be
+    // evaluated only if the field is not empty
+    optional bool ignore_empty = 8;
 }
 
 // SFixed64Rules describes the constraints applied to `sfixed64` values
@@ -445,6 +491,10 @@ message SFixed64Rules {
     // NotIn specifies that this field cannot be equal to one of the specified
     // values
     repeated sfixed64 not_in = 7;
+
+    // IgnoreEmpty specifies that the validation rules of this field should be
+    // evaluated only if the field is not empty
+    optional bool ignore_empty = 8;
 }
 
 // BoolRules describes the constraints applied to `bool` values
@@ -502,6 +552,10 @@ message StringRules {
     // anywhere in the string.
     optional string contains = 9;
 
+    // NotContains specifies that this field cannot have the specified substring
+    // anywhere in the string.
+    optional string not_contains = 23;
+
     // In specifies that this field must be equal to one of the specified
     // values
     repeated string in     = 10;
@@ -540,7 +594,41 @@ message StringRules {
         // UriRef specifies that the field must be a valid URI as defined by RFC
         // 3986 and may be relative or absolute.
         bool uri_ref  = 18;
+
+        // Address specifies that the field must be either a valid hostname as
+        // defined by RFC 1034 (which does not support internationalized domain
+        // names or IDNs), or it can be a valid IP (v4 or v6).
+        bool address  = 21;
+
+        // Uuid specifies that the field must be a valid UUID as defined by
+        // RFC 4122
+        bool uuid     = 22;
+
+        // WellKnownRegex specifies a common well known pattern defined as a regex.
+        KnownRegex well_known_regex = 24;
     }
+
+    // This applies to regexes HTTP_HEADER_NAME and HTTP_HEADER_VALUE to enable
+    // strict header validation.
+    // By default, this is true, and HTTP header validations are RFC-compliant.
+    // Setting to false will enable a looser validations that only disallows
+    // \r\n\0 characters, which can be used to bypass header matching rules.
+    optional bool strict = 25 [default = true];
+
+    // IgnoreEmpty specifies that the validation rules of this field should be
+    // evaluated only if the field is not empty
+    optional bool ignore_empty = 26;
+}
+
+// WellKnownRegex contain some well-known patterns.
+enum KnownRegex {
+    UNKNOWN = 0;
+
+    // HTTP header name as defined by RFC 7230.
+    HTTP_HEADER_NAME = 1;
+
+    // HTTP header value as defined by RFC 7230.
+    HTTP_HEADER_VALUE = 2;
 }
 
 // BytesRules describe the constraints applied to `bytes` values
@@ -599,6 +687,10 @@ message BytesRules {
         // format
         bool ipv6 = 12;
     }
+
+    // IgnoreEmpty specifies that the validation rules of this field should be
+    // evaluated only if the field is not empty
+    optional bool ignore_empty = 14;
 }
 
 // EnumRules describe the constraints applied to enum values
@@ -649,6 +741,10 @@ message RepeatedRules {
     // Repeated message fields will still execute validation against each item
     // unless skip is specified here.
     optional FieldRules items = 4;
+
+    // IgnoreEmpty specifies that the validation rules of this field should be
+    // evaluated only if the field is not empty
+    optional bool ignore_empty = 5;
 }
 
 // MapRules describe the constraints applied to `map` values
@@ -672,6 +768,10 @@ message MapRules {
     // in the field. Message values will still have their validations evaluated
     // unless skip is specified here.
     optional FieldRules values = 5;
+
+    // IgnoreEmpty specifies that the validation rules of this field should be
+    // evaluated only if the field is not empty
+    optional bool ignore_empty = 6;
 }
 
 // AnyRules describe constraints applied exclusively to the
diff --git a/sentinel-core/pom.xml b/sentinel-core/pom.xml
index bfe206c7..18366417 100755
--- a/sentinel-core/pom.xml
+++ b/sentinel-core/pom.xml
@@ -6,7 +6,7 @@
     <parent>
         <groupId>com.alibaba.csp</groupId>
         <artifactId>sentinel-parent</artifactId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <artifactId>sentinel-core</artifactId>
     <packaging>jar</packaging>
diff --git a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/Constants.java b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/Constants.java
index a2710617..e094181d 100755
--- a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/Constants.java
+++ b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/Constants.java
@@ -31,7 +31,7 @@ import com.alibaba.csp.sentinel.util.VersionUtil;
  */
 public final class Constants {
 
-    public static final String SENTINEL_VERSION = VersionUtil.getVersion("1.8.2");
+    public static final String SENTINEL_VERSION = VersionUtil.getVersion("1.8.3");
 
     public final static int MAX_CONTEXT_NAME_SIZE = 2000;
     public final static int MAX_SLOT_CHAIN_SIZE = 6000;
diff --git a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/eagleeye/EagleEyeCoreUtils.java b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/eagleeye/EagleEyeCoreUtils.java
index 8874f721..615c73b7 100755
--- a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/eagleeye/EagleEyeCoreUtils.java
+++ b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/eagleeye/EagleEyeCoreUtils.java
@@ -194,44 +194,4 @@ final class EagleEyeCoreUtils {
         }
     }
 
-    // Unsafe mechanics
-    @SuppressWarnings("restriction")
-    private static final sun.misc.Unsafe UNSAFE = doGetUnsafe();
-
-    @SuppressWarnings("restriction")
-    public static sun.misc.Unsafe getUnsafe() {
-        return UNSAFE;
-    }
-
-    /**
-     * Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package.
-     * Replace with a simple call to Unsafe.getUnsafe when integrating into a
-     * jdk.
-     *
-     * @return a sun.misc.Unsafe
-     */
-    @SuppressWarnings("restriction")
-    private static sun.misc.Unsafe doGetUnsafe() {
-        try {
-            return sun.misc.Unsafe.getUnsafe();
-        } catch (Throwable tryReflectionInstead) {
-        }
-        try {
-            return java.security.AccessController
-                .doPrivileged(new java.security.PrivilegedExceptionAction<sun.misc.Unsafe>() {
-                    @Override
-                    public sun.misc.Unsafe run() throws Exception {
-                        Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
-                        for (java.lang.reflect.Field f : k.getDeclaredFields()) {
-                            f.setAccessible(true);
-                            Object x = f.get(null);
-                            if (k.isInstance(x)) { return k.cast(x); }
-                        }
-                        throw new NoSuchFieldError("the Unsafe");
-                    }
-                });
-        } catch (Throwable t) {
-            return null;
-        }
-    }
 }
diff --git a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/FlowRuleManager.java b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/FlowRuleManager.java
index 10d34c1d..0fb7f4fe 100755
--- a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/FlowRuleManager.java
+++ b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/block/flow/FlowRuleManager.java
@@ -15,23 +15,23 @@
  */
 package com.alibaba.csp.sentinel.slots.block.flow;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-
 import com.alibaba.csp.sentinel.concurrent.NamedThreadFactory;
 import com.alibaba.csp.sentinel.config.SentinelConfig;
 import com.alibaba.csp.sentinel.log.RecordLog;
-import com.alibaba.csp.sentinel.util.AssertUtil;
-import com.alibaba.csp.sentinel.util.StringUtil;
 import com.alibaba.csp.sentinel.node.metric.MetricTimerListener;
 import com.alibaba.csp.sentinel.property.DynamicSentinelProperty;
 import com.alibaba.csp.sentinel.property.PropertyListener;
 import com.alibaba.csp.sentinel.property.SentinelProperty;
+import com.alibaba.csp.sentinel.util.AssertUtil;
+import com.alibaba.csp.sentinel.util.StringUtil;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
 
 /**
  * <p>
@@ -53,6 +53,7 @@ public class FlowRuleManager {
     private static final FlowPropertyListener LISTENER = new FlowPropertyListener();
     private static SentinelProperty<List<FlowRule>> currentProperty = new DynamicSentinelProperty<List<FlowRule>>();
 
+    /** the corePool size of SCHEDULER must be set at 1, so the two task ({@link #startMetricTimerListener()} can run orderly by the SCHEDULER **/
     @SuppressWarnings("PMD.ThreadPoolCreationRule")
     private static final ScheduledExecutorService SCHEDULER = Executors.newScheduledThreadPool(1,
         new NamedThreadFactory("sentinel-metrics-record-task", true));
diff --git a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/system/SystemRuleManager.java b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/system/SystemRuleManager.java
index d860344e..4ee5f17c 100755
--- a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/system/SystemRuleManager.java
+++ b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/system/SystemRuleManager.java
@@ -287,7 +287,7 @@ public final class SystemRuleManager {
      * @param resourceWrapper the resource.
      * @throws BlockException when any system rule's threshold is exceeded.
      */
-    public static void checkSystem(ResourceWrapper resourceWrapper) throws BlockException {
+    public static void checkSystem(ResourceWrapper resourceWrapper, int count) throws BlockException {
         if (resourceWrapper == null) {
             return;
         }
@@ -302,8 +302,8 @@ public final class SystemRuleManager {
         }
 
         // total qps
-        double currentQps = Constants.ENTRY_NODE == null ? 0.0 : Constants.ENTRY_NODE.successQps();
-        if (currentQps > qps) {
+        double currentQps = Constants.ENTRY_NODE == null ? 0.0 : Constants.ENTRY_NODE.passQps();
+        if (currentQps + count > qps) {
             throw new SystemBlockException(resourceWrapper.getName(), "qps");
         }
 
diff --git a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/system/SystemSlot.java b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/system/SystemSlot.java
index c98e491c..44b54727 100755
--- a/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/system/SystemSlot.java
+++ b/sentinel-core/src/main/java/com/alibaba/csp/sentinel/slots/system/SystemSlot.java
@@ -35,7 +35,7 @@ public class SystemSlot extends AbstractLinkedProcessorSlot<DefaultNode> {
     @Override
     public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count,
                       boolean prioritized, Object... args) throws Throwable {
-        SystemRuleManager.checkSystem(resourceWrapper);
+        SystemRuleManager.checkSystem(resourceWrapper, count);
         fireEntry(context, resourceWrapper, node, count, prioritized, args);
     }
 
diff --git a/sentinel-dashboard/pom.xml b/sentinel-dashboard/pom.xml
index 9430bbb4..f8ff068a 100644
--- a/sentinel-dashboard/pom.xml
+++ b/sentinel-dashboard/pom.xml
@@ -6,7 +6,7 @@
     <parent>
         <groupId>com.alibaba.csp</groupId>
         <artifactId>sentinel-parent</artifactId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
 
     <artifactId>sentinel-dashboard</artifactId>
diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/client/SentinelApiClient.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/client/SentinelApiClient.java
index 01420598..e013f89f 100755
--- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/client/SentinelApiClient.java
+++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/client/SentinelApiClient.java
@@ -163,7 +163,7 @@ public class SentinelApiClient {
     }
     
     /**
-     * Check wheter target instance (identified by tuple of app-ip:port)
+     * Check whether target instance (identified by tuple of app-ip:port)
      * supports the form of "xxxxx; xx=xx" in "Content-Type" header.
      * 
      * @param app target app name
diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/MachineRegistryController.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/MachineRegistryController.java
index d11815d2..6552d1ce 100755
--- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/MachineRegistryController.java
+++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/controller/MachineRegistryController.java
@@ -29,6 +29,7 @@ import org.springframework.stereotype.Controller;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.ResponseBody;
+import sun.net.util.IPAddressUtil;
 
 @Controller
 @RequestMapping(value = "/registry", produces = MediaType.APPLICATION_JSON_VALUE)
@@ -51,6 +52,9 @@ public class MachineRegistryController {
         if (StringUtil.isBlank(ip) || ip.length() > 128) {
             return Result.ofFail(-1, "invalid ip: " + ip);
         }
+        if (!IPAddressUtil.isIPv4LiteralAddress(ip) && !IPAddressUtil.isIPv6LiteralAddress(ip)) {
+            return Result.ofFail(-1, "invalid ip: " + ip);
+        }
         if (port == null || port < -1) {
             return Result.ofFail(-1, "invalid port");
         }
diff --git a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/metric/MetricFetcher.java b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/metric/MetricFetcher.java
index 05fc6cf0..13bd4db5 100755
--- a/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/metric/MetricFetcher.java
+++ b/sentinel-dashboard/src/main/java/com/alibaba/csp/sentinel/dashboard/metric/MetricFetcher.java
@@ -268,7 +268,7 @@ public class MetricFetcher {
         lastFetchMs = lastFetchMs / 1000 * 1000;
         long endTime = lastFetchMs + FETCH_INTERVAL_SECOND * 1000;
         if (endTime > now - 1000 * 2) {
-            // to near
+            // too near
             return;
         }
         // update last_fetch in advance.
diff --git a/sentinel-dashboard/src/main/webapp/resources/index.htm b/sentinel-dashboard/src/main/webapp/resources/index.htm
index 8308dfec..268ab100 100755
--- a/sentinel-dashboard/src/main/webapp/resources/index.htm
+++ b/sentinel-dashboard/src/main/webapp/resources/index.htm
@@ -10,7 +10,7 @@
   <link rel="stylesheet" href="./lib/css/bootstrap.min.css" />
   <link rel="stylesheet" href="./lib/css/font-awesome.min.css">
   <link rel="stylesheet" href="./dist/css/app.css">
-  <link rel="icon" type="image/x-icon" href="/static/favicon.ico">
+  <link rel="icon" type="image/x-icon" href="./static/favicon.ico">
   <base href="./">
 </head>
 
diff --git a/sentinel-dashboard/src/main/webapp/resources/index_dev.htm b/sentinel-dashboard/src/main/webapp/resources/index_dev.htm
index 827369ba..008fcfb4 100755
--- a/sentinel-dashboard/src/main/webapp/resources/index_dev.htm
+++ b/sentinel-dashboard/src/main/webapp/resources/index_dev.htm
@@ -10,7 +10,7 @@
   <link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.0.3/css/bootstrap.min.css" />
   <link rel="stylesheet" href="//cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css">
   <link rel="stylesheet" href="http://localhost:1234/css/app.css">
-  <link rel="icon" type="image/x-icon" href="/static/favicon.ico">
+  <link rel="icon" type="image/x-icon" href="./static/favicon.ico">
   <base href="./">
 </head>
 
diff --git a/sentinel-demo/pom.xml b/sentinel-demo/pom.xml
index fed2b732..2b8294e3 100755
--- a/sentinel-demo/pom.xml
+++ b/sentinel-demo/pom.xml
@@ -6,7 +6,7 @@
     <parent>
         <groupId>com.alibaba.csp</groupId>
         <artifactId>sentinel-parent</artifactId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <artifactId>sentinel-demo</artifactId>
     <packaging>pom</packaging>
diff --git a/sentinel-demo/sentinel-demo-annotation-cdi-interceptor/pom.xml b/sentinel-demo/sentinel-demo-annotation-cdi-interceptor/pom.xml
index 54a84ed1..aedcb434 100644
--- a/sentinel-demo/sentinel-demo-annotation-cdi-interceptor/pom.xml
+++ b/sentinel-demo/sentinel-demo-annotation-cdi-interceptor/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-demo</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-demo/sentinel-demo-annotation-spring-aop/pom.xml b/sentinel-demo/sentinel-demo-annotation-spring-aop/pom.xml
index a281e236..b1a834cc 100644
--- a/sentinel-demo/sentinel-demo-annotation-spring-aop/pom.xml
+++ b/sentinel-demo/sentinel-demo-annotation-spring-aop/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-demo</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-demo/sentinel-demo-apache-dubbo/pom.xml b/sentinel-demo/sentinel-demo-apache-dubbo/pom.xml
index f0477d92..820bc35a 100644
--- a/sentinel-demo/sentinel-demo-apache-dubbo/pom.xml
+++ b/sentinel-demo/sentinel-demo-apache-dubbo/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-demo</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-demo/sentinel-demo-apache-httpclient/pom.xml b/sentinel-demo/sentinel-demo-apache-httpclient/pom.xml
index 40559ca0..c04b2c02 100644
--- a/sentinel-demo/sentinel-demo-apache-httpclient/pom.xml
+++ b/sentinel-demo/sentinel-demo-apache-httpclient/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-demo</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-demo/sentinel-demo-apollo-datasource/pom.xml b/sentinel-demo/sentinel-demo-apollo-datasource/pom.xml
index 4c6750b2..123f1f98 100644
--- a/sentinel-demo/sentinel-demo-apollo-datasource/pom.xml
+++ b/sentinel-demo/sentinel-demo-apollo-datasource/pom.xml
@@ -5,14 +5,14 @@
   <parent>
     <artifactId>sentinel-demo</artifactId>
     <groupId>com.alibaba.csp</groupId>
-    <version>1.8.2</version>
+    <version>1.8.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
   <artifactId>sentinel-demo-apollo-datasource</artifactId>
 
   <properties>
-    <log4j2.version>2.9.1</log4j2.version>
+    <log4j2.version>2.17.0</log4j2.version>
     <slf4j.version>1.7.25</slf4j.version>
   </properties>
 
diff --git a/sentinel-demo/sentinel-demo-basic/pom.xml b/sentinel-demo/sentinel-demo-basic/pom.xml
index 7acc67f0..3bc5870b 100755
--- a/sentinel-demo/sentinel-demo-basic/pom.xml
+++ b/sentinel-demo/sentinel-demo-basic/pom.xml
@@ -6,7 +6,7 @@
     <parent>
         <groupId>com.alibaba.csp</groupId>
         <artifactId>sentinel-demo</artifactId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <artifactId>sentinel-demo-basic</artifactId>
 
diff --git a/sentinel-demo/sentinel-demo-cluster/pom.xml b/sentinel-demo/sentinel-demo-cluster/pom.xml
index d9561281..eb278308 100644
--- a/sentinel-demo/sentinel-demo-cluster/pom.xml
+++ b/sentinel-demo/sentinel-demo-cluster/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-demo</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/pom.xml b/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/pom.xml
index a2f33f5a..0896befd 100644
--- a/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/pom.xml
+++ b/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-embedded/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-demo-cluster</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-server-alone/pom.xml b/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-server-alone/pom.xml
index 2cb011b8..6a881856 100644
--- a/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-server-alone/pom.xml
+++ b/sentinel-demo/sentinel-demo-cluster/sentinel-demo-cluster-server-alone/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-demo-cluster</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-demo/sentinel-demo-command-handler/pom.xml b/sentinel-demo/sentinel-demo-command-handler/pom.xml
index d1fe10b1..dfe83e97 100644
--- a/sentinel-demo/sentinel-demo-command-handler/pom.xml
+++ b/sentinel-demo/sentinel-demo-command-handler/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-demo</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-demo/sentinel-demo-dubbo/pom.xml b/sentinel-demo/sentinel-demo-dubbo/pom.xml
index 619148f4..0a573ce4 100644
--- a/sentinel-demo/sentinel-demo-dubbo/pom.xml
+++ b/sentinel-demo/sentinel-demo-dubbo/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-demo</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-demo/sentinel-demo-dynamic-file-rule/pom.xml b/sentinel-demo/sentinel-demo-dynamic-file-rule/pom.xml
index 74b97f7d..652cdbf4 100755
--- a/sentinel-demo/sentinel-demo-dynamic-file-rule/pom.xml
+++ b/sentinel-demo/sentinel-demo-dynamic-file-rule/pom.xml
@@ -6,7 +6,7 @@
     <parent>
         <groupId>com.alibaba.csp</groupId>
         <artifactId>sentinel-demo</artifactId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <artifactId>sentinel-demo-dynamic-file-rule</artifactId>
 
diff --git a/sentinel-demo/sentinel-demo-etcd-datasource/pom.xml b/sentinel-demo/sentinel-demo-etcd-datasource/pom.xml
index fec83f82..8fe3fe94 100644
--- a/sentinel-demo/sentinel-demo-etcd-datasource/pom.xml
+++ b/sentinel-demo/sentinel-demo-etcd-datasource/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-demo</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-demo/sentinel-demo-jax-rs/pom.xml b/sentinel-demo/sentinel-demo-jax-rs/pom.xml
index 948a1a15..de731498 100644
--- a/sentinel-demo/sentinel-demo-jax-rs/pom.xml
+++ b/sentinel-demo/sentinel-demo-jax-rs/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-demo</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-demo/sentinel-demo-log-logback/pom.xml b/sentinel-demo/sentinel-demo-log-logback/pom.xml
index 65c1e8a6..21ea49c6 100644
--- a/sentinel-demo/sentinel-demo-log-logback/pom.xml
+++ b/sentinel-demo/sentinel-demo-log-logback/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-demo</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-demo/sentinel-demo-motan/pom.xml b/sentinel-demo/sentinel-demo-motan/pom.xml
index 746641e1..e26b6a8c 100644
--- a/sentinel-demo/sentinel-demo-motan/pom.xml
+++ b/sentinel-demo/sentinel-demo-motan/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-demo</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>sentinel-demo-motan</artifactId>
diff --git a/sentinel-demo/sentinel-demo-nacos-datasource/pom.xml b/sentinel-demo/sentinel-demo-nacos-datasource/pom.xml
index 97046326..202150f6 100644
--- a/sentinel-demo/sentinel-demo-nacos-datasource/pom.xml
+++ b/sentinel-demo/sentinel-demo-nacos-datasource/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-demo</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-demo/sentinel-demo-okhttp/pom.xml b/sentinel-demo/sentinel-demo-okhttp/pom.xml
index a2a98d73..56d264c8 100644
--- a/sentinel-demo/sentinel-demo-okhttp/pom.xml
+++ b/sentinel-demo/sentinel-demo-okhttp/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-demo</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-demo/sentinel-demo-parameter-flow-control/pom.xml b/sentinel-demo/sentinel-demo-parameter-flow-control/pom.xml
index a87134da..95b0f6d9 100644
--- a/sentinel-demo/sentinel-demo-parameter-flow-control/pom.xml
+++ b/sentinel-demo/sentinel-demo-parameter-flow-control/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-demo</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-demo/sentinel-demo-quarkus/pom.xml b/sentinel-demo/sentinel-demo-quarkus/pom.xml
index dbc203c5..f9e11c36 100644
--- a/sentinel-demo/sentinel-demo-quarkus/pom.xml
+++ b/sentinel-demo/sentinel-demo-quarkus/pom.xml
@@ -6,7 +6,7 @@
     <parent>
         <artifactId>sentinel-demo</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-demo/sentinel-demo-rocketmq/pom.xml b/sentinel-demo/sentinel-demo-rocketmq/pom.xml
index 0c14793b..1e099682 100755
--- a/sentinel-demo/sentinel-demo-rocketmq/pom.xml
+++ b/sentinel-demo/sentinel-demo-rocketmq/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <groupId>com.alibaba.csp</groupId>
         <artifactId>sentinel-demo</artifactId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-demo/sentinel-demo-slot-spi/pom.xml b/sentinel-demo/sentinel-demo-slot-spi/pom.xml
index 3b2d21a5..a700e3ae 100644
--- a/sentinel-demo/sentinel-demo-slot-spi/pom.xml
+++ b/sentinel-demo/sentinel-demo-slot-spi/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-demo</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-demo/sentinel-demo-slotchain-spi/pom.xml b/sentinel-demo/sentinel-demo-slotchain-spi/pom.xml
index 845d8f01..2b160851 100644
--- a/sentinel-demo/sentinel-demo-slotchain-spi/pom.xml
+++ b/sentinel-demo/sentinel-demo-slotchain-spi/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-demo</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-demo/sentinel-demo-sofa-rpc/pom.xml b/sentinel-demo/sentinel-demo-sofa-rpc/pom.xml
index f9b0a48e..66f461f7 100644
--- a/sentinel-demo/sentinel-demo-sofa-rpc/pom.xml
+++ b/sentinel-demo/sentinel-demo-sofa-rpc/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-demo</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-demo/sentinel-demo-spring-cloud-gateway/pom.xml b/sentinel-demo/sentinel-demo-spring-cloud-gateway/pom.xml
index a94aab88..9d3d5c43 100644
--- a/sentinel-demo/sentinel-demo-spring-cloud-gateway/pom.xml
+++ b/sentinel-demo/sentinel-demo-spring-cloud-gateway/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-demo</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-demo/sentinel-demo-spring-webflux/pom.xml b/sentinel-demo/sentinel-demo-spring-webflux/pom.xml
index bfa972bc..f9dcd9be 100644
--- a/sentinel-demo/sentinel-demo-spring-webflux/pom.xml
+++ b/sentinel-demo/sentinel-demo-spring-webflux/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-demo</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
@@ -16,10 +16,6 @@
     </properties>
 
     <dependencies>
-        <dependency>
-            <groupId>com.alibaba.csp</groupId>
-            <artifactId>sentinel-core</artifactId>
-        </dependency>
         <dependency>
             <groupId>com.alibaba.csp</groupId>
             <artifactId>sentinel-transport-simple-http</artifactId>
diff --git a/sentinel-demo/sentinel-demo-spring-webflux/src/main/java/com/alibaba/csp/sentinel/demo/spring/webflux/config/WebFluxConfig.java b/sentinel-demo/sentinel-demo-spring-webflux/src/main/java/com/alibaba/csp/sentinel/demo/spring/webflux/config/WebFluxConfig.java
index 60536673..9ce03fa4 100644
--- a/sentinel-demo/sentinel-demo-spring-webflux/src/main/java/com/alibaba/csp/sentinel/demo/spring/webflux/config/WebFluxConfig.java
+++ b/sentinel-demo/sentinel-demo-spring-webflux/src/main/java/com/alibaba/csp/sentinel/demo/spring/webflux/config/WebFluxConfig.java
@@ -31,7 +31,6 @@ import org.springframework.web.reactive.result.view.ViewResolver;
 /**
  * @author Eric Zhao
  */
-@Configuration
 public class WebFluxConfig {
 
     private final List<ViewResolver> viewResolvers;
diff --git a/sentinel-demo/sentinel-demo-spring-webmvc/pom.xml b/sentinel-demo/sentinel-demo-spring-webmvc/pom.xml
index c1fb6543..0e8d81a0 100644
--- a/sentinel-demo/sentinel-demo-spring-webmvc/pom.xml
+++ b/sentinel-demo/sentinel-demo-spring-webmvc/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-demo</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-demo/sentinel-demo-transport-spring-mvc/pom.xml b/sentinel-demo/sentinel-demo-transport-spring-mvc/pom.xml
index 6ad16b1f..9ac21749 100644
--- a/sentinel-demo/sentinel-demo-transport-spring-mvc/pom.xml
+++ b/sentinel-demo/sentinel-demo-transport-spring-mvc/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-demo</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-demo/sentinel-demo-zookeeper-datasource/pom.xml b/sentinel-demo/sentinel-demo-zookeeper-datasource/pom.xml
index 015bc472..24ffc232 100644
--- a/sentinel-demo/sentinel-demo-zookeeper-datasource/pom.xml
+++ b/sentinel-demo/sentinel-demo-zookeeper-datasource/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-demo</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-demo/sentinel-demo-zuul-gateway/pom.xml b/sentinel-demo/sentinel-demo-zuul-gateway/pom.xml
index 84a44469..7038fc9c 100644
--- a/sentinel-demo/sentinel-demo-zuul-gateway/pom.xml
+++ b/sentinel-demo/sentinel-demo-zuul-gateway/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-demo</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-demo/sentinel-demo-zuul2-gateway/pom.xml b/sentinel-demo/sentinel-demo-zuul2-gateway/pom.xml
index f380c270..6d5eda4c 100644
--- a/sentinel-demo/sentinel-demo-zuul2-gateway/pom.xml
+++ b/sentinel-demo/sentinel-demo-zuul2-gateway/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-demo</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-extension/pom.xml b/sentinel-extension/pom.xml
index 8e336793..413c94dc 100755
--- a/sentinel-extension/pom.xml
+++ b/sentinel-extension/pom.xml
@@ -6,7 +6,7 @@
     <parent>
         <groupId>com.alibaba.csp</groupId>
         <artifactId>sentinel-parent</artifactId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <artifactId>sentinel-extension</artifactId>
     <packaging>pom</packaging>
@@ -24,6 +24,7 @@
         <module>sentinel-datasource-etcd</module>
         <module>sentinel-datasource-eureka</module>
         <module>sentinel-annotation-cdi-interceptor</module>
+        <module>sentinel-metric-exporter</module>
     </modules>
 
 </project>
diff --git a/sentinel-extension/sentinel-annotation-aspectj/pom.xml b/sentinel-extension/sentinel-annotation-aspectj/pom.xml
index be696ac7..8bd8c68a 100644
--- a/sentinel-extension/sentinel-annotation-aspectj/pom.xml
+++ b/sentinel-extension/sentinel-annotation-aspectj/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-extension</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-extension/sentinel-annotation-cdi-interceptor/pom.xml b/sentinel-extension/sentinel-annotation-cdi-interceptor/pom.xml
index 195501fa..6d938bb0 100644
--- a/sentinel-extension/sentinel-annotation-cdi-interceptor/pom.xml
+++ b/sentinel-extension/sentinel-annotation-cdi-interceptor/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-extension</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-extension/sentinel-datasource-apollo/pom.xml b/sentinel-extension/sentinel-datasource-apollo/pom.xml
index cf4ded42..873a1b78 100644
--- a/sentinel-extension/sentinel-datasource-apollo/pom.xml
+++ b/sentinel-extension/sentinel-datasource-apollo/pom.xml
@@ -5,7 +5,7 @@
   <parent>
     <artifactId>sentinel-extension</artifactId>
     <groupId>com.alibaba.csp</groupId>
-    <version>1.8.2</version>
+    <version>1.8.3</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-extension/sentinel-datasource-consul/pom.xml b/sentinel-extension/sentinel-datasource-consul/pom.xml
index d23b4b4e..2997fc04 100644
--- a/sentinel-extension/sentinel-datasource-consul/pom.xml
+++ b/sentinel-extension/sentinel-datasource-consul/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-extension</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-extension/sentinel-datasource-consul/src/main/java/com/alibaba/csp/sentinel/datasource/consul/ConsulDataSource.java b/sentinel-extension/sentinel-datasource-consul/src/main/java/com/alibaba/csp/sentinel/datasource/consul/ConsulDataSource.java
index 276bd853..445fe80d 100644
--- a/sentinel-extension/sentinel-datasource-consul/src/main/java/com/alibaba/csp/sentinel/datasource/consul/ConsulDataSource.java
+++ b/sentinel-extension/sentinel-datasource-consul/src/main/java/com/alibaba/csp/sentinel/datasource/consul/ConsulDataSource.java
@@ -21,6 +21,7 @@ import com.alibaba.csp.sentinel.datasource.Converter;
 import com.alibaba.csp.sentinel.log.RecordLog;
 import com.alibaba.csp.sentinel.util.AssertUtil;
 
+import com.alibaba.csp.sentinel.util.StringUtil;
 import com.ecwid.consul.v1.ConsulClient;
 import com.ecwid.consul.v1.QueryParams;
 import com.ecwid.consul.v1.Response;
@@ -43,12 +44,14 @@ import java.util.concurrent.*;
  * </p>
  *
  * @author wavesZh
+ * @author Zhiguo.Chen
  */
 public class ConsulDataSource<T> extends AbstractDataSource<String, T> {
 
     private static final int DEFAULT_PORT = 8500;
 
     private final String address;
+    private final String token;
     private final String ruleKey;
     /**
      * Request of query will hang until timeout (in second) or get updated value.
@@ -83,12 +86,27 @@ public class ConsulDataSource<T> extends AbstractDataSource<String, T> {
      * @param watchTimeout request for querying data will be blocked until new data or timeout. The unit is second (s)
      */
     public ConsulDataSource(String host, int port, String ruleKey, int watchTimeout, Converter<String, T> parser) {
+        this(host, port, null, ruleKey, watchTimeout, parser);
+    }
+
+    /**
+     * Constructor of {@code ConsulDataSource}.
+     *
+     * @param parser       customized data parser, cannot be empty
+     * @param host         consul agent host
+     * @param port         consul agent port
+     * @param token     consul agent acl token
+     * @param ruleKey      data key in Consul
+     * @param watchTimeout request for querying data will be blocked until new data or timeout. The unit is second (s)
+     */
+    public ConsulDataSource(String host, int port, String token, String ruleKey, int watchTimeout, Converter<String, T> parser) {
         super(parser);
         AssertUtil.notNull(host, "Consul host can not be null");
         AssertUtil.notEmpty(ruleKey, "Consul ruleKey can not be empty");
         AssertUtil.isTrue(watchTimeout >= 0, "watchTimeout should not be negative");
         this.client = new ConsulClient(host, port);
         this.address = host + ":" + port;
+        this.token = token;
         this.ruleKey = ruleKey;
         this.watchTimeout = watchTimeout;
         loadInitialConfig();
@@ -193,7 +211,11 @@ public class ConsulDataSource<T> extends AbstractDataSource<String, T> {
      */
     private Response<GetValue> getValue(String key, long index, long waitTime) {
         try {
-            return client.getKVValue(key, new QueryParams(waitTime, index));
+            if (StringUtil.isNotBlank(token)) {
+                return client.getKVValue(key, token, new QueryParams(waitTime, index));
+            } else {
+                return client.getKVValue(key, new QueryParams(waitTime, index));
+            }
         } catch (Throwable t) {
             RecordLog.warn("[ConsulDataSource] Failed to get value for key: " + key, t);
         }
diff --git a/sentinel-extension/sentinel-datasource-etcd/pom.xml b/sentinel-extension/sentinel-datasource-etcd/pom.xml
index 15e7979e..9155fee3 100644
--- a/sentinel-extension/sentinel-datasource-etcd/pom.xml
+++ b/sentinel-extension/sentinel-datasource-etcd/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-extension</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-extension/sentinel-datasource-eureka/pom.xml b/sentinel-extension/sentinel-datasource-eureka/pom.xml
index b9e11aa2..21248b46 100644
--- a/sentinel-extension/sentinel-datasource-eureka/pom.xml
+++ b/sentinel-extension/sentinel-datasource-eureka/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-extension</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-extension/sentinel-datasource-extension/pom.xml b/sentinel-extension/sentinel-datasource-extension/pom.xml
index 1850e958..e58a3750 100755
--- a/sentinel-extension/sentinel-datasource-extension/pom.xml
+++ b/sentinel-extension/sentinel-datasource-extension/pom.xml
@@ -6,7 +6,7 @@
     <parent>
         <groupId>com.alibaba.csp</groupId>
         <artifactId>sentinel-extension</artifactId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
 
     <artifactId>sentinel-datasource-extension</artifactId>
diff --git a/sentinel-extension/sentinel-datasource-nacos/pom.xml b/sentinel-extension/sentinel-datasource-nacos/pom.xml
index 01cf0b68..bde2474c 100644
--- a/sentinel-extension/sentinel-datasource-nacos/pom.xml
+++ b/sentinel-extension/sentinel-datasource-nacos/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-extension</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-extension/sentinel-datasource-redis/pom.xml b/sentinel-extension/sentinel-datasource-redis/pom.xml
index 82dcecda..53b6691b 100644
--- a/sentinel-extension/sentinel-datasource-redis/pom.xml
+++ b/sentinel-extension/sentinel-datasource-redis/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-extension</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-extension/sentinel-datasource-spring-cloud-config/pom.xml b/sentinel-extension/sentinel-datasource-spring-cloud-config/pom.xml
index 99e6bfca..b590a757 100644
--- a/sentinel-extension/sentinel-datasource-spring-cloud-config/pom.xml
+++ b/sentinel-extension/sentinel-datasource-spring-cloud-config/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-extension</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-extension/sentinel-datasource-zookeeper/pom.xml b/sentinel-extension/sentinel-datasource-zookeeper/pom.xml
index cc412a21..1e6fc54f 100644
--- a/sentinel-extension/sentinel-datasource-zookeeper/pom.xml
+++ b/sentinel-extension/sentinel-datasource-zookeeper/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-extension</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-extension/sentinel-metric-exporter/pom.xml b/sentinel-extension/sentinel-metric-exporter/pom.xml
new file mode 100644
index 00000000..482ac4d4
--- /dev/null
+++ b/sentinel-extension/sentinel-metric-exporter/pom.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>sentinel-extension</artifactId>
+        <groupId>com.alibaba.csp</groupId>
+        <version>1.8.3</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    
+    <artifactId>sentinel-metric-exporter</artifactId>
+    <packaging>jar</packaging>
+    
+    <dependencies>
+        <dependency>
+            <groupId>com.alibaba.csp</groupId>
+            <artifactId>sentinel-core</artifactId>
+        </dependency>
+    
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/sentinel-extension/sentinel-metric-exporter/src/main/java/com/alibaba/csp/sentinel/metric/MetricExporterInit.java b/sentinel-extension/sentinel-metric-exporter/src/main/java/com/alibaba/csp/sentinel/metric/MetricExporterInit.java
new file mode 100644
index 00000000..a8d30cfa
--- /dev/null
+++ b/sentinel-extension/sentinel-metric-exporter/src/main/java/com/alibaba/csp/sentinel/metric/MetricExporterInit.java
@@ -0,0 +1,76 @@
+/*
+ *  Copyright 1999-2021 Alibaba Group Holding Ltd.
+ *
+ *  Licensed 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 com.alibaba.csp.sentinel.metric;
+
+import com.alibaba.csp.sentinel.init.InitFunc;
+import com.alibaba.csp.sentinel.log.RecordLog;
+import com.alibaba.csp.sentinel.metric.collector.MetricCollector;
+import com.alibaba.csp.sentinel.metric.exporter.MetricExporter;
+import com.alibaba.csp.sentinel.metric.exporter.jmx.JMXMetricExporter;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The{@link MetricExporterInit} work on load Metric exporters.
+ *
+ * @author chenglu
+ * @date 2021-07-01 19:58
+ * @since 1.8.3
+ */
+public class MetricExporterInit implements InitFunc {
+    
+    /**
+     * the list of metric exporters.
+     */
+    private static List<MetricExporter> metricExporters = new ArrayList<>();
+    
+    /*
+      load metric exporters.
+     */
+    static {
+        // now we use this simple way to load MetricExporter.
+        metricExporters.add(new JMXMetricExporter());
+    }
+    
+    @Override
+    public void init() throws Exception {
+        RecordLog.info("[MetricExporterInit] MetricExporter start init.");
+        // start the metric exporters.
+        for (MetricExporter metricExporter : metricExporters) {
+           try {
+               metricExporter.start();
+           } catch (Exception e) {
+               RecordLog.warn("[MetricExporterInit] MetricExporterInit start the metricExport[{}] failed, will ignore it.",
+                       metricExporter.getClass().getName(), e);
+           }
+        }
+        
+        // add shutdown hook.
+        Runtime.getRuntime().addShutdownHook(new Thread(
+                () -> metricExporters.forEach(metricExporter -> {
+                    try {
+                        metricExporter.shutdown();
+                    } catch (Exception e) {
+                        RecordLog.warn("[MetricExporterInit] MetricExporterInit shutdown the metricExport[{}] failed, will ignore it.",
+                                metricExporter.getClass().getName(), e);
+                    }
+                })
+        ));
+    }
+}
diff --git a/sentinel-extension/sentinel-metric-exporter/src/main/java/com/alibaba/csp/sentinel/metric/collector/MetricCollector.java b/sentinel-extension/sentinel-metric-exporter/src/main/java/com/alibaba/csp/sentinel/metric/collector/MetricCollector.java
new file mode 100644
index 00000000..ee940e60
--- /dev/null
+++ b/sentinel-extension/sentinel-metric-exporter/src/main/java/com/alibaba/csp/sentinel/metric/collector/MetricCollector.java
@@ -0,0 +1,94 @@
+/*
+ *  Copyright 1999-2021 Alibaba Group Holding Ltd.
+ *
+ *  Licensed 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 com.alibaba.csp.sentinel.metric.collector;
+
+import com.alibaba.csp.sentinel.Constants;
+import com.alibaba.csp.sentinel.node.ClusterNode;
+import com.alibaba.csp.sentinel.node.metric.MetricNode;
+import com.alibaba.csp.sentinel.slotchain.ResourceWrapper;
+import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot;
+import com.alibaba.csp.sentinel.util.TimeUtil;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * The {@link MetricCollector} work on collecting metrics in {@link MetricNode}.
+ *
+ * @author chenglu
+ * @date 2021-07-01 20:01
+ * @since 1.8.3
+ */
+public class MetricCollector {
+    
+    /**
+     * collect the metrics in {@link MetricNode}.
+     *
+     * @return the metric grouped by resource name.
+     */
+    public Map<String, MetricNode> collectMetric() {
+        final long currentTime = TimeUtil.currentTimeMillis();
+        final long maxTime = currentTime - currentTime % 1000;
+        final long minTime = maxTime - 1000;
+        Map<String, MetricNode> metricNodeMap = new HashMap<>();
+        for (Map.Entry<ResourceWrapper, ClusterNode> e : ClusterBuilderSlot.getClusterNodeMap().entrySet()) {
+            ClusterNode node = e.getValue();
+            List<MetricNode> metrics = getLastMetrics(node, minTime, maxTime);
+            aggregate(metricNodeMap, metrics, node);
+        }
+        aggregate(metricNodeMap, getLastMetrics(Constants.ENTRY_NODE, minTime, maxTime), Constants.ENTRY_NODE);
+        return metricNodeMap;
+    }
+    
+    
+    /**
+     * Get the last second {@link MetricNode} of {@link ClusterNode}
+     * @param node {@link ClusterNode}
+     * @param minTime the min time.
+     * @param maxTime the max time.
+     * @return the list of {@link MetricNode}
+     */
+    private List<MetricNode> getLastMetrics(ClusterNode node, long minTime, long maxTime) {
+        return node.rawMetricsInMin(time -> time >= minTime && time < maxTime);
+    }
+    
+    
+    /**
+     * aggregate the metrics, the metrics under the same resource will left the lasted value
+     * @param metricNodeMap metrics map
+     * @param metrics metrics info group by timestamp
+     * @param node the node
+     */
+    private void aggregate(Map<String, MetricNode> metricNodeMap, List<MetricNode> metrics, ClusterNode node) {
+        if (metrics == null || metrics.size() == 0) {
+            return;
+        }
+        for (MetricNode metricNode : metrics) {
+            String resource = node.getName();
+            metricNode.setResource(resource);
+            metricNode.setClassification(node.getResourceType());
+            MetricNode existMetricNode = metricNodeMap.get(resource);
+            // always keep the MetricNode is the last
+            if (existMetricNode != null && existMetricNode.getTimestamp() > metricNode.getTimestamp()) {
+                continue;
+            }
+            metricNodeMap.put(resource, metricNode);
+        }
+    }
+}
diff --git a/sentinel-extension/sentinel-metric-exporter/src/main/java/com/alibaba/csp/sentinel/metric/exporter/MetricExporter.java b/sentinel-extension/sentinel-metric-exporter/src/main/java/com/alibaba/csp/sentinel/metric/exporter/MetricExporter.java
new file mode 100644
index 00000000..f08eb1d5
--- /dev/null
+++ b/sentinel-extension/sentinel-metric-exporter/src/main/java/com/alibaba/csp/sentinel/metric/exporter/MetricExporter.java
@@ -0,0 +1,49 @@
+/*
+ *  Copyright 1999-2021 Alibaba Group Holding Ltd.
+ *
+ *  Licensed 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 com.alibaba.csp.sentinel.metric.exporter;
+
+/**
+ * {@link MetricExporter} work on export metric to target monitor.
+ * you can implement your export ways by this class.
+ *
+ * @author chenglu
+ * @date 2021-07-01 21:16
+ */
+public interface MetricExporter {
+    
+    /**
+     * start the {@link MetricExporter}.
+     *
+     * @throws Exception start exception.
+     */
+    void start() throws Exception;
+    
+    /**
+     * export the data to target monitor by the implement.
+     *
+     * @throws Exception export exception.
+     */
+    void export() throws Exception;
+    
+    /**
+     * shutdown the {@link MetricExporter}.
+     *
+     * @throws Exception shutdown exception.
+     */
+    void shutdown() throws Exception;
+}
diff --git a/sentinel-extension/sentinel-metric-exporter/src/main/java/com/alibaba/csp/sentinel/metric/exporter/jmx/JMXMetricExporter.java b/sentinel-extension/sentinel-metric-exporter/src/main/java/com/alibaba/csp/sentinel/metric/exporter/jmx/JMXMetricExporter.java
new file mode 100644
index 00000000..cab682c5
--- /dev/null
+++ b/sentinel-extension/sentinel-metric-exporter/src/main/java/com/alibaba/csp/sentinel/metric/exporter/jmx/JMXMetricExporter.java
@@ -0,0 +1,88 @@
+/*
+ *  Copyright 1999-2021 Alibaba Group Holding Ltd.
+ *
+ *  Licensed 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 com.alibaba.csp.sentinel.metric.exporter.jmx;
+
+import com.alibaba.csp.sentinel.concurrent.NamedThreadFactory;
+import com.alibaba.csp.sentinel.log.RecordLog;
+import com.alibaba.csp.sentinel.metric.collector.MetricCollector;
+import com.alibaba.csp.sentinel.metric.exporter.MetricExporter;
+
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * The JMX metric exporter, mainly for write metric datas to JMX bean. It implement {@link MetricExporter}, provide method
+ * start, export and shutdown. The mainly design for the jmx is refresh the JMX bean data scheduled.
+ * {@link JMXExportTask} work on export data to {@link MetricBean}.
+ *
+ * @author chenglu
+ * @date 2021-07-01 20:02
+ * @since 1.8.3
+ */
+public class JMXMetricExporter implements MetricExporter {
+    
+    /**
+     * schedule executor.
+     */
+    private final ScheduledExecutorService jmxExporterSchedule;
+    
+    /**
+     * JMX metric writer, write metric datas to {@link MetricBean}.
+     */
+    private final MetricBeanWriter metricBeanWriter = new MetricBeanWriter();
+    
+    /**
+     * global metrics collector.
+     */
+    private final MetricCollector metricCollector = new MetricCollector();
+    
+    public JMXMetricExporter() {
+        jmxExporterSchedule = new ScheduledThreadPoolExecutor(1, new NamedThreadFactory("sentinel-metrics-jmx-exporter-task", true));
+    }
+    
+    @Override
+    public void start() throws Exception {
+        jmxExporterSchedule.scheduleAtFixedRate(new JMXExportTask(), 1, 1, TimeUnit.SECONDS);
+    }
+    
+    @Override
+    public void export() throws Exception {
+        metricBeanWriter.write(metricCollector.collectMetric());
+    }
+    
+    @Override
+    public void shutdown() throws Exception {
+        jmxExporterSchedule.shutdown();
+    }
+    
+    /**
+     * JMXExportTask mainly work on execute the JMX metric export.
+     */
+    class JMXExportTask implements Runnable {
+        
+        @Override
+        public void run() {
+            try {
+                export();
+            } catch (Exception e) {
+                RecordLog.warn("[JMX Metric Exporter] export to JMX MetricBean failed.", e);
+            }
+        }
+    }
+}
diff --git a/sentinel-extension/sentinel-metric-exporter/src/main/java/com/alibaba/csp/sentinel/metric/exporter/jmx/MBeanRegistry.java b/sentinel-extension/sentinel-metric-exporter/src/main/java/com/alibaba/csp/sentinel/metric/exporter/jmx/MBeanRegistry.java
new file mode 100644
index 00000000..a0168d1a
--- /dev/null
+++ b/sentinel-extension/sentinel-metric-exporter/src/main/java/com/alibaba/csp/sentinel/metric/exporter/jmx/MBeanRegistry.java
@@ -0,0 +1,121 @@
+/*
+ *  Copyright 1999-2021 Alibaba Group Holding Ltd.
+ *
+ *  Licensed 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 com.alibaba.csp.sentinel.metric.exporter.jmx;
+
+import com.alibaba.csp.sentinel.log.RecordLog;
+
+import javax.management.JMException;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.ObjectName;
+import java.lang.management.ManagementFactory;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * This class provides a unified interface for registering/unregistering of Metric MBean.
+ *
+ * @author chenglu
+ * @date 2021-07-01 20:02
+ * @since 1.8.3
+ */
+public class MBeanRegistry {
+    
+    private static volatile MBeanRegistry instance = new MBeanRegistry();
+    
+    private Map<MetricBean, String> mapBean2Name= new ConcurrentHashMap<>(8);
+    
+    private Map<String, MetricBean> mapName2Bean = new ConcurrentHashMap<>(8);
+    
+    private MBeanServer mBeanServer;
+    
+    public static MBeanRegistry getInstance() {
+        return instance;
+    }
+    
+    public MBeanRegistry() {
+        try {
+            mBeanServer = ManagementFactory.getPlatformMBeanServer();
+        } catch (Error e) {
+            // Account for running within IKVM and create a new MBeanServer
+            // if the PlatformMBeanServer does not exist.
+            mBeanServer =  MBeanServerFactory.createMBeanServer();
+        }
+    }
+    
+    /**
+     * Registers a new MBean with the platform MBean server.
+     * @param bean the bean being registered
+     * @param mBeanName the mBeanName
+     * @throws JMException MBean can not register exception
+     */
+    public void register(MetricBean bean, String mBeanName) throws JMException {
+        assert bean != null;
+        try {
+            ObjectName oname = new ObjectName(mBeanName);
+            mBeanServer.registerMBean(bean, oname);
+            mapBean2Name.put(bean, mBeanName);
+            mapName2Bean.put(mBeanName, bean);
+        } catch (JMException e) {
+            RecordLog.warn("[MBeanRegistry] Failed to register MBean " + mBeanName, e);
+            throw e;
+        }
+    }
+    
+    /**
+     * unregister the MetricBean
+     * @param bean MetricBean
+     */
+    public void unRegister(MetricBean bean) {
+        assert bean != null;
+        String beanName = mapBean2Name.get(bean);
+        if (beanName == null) {
+            return;
+        }
+        try {
+            ObjectName objectName = new ObjectName(beanName);
+            mBeanServer.unregisterMBean(objectName);
+            mapBean2Name.remove(bean);
+            mapName2Bean.remove(beanName);
+        } catch (JMException e) {
+            RecordLog.warn("[MBeanRegistry] UnRegister the MetricBean fail", e);
+        }
+    }
+    
+    /**
+     * find the MBean by BeanName
+     * @param mBeanName mBeanName
+     * @return MetricMBean
+     */
+    public MetricBean findMBean(String mBeanName) {
+        if (mBeanName == null) {
+            return null;
+        }
+        return mapName2Bean.get(mBeanName);
+    }
+    
+    /**
+     * list all MBeans which is registered into MBeanRegistry
+     * @return MetricBeans
+     */
+    public List<MetricBean> listAllMBeans() {
+        return new ArrayList<>(mapName2Bean.values());
+    }
+}
diff --git a/sentinel-extension/sentinel-metric-exporter/src/main/java/com/alibaba/csp/sentinel/metric/exporter/jmx/MetricBean.java b/sentinel-extension/sentinel-metric-exporter/src/main/java/com/alibaba/csp/sentinel/metric/exporter/jmx/MetricBean.java
new file mode 100644
index 00000000..2c169c72
--- /dev/null
+++ b/sentinel-extension/sentinel-metric-exporter/src/main/java/com/alibaba/csp/sentinel/metric/exporter/jmx/MetricBean.java
@@ -0,0 +1,154 @@
+/*
+ *  Copyright 1999-2021 Alibaba Group Holding Ltd.
+ *
+ *  Licensed 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 com.alibaba.csp.sentinel.metric.exporter.jmx;
+
+import com.alibaba.csp.sentinel.node.metric.MetricNode;
+
+/**
+ * the MetricBean for JMX expose.
+ *
+ * @author chenglu
+ * @date 2021-07-01 20:02
+ * @since 1.8.3
+ */
+public class MetricBean implements MetricMXBean {
+    
+    private String resource;
+    
+    /**
+     * Resource classification (e.g. SQL or RPC)
+     */
+    private int classification;
+    
+    private long timestamp;
+    
+    private long passQps;
+    
+    private long blockQps;
+    
+    private long successQps;
+    
+    private long exceptionQps;
+    
+    private long rt;
+    
+    private long occupiedPassQps;
+
+    private int concurrency;
+
+    private long version;
+    
+    @Override
+    public String getResource() {
+        return resource;
+    }
+    
+    @Override
+    public int getClassification() {
+        return classification;
+    }
+    
+    @Override
+    public long getTimestamp() {
+        return timestamp;
+    }
+    
+    @Override
+    public long getPassQps() {
+        return passQps;
+    }
+    
+    @Override
+    public long getBlockQps() {
+        return blockQps;
+    }
+    
+    @Override
+    public long getSuccessQps() {
+        return successQps;
+    }
+    
+    @Override
+    public long getExceptionQps() {
+        return exceptionQps;
+    }
+    
+    @Override
+    public long getRt() {
+        return rt;
+    }
+    
+    @Override
+    public long getOccupiedPassQps() {
+        return occupiedPassQps;
+    }
+    
+    @Override
+    public int getConcurrency() {
+        return concurrency;
+    }
+
+    @Override
+    public long getVersion() {
+        return version;
+    }
+
+    /**
+     * set the version to current Mbean.
+     *
+     * @param version current version.
+     */
+    public void setVersion(long version) {
+        this.version = version;
+    }
+
+    /**
+     * reset the MBean value to the initialized value.
+     */
+    public void reset() {
+        this.blockQps = 0;
+        this.passQps = 0;
+        this.timestamp = System.currentTimeMillis();
+        this.exceptionQps = 0;
+        this.occupiedPassQps = 0;
+        this.successQps = 0;
+        this.rt = 0;
+        this.concurrency = 0;
+    }
+    
+    /**
+     * set the MetricBean's value which from MetricNode.
+     *
+     * @param metricNode metric Node for write file
+     */
+    public void setValueFromNode(MetricNode metricNode) {
+        if (metricNode == null) {
+            return;
+        }
+        this.successQps = metricNode.getSuccessQps();
+        this.blockQps = metricNode.getBlockQps();
+        this.passQps = metricNode.getPassQps();
+        this.occupiedPassQps = metricNode.getOccupiedPassQps();
+        this.exceptionQps = metricNode.getExceptionQps();
+        this.timestamp = metricNode.getTimestamp();
+        this.classification = metricNode.getClassification();
+        this.concurrency = metricNode.getConcurrency();
+        this.resource = metricNode.getResource();
+        this.rt = metricNode.getRt();
+    }
+}
diff --git a/sentinel-extension/sentinel-metric-exporter/src/main/java/com/alibaba/csp/sentinel/metric/exporter/jmx/MetricBeanWriter.java b/sentinel-extension/sentinel-metric-exporter/src/main/java/com/alibaba/csp/sentinel/metric/exporter/jmx/MetricBeanWriter.java
new file mode 100644
index 00000000..974d0692
--- /dev/null
+++ b/sentinel-extension/sentinel-metric-exporter/src/main/java/com/alibaba/csp/sentinel/metric/exporter/jmx/MetricBeanWriter.java
@@ -0,0 +1,97 @@
+/*
+ *  Copyright 1999-2021 Alibaba Group Holding Ltd.
+ *
+ *  Licensed 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 com.alibaba.csp.sentinel.metric.exporter.jmx;
+
+import com.alibaba.csp.sentinel.config.SentinelConfig;
+import com.alibaba.csp.sentinel.log.RecordLog;
+import com.alibaba.csp.sentinel.node.metric.MetricNode;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * the metric bean writer, it provides {@link MetricBeanWriter#write} method for register the
+ * MetricBean in {@link MBeanRegistry} or update the value of MetricBean
+ *
+ * @author chenglu
+ * @date 2021-07-01 20:02
+ * @since 1.8.3
+ */
+public class MetricBeanWriter {
+    
+    private final MBeanRegistry mBeanRegistry = MBeanRegistry.getInstance();
+    
+    private static final String DEFAULT_APP_NAME = "sentinel-application";
+    
+    /**
+     * write the MetricNode value to MetricBean
+     * if the MetricBean is not registered into {@link MBeanRegistry},
+     * it will be created and registered into {@link MBeanRegistry}.
+     * else it will update the value of MetricBean.
+     * Notes. if the MetricNode is null, then {@link MetricBean} will be reset.
+     * @param map metricNode value group by resource
+     * @throws Exception write failed exception
+     */
+    public synchronized void write(Map<String, MetricNode> map) throws Exception {
+        if (map == null || map.isEmpty()) {
+            List<MetricBean> metricNodes = mBeanRegistry.listAllMBeans();
+            if (metricNodes == null || metricNodes.isEmpty()) {
+                return;
+            }
+            for (MetricBean metricNode : metricNodes) {
+                metricNode.reset();
+            }
+            return;
+        }
+        String appName = SentinelConfig.getAppName();
+        if (appName == null) {
+            appName = DEFAULT_APP_NAME;
+        }
+        long version = System.currentTimeMillis();
+        // set or update the new value
+        for (MetricNode metricNode : map.values()) {
+            final String mBeanName = "Sentinel:type=" + appName + ",name=\"" + metricNode.getResource()
+                    +"\",classification=\"" + metricNode.getClassification() +"\"";
+            MetricBean metricBean = mBeanRegistry.findMBean(mBeanName);
+            if (metricBean != null) {
+                metricBean.setValueFromNode(metricNode);
+                metricBean.setVersion(version);
+            } else {
+                metricBean = new MetricBean();
+                metricBean.setValueFromNode(metricNode);
+                metricBean.setVersion(version);
+                mBeanRegistry.register(metricBean, mBeanName);
+                RecordLog.info("[MetricBeanWriter] Registering with JMX as Metric MBean [{}]", mBeanName);
+            }
+        }
+        // reset the old value
+        List<MetricBean> metricBeans = mBeanRegistry.listAllMBeans();
+        if (metricBeans == null || metricBeans.isEmpty()) {
+            return;
+        }
+        for (MetricBean metricBean : metricBeans) {
+            if (!Objects.equals(metricBean.getVersion(), version)) {
+                metricBean.reset();
+                mBeanRegistry.unRegister(metricBean);
+            }
+        }
+    }
+}
diff --git a/sentinel-extension/sentinel-metric-exporter/src/main/java/com/alibaba/csp/sentinel/metric/exporter/jmx/MetricMXBean.java b/sentinel-extension/sentinel-metric-exporter/src/main/java/com/alibaba/csp/sentinel/metric/exporter/jmx/MetricMXBean.java
new file mode 100644
index 00000000..dc6697ea
--- /dev/null
+++ b/sentinel-extension/sentinel-metric-exporter/src/main/java/com/alibaba/csp/sentinel/metric/exporter/jmx/MetricMXBean.java
@@ -0,0 +1,50 @@
+/*
+ *  Copyright 1999-2021 Alibaba Group Holding Ltd.
+ *
+ *  Licensed 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 com.alibaba.csp.sentinel.metric.exporter.jmx;
+
+/**
+ * the Metric JMX Bean interface.
+ *
+ * @author chenglu
+ * @date 2021-07-01 20:02
+ * @since 1.8.3
+ */
+public interface MetricMXBean {
+    
+    long getTimestamp();
+    
+    long getOccupiedPassQps();
+    
+    long getSuccessQps();
+    
+    long getPassQps();
+    
+    long getExceptionQps();
+    
+    long getBlockQps();
+    
+    long getRt();
+    
+    String getResource();
+    
+    int getClassification();
+    
+    int getConcurrency();
+
+    long getVersion();
+}
diff --git a/sentinel-extension/sentinel-metric-exporter/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.init.InitFunc b/sentinel-extension/sentinel-metric-exporter/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.init.InitFunc
new file mode 100644
index 00000000..9774e1f0
--- /dev/null
+++ b/sentinel-extension/sentinel-metric-exporter/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.init.InitFunc
@@ -0,0 +1,1 @@
+com.alibaba.csp.sentinel.metric.MetricExporterInit
\ No newline at end of file
diff --git a/sentinel-extension/sentinel-parameter-flow-control/pom.xml b/sentinel-extension/sentinel-parameter-flow-control/pom.xml
index 263b828b..2656d6d9 100644
--- a/sentinel-extension/sentinel-parameter-flow-control/pom.xml
+++ b/sentinel-extension/sentinel-parameter-flow-control/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-extension</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-logging/pom.xml b/sentinel-logging/pom.xml
index 18768307..60cc9a61 100755
--- a/sentinel-logging/pom.xml
+++ b/sentinel-logging/pom.xml
@@ -6,7 +6,7 @@
     <parent>
         <groupId>com.alibaba.csp</groupId>
         <artifactId>sentinel-parent</artifactId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <artifactId>sentinel-logging</artifactId>
     <packaging>pom</packaging>
diff --git a/sentinel-logging/sentinel-logging-slf4j/pom.xml b/sentinel-logging/sentinel-logging-slf4j/pom.xml
index 1eadcd36..274dce71 100644
--- a/sentinel-logging/sentinel-logging-slf4j/pom.xml
+++ b/sentinel-logging/sentinel-logging-slf4j/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-logging</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-transport/pom.xml b/sentinel-transport/pom.xml
index e5ff2ee4..3726b3fd 100755
--- a/sentinel-transport/pom.xml
+++ b/sentinel-transport/pom.xml
@@ -6,7 +6,7 @@
     <parent>
         <groupId>com.alibaba.csp</groupId>
         <artifactId>sentinel-parent</artifactId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <artifactId>sentinel-transport</artifactId>
     <description>The transport module of Sentinel</description>
diff --git a/sentinel-transport/sentinel-transport-common/pom.xml b/sentinel-transport/sentinel-transport-common/pom.xml
index e3a33bf9..2b480d12 100755
--- a/sentinel-transport/sentinel-transport-common/pom.xml
+++ b/sentinel-transport/sentinel-transport-common/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <groupId>com.alibaba.csp</groupId>
         <artifactId>sentinel-transport</artifactId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <packaging>jar</packaging>
diff --git a/sentinel-transport/sentinel-transport-netty-http/pom.xml b/sentinel-transport/sentinel-transport-netty-http/pom.xml
index d6dfbac6..aaefe0bb 100755
--- a/sentinel-transport/sentinel-transport-netty-http/pom.xml
+++ b/sentinel-transport/sentinel-transport-netty-http/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <groupId>com.alibaba.csp</groupId>
         <artifactId>sentinel-transport</artifactId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>sentinel-transport-netty-http</artifactId>
diff --git a/sentinel-transport/sentinel-transport-simple-http/pom.xml b/sentinel-transport/sentinel-transport-simple-http/pom.xml
index 67a7b788..94d4d7af 100755
--- a/sentinel-transport/sentinel-transport-simple-http/pom.xml
+++ b/sentinel-transport/sentinel-transport-simple-http/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-transport</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
diff --git a/sentinel-transport/sentinel-transport-spring-mvc/pom.xml b/sentinel-transport/sentinel-transport-spring-mvc/pom.xml
index d7f9aea7..3e4f140c 100644
--- a/sentinel-transport/sentinel-transport-spring-mvc/pom.xml
+++ b/sentinel-transport/sentinel-transport-spring-mvc/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>sentinel-transport</artifactId>
         <groupId>com.alibaba.csp</groupId>
-        <version>1.8.2</version>
+        <version>1.8.3</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 


Test patch:
diff --git a/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/test/java/com/alibaba/csp/sentinel/cluster/server/envoy/rls/service/v3/SentinelEnvoyRlsServiceImplTest.java b/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/test/java/com/alibaba/csp/sentinel/cluster/server/envoy/rls/service/v3/SentinelEnvoyRlsServiceImplTest.java
new file mode 100644
index 00000000..3ca43e43
--- /dev/null
+++ b/sentinel-cluster/sentinel-cluster-server-envoy-rls/src/test/java/com/alibaba/csp/sentinel/cluster/server/envoy/rls/service/v3/SentinelEnvoyRlsServiceImplTest.java
@@ -0,0 +1,109 @@
+package com.alibaba.csp.sentinel.cluster.server.envoy.rls.service.v3;
+
+import com.alibaba.csp.sentinel.cluster.TokenResult;
+import com.alibaba.csp.sentinel.cluster.TokenResultStatus;
+import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
+import com.alibaba.csp.sentinel.util.function.Tuple2;
+
+import io.envoyproxy.envoy.extensions.common.ratelimit.v3.RateLimitDescriptor;
+import io.envoyproxy.envoy.service.ratelimit.v3.RateLimitRequest;
+import io.envoyproxy.envoy.service.ratelimit.v3.RateLimitResponse;
+import io.grpc.stub.StreamObserver;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import static org.junit.Assert.*;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.same;
+import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.when;
+
+/**
+ * Created by Winjay
+ *
+ * @author Winjay chan
+ * @date 2021/8/13 16:31
+ */
+public class SentinelEnvoyRlsServiceImplTest {
+    @Test
+    public void testShouldRateLimitPass() {
+        SentinelEnvoyRlsServiceImpl rlsService = mock(SentinelEnvoyRlsServiceImpl.class);
+        StreamObserver<RateLimitResponse> streamObserver = mock(StreamObserver.class);
+        String domain = "testShouldRateLimitPass";
+        int acquireCount = 1;
+
+        RateLimitDescriptor descriptor1 = RateLimitDescriptor.newBuilder()
+                .addEntries(RateLimitDescriptor.Entry.newBuilder().setKey("rk1").setValue("rv1").build())
+                .build();
+        RateLimitDescriptor descriptor2 = RateLimitDescriptor.newBuilder()
+                .addEntries(RateLimitDescriptor.Entry.newBuilder().setKey("rk2").setValue("rv2").build())
+                .addEntries(RateLimitDescriptor.Entry.newBuilder().setKey("rk3").setValue("rv3").build())
+                .build();
+
+        ArgumentCaptor<RateLimitResponse> responseCapture = ArgumentCaptor.forClass(RateLimitResponse.class);
+        doNothing().when(streamObserver)
+                .onNext(responseCapture.capture());
+
+        doCallRealMethod().when(rlsService).shouldRateLimit(any(), any());
+        when(rlsService.checkToken(eq(domain), same(descriptor1), eq(acquireCount)))
+                .thenReturn(Tuple2.of(new FlowRule(), new TokenResult(TokenResultStatus.OK)));
+        when(rlsService.checkToken(eq(domain), same(descriptor2), eq(acquireCount)))
+                .thenReturn(Tuple2.of(new FlowRule(), new TokenResult(TokenResultStatus.OK)));
+
+        RateLimitRequest rateLimitRequest = RateLimitRequest.newBuilder()
+                .addDescriptors(descriptor1)
+                .addDescriptors(descriptor2)
+                .setDomain(domain)
+                .setHitsAddend(acquireCount)
+                .build();
+        rlsService.shouldRateLimit(rateLimitRequest, streamObserver);
+
+        RateLimitResponse response = responseCapture.getValue();
+        assertEquals(RateLimitResponse.Code.OK, response.getOverallCode());
+        response.getStatusesList()
+                .forEach(e -> assertEquals(RateLimitResponse.Code.OK, e.getCode()));
+    }
+
+    @Test
+    public void testShouldRatePartialBlock() {
+        SentinelEnvoyRlsServiceImpl rlsService = mock(SentinelEnvoyRlsServiceImpl.class);
+        StreamObserver<RateLimitResponse> streamObserver = mock(StreamObserver.class);
+        String domain = "testShouldRatePartialBlock";
+        int acquireCount = 1;
+
+        RateLimitDescriptor descriptor1 = RateLimitDescriptor.newBuilder()
+                .addEntries(RateLimitDescriptor.Entry.newBuilder().setKey("rk1").setValue("rv1").build())
+                .build();
+        RateLimitDescriptor descriptor2 = RateLimitDescriptor.newBuilder()
+                .addEntries(RateLimitDescriptor.Entry.newBuilder().setKey("rk2").setValue("rv2").build())
+                .addEntries(RateLimitDescriptor.Entry.newBuilder().setKey("rk3").setValue("rv3").build())
+                .build();
+
+        ArgumentCaptor<RateLimitResponse> responseCapture = ArgumentCaptor.forClass(RateLimitResponse.class);
+        doNothing().when(streamObserver)
+                .onNext(responseCapture.capture());
+
+        doCallRealMethod().when(rlsService).shouldRateLimit(any(), any());
+        when(rlsService.checkToken(eq(domain), same(descriptor1), eq(acquireCount)))
+                .thenReturn(Tuple2.of(new FlowRule(), new TokenResult(TokenResultStatus.BLOCKED)));
+        when(rlsService.checkToken(eq(domain), same(descriptor2), eq(acquireCount)))
+                .thenReturn(Tuple2.of(new FlowRule(), new TokenResult(TokenResultStatus.OK)));
+
+        RateLimitRequest rateLimitRequest = RateLimitRequest.newBuilder()
+                .addDescriptors(descriptor1)
+                .addDescriptors(descriptor2)
+                .setDomain(domain)
+                .setHitsAddend(acquireCount)
+                .build();
+        rlsService.shouldRateLimit(rateLimitRequest, streamObserver);
+
+        RateLimitResponse response = responseCapture.getValue();
+        assertEquals(RateLimitResponse.Code.OVER_LIMIT, response.getOverallCode());
+        assertEquals(2, response.getStatusesCount());
+        assertTrue(response.getStatusesList().stream()
+                .anyMatch(e -> e.getCode().equals(RateLimitResponse.Code.OVER_LIMIT)));
+        assertFalse(response.getStatusesList().stream()
+                .allMatch(e -> e.getCode().equals(RateLimitResponse.Code.OVER_LIMIT)));
+    }
+}
diff --git a/sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/system/SystemRuleManagerTest.java b/sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/system/SystemRuleManagerTest.java
index fcd1f665..2e7ac3a3 100644
--- a/sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/system/SystemRuleManagerTest.java
+++ b/sentinel-core/src/test/java/com/alibaba/csp/sentinel/slots/system/SystemRuleManagerTest.java
@@ -92,7 +92,8 @@ public class SystemRuleManagerTest {
 
         boolean blocked = false;
         try {
-            SystemRuleManager.checkSystem(new StringResourceWrapper("testCheckMaxCpuUsageNotBBR", EntryType.IN));
+            StringResourceWrapper resourceWrapper = new StringResourceWrapper("testCheckMaxCpuUsageNotBBR", EntryType.IN);
+            SystemRuleManager.checkSystem(resourceWrapper, 1);
         } catch (BlockException ex) {
             blocked = true;
         }
diff --git a/sentinel-extension/sentinel-metric-exporter/src/test/java/com/alibaba/cps/sentinel/metric/exporter/MBeanRegistryTest.java b/sentinel-extension/sentinel-metric-exporter/src/test/java/com/alibaba/cps/sentinel/metric/exporter/MBeanRegistryTest.java
new file mode 100644
index 00000000..d07e0726
--- /dev/null
+++ b/sentinel-extension/sentinel-metric-exporter/src/test/java/com/alibaba/cps/sentinel/metric/exporter/MBeanRegistryTest.java
@@ -0,0 +1,34 @@
+package com.alibaba.cps.sentinel.metric.exporter;
+
+import com.alibaba.csp.sentinel.metric.exporter.jmx.MBeanRegistry;
+import com.alibaba.csp.sentinel.metric.exporter.jmx.MetricBean;
+import org.junit.Assert;
+import org.junit.Test;
+
+import javax.management.JMException;
+
+/**
+ * {@link com.alibaba.csp.sentinel.metric.exporter.jmx.MBeanRegistry} unit test.
+ *
+ * @author chenglu
+ * @date 2021-07-01 23:07
+ */
+public class MBeanRegistryTest {
+    
+    @Test
+    public void testMBeanRegistry() throws JMException {
+        MBeanRegistry mBeanRegistry = MBeanRegistry.getInstance();
+    
+        MetricBean metricBean = new MetricBean();
+        String mBeanName = "Sentinel:type=test,name=test";
+        mBeanRegistry.register(metricBean, mBeanName);
+        
+        MetricBean mb1 = mBeanRegistry.findMBean(mBeanName);
+        Assert.assertEquals(mb1, metricBean);
+        
+        mBeanRegistry.unRegister(metricBean);
+    
+        MetricBean mb2 = mBeanRegistry.findMBean(mBeanName);
+        Assert.assertNull(mb2);
+    }
+}