You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shenyu.apache.org by he...@apache.org on 2023/09/06 01:02:05 UTC

[shenyu] branch master updated: [type:refactor] Refactor grpc. (#5115)

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

hefengen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shenyu.git


The following commit(s) were added to refs/heads/master by this push:
     new f0ac2ccbff [type:refactor] Refactor grpc.  (#5115)
f0ac2ccbff is described below

commit f0ac2ccbff937253a6ab785a15b625c651bf60fd
Author: yunlongn <yu...@outlook.com>
AuthorDate: Wed Sep 6 09:01:59 2023 +0800

    [type:refactor] Refactor grpc.  (#5115)
    
    * [type:refactor] refactor grpc.
    
    * [type:feat] add idea project logo.
    
    * [type:feat] add idea project logo.
    
    * [type:feat] add idea project logo.
    
    * [type:refactor] refactor grpc.
    
    * [type:refactor] refactor grpc.
    
    * [type:refactor] refactor grpc.
    
    * [type:refactor] refactor grpc.
    
    * [type:refactor] refactor grpc.
    
    * [type:refactor] refactor grpc.
    
    ---------
    
    Co-authored-by: xiaoyu <xi...@apache.org>
    Co-authored-by: likeguo <33...@users.noreply.github.com>
---
 db/init/mysql/schema.sql                           |   1 +
 db/init/og/create-table.sql                        |   2 +-
 db/init/oracle/schema.sql                          |   3 +
 db/init/pg/create-table.sql                        |   1 +
 .../src/main/resources/sql-script/h2/schema.sql    |   2 +-
 .../dto/convert/rule/impl/GrpcRuleHandle.java      |  86 ++++++++++++++++
 .../examples/grpc/ShenyuGrpcServerBuilder.java     |   6 +-
 .../test/grpc/GrpcPluginSharedThreadPoolTest.java  |   2 +-
 .../shenyu-plugin-rpc/shenyu-plugin-grpc/pom.xml   |   5 +
 .../org/apache/shenyu/plugin/grpc/GrpcPlugin.java  |   8 +-
 .../plugin/grpc/cache/ApplicationConfigCache.java  | 112 ++++++++++++++-------
 .../shenyu/plugin/grpc/cache/GrpcClientCache.java  |  18 ++--
 .../plugin/grpc/client/GrpcClientBuilder.java      |  10 +-
 .../GrpcConstants.java}                            |  36 ++++---
 .../plugin/grpc/handler/GrpcPluginDataHandler.java |  26 ++++-
 .../grpc/loadbalance/LoadBalancerStrategy.java     |   6 +-
 .../ShenyuLoadBalancerProvider.java}               |  37 ++++---
 .../plugin/grpc/loadbalance/SubChannelCopy.java    |  17 +++-
 .../plugin/grpc/loadbalance/SubChannels.java       |  18 +++-
 .../grpc/loadbalance/picker/ShenyuPicker.java      |  76 ++++++++++++++
 .../plugin/grpc/resolver/ShenyuNameResolver.java   |  63 ++++--------
 .../grpc/resolver/ShenyuNameResolverProvider.java  |   2 +-
 .../plugin/grpc/resolver/ShenyuResolverHelper.java |  11 +-
 .../apache/shenyu/plugin/grpc/GrpcPluginTest.java  |   1 +
 .../grpc/cache/ApplicationConfigCacheTest.java     |   6 --
 .../grpc/handler/GrpcPluginDataHandlerTest.java    |  12 +--
 .../grpc/loadbalance/picker/RandomPickerTest.java  |   2 +-
 .../loadbalance/picker/RoundRobinPickerTest.java   |   2 +-
 .../grpc/resolver/ShenyuResolverHelperTest.java    |   7 +-
 29 files changed, 414 insertions(+), 164 deletions(-)

diff --git a/db/init/mysql/schema.sql b/db/init/mysql/schema.sql
index 023d1cae83..a351736708 100644
--- a/db/init/mysql/schema.sql
+++ b/db/init/mysql/schema.sql
@@ -1162,6 +1162,7 @@ INSERT INTO `plugin_handle` VALUES ('1678997557628272640', '42', 'clientPendingA
 
 INSERT INTO `plugin_handle` VALUES ('1678997557628272641', '17', 'registerAddress', 'registerAddress', 2, 3, 1, '{\"required\":\"0\",\"defaultValue\":\"127.0.0.1:2181\",\"placeholder\":\"registerAddress\",\"rule\":\"\"}', '2023-01-10 10:08:01.158', '2023-01-10 10:08:01.158');
 
+INSERT INTO `plugin_handle` VALUES ('1678997557628272642', '15', 'loadBalance', 'loadBalance', 3, 2, 3, '{\"required\":\"0\",\"defaultValue\":\"random\",\"rule\":\"\"}', '2023-09-05 18:02:53', '2023-09-05 18:02:53');
 -- ----------------------------
 -- Table structure for resource
 -- ----------------------------
diff --git a/db/init/og/create-table.sql b/db/init/og/create-table.sql
index 4614330738..8b536a419e 100644
--- a/db/init/og/create-table.sql
+++ b/db/init/og/create-table.sql
@@ -1312,7 +1312,7 @@ INSERT INTO "public"."plugin_handle" VALUES ('1678996921914392576', '42', 'loadB
 INSERT INTO "public"."plugin_handle" VALUES ('1678997769998467072', '42', 'clientMaxLifeTimeMs', 'clientMaxLifeTimeMs', 2, 1, 8, '{"required":"0","defaultValue":"60000","rule":""}');
 INSERT INTO "public"."plugin_handle" VALUES ('1678997277012557824', '42', 'clientMaxConnections', 'clientMaxConnections', 2, 1, 6, '{"required":"0","defaultValue":"20","rule":""}');
 INSERT INTO "public"."plugin_handle" VALUES ('1678997557628272640', '42', 'clientPendingAcquireTimeout', 'clientPendingAcquireTimeout', 2, 1, 5, '{"required":"0","defaultValue":"5","rule":""}');
-
+INSERT INTO "public"."plugin_handle" VALUES ('1570591265492312085', '6', 'loadBalance', 'loadBalance', 3, 2, 3, '{"required":"0","defaultValue":"random","rule":""}', '2023-09-05 18:08:01', '2023-09-05 18:08:01');
 -- ----------------------------
 -- Table structure for resource
 -- ----------------------------
diff --git a/db/init/oracle/schema.sql b/db/init/oracle/schema.sql
index 88f6ba4f73..bd18a04c38 100644
--- a/db/init/oracle/schema.sql
+++ b/db/init/oracle/schema.sql
@@ -2067,6 +2067,9 @@ VALUES ('1678997277012557824', '42', 'clientMaxConnections', 'clientMaxConnectio
 INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) */ INTO plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, EXT_OBJ)
 VALUES ('1678997557628272640', '42', 'clientPendingAcquireTimeout', 'clientPendingAcquireTimeout', 2, 1, 5, '{"required":"0","defaultValue":"5","rule":""}');
 
+insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(plugin_handle(plugin_id, field, type)) */ into plugin_handle (ID, PLUGIN_ID, FIELD, LABEL, DATA_TYPE, TYPE, SORT, EXT_OBJ)
+values ('1529402613204172883', '15', 'loadBalance', 'loadBalance', 3, 2, 3, '{"required":"0","defaultValue":"random","rule":""}');
+
 
 insert /*+ IGNORE_ROW_ON_DUPKEY_INDEX(shenyu_dict(type, dict_code, dict_name)) */ into SHENYU_DICT (ID, TYPE, DICT_CODE, DICT_NAME, DICT_VALUE, "desc", SORT, ENABLED)
 VALUES ('1529402613195784272', 'securityProtocol', 'SECURITY_PROTOCOL', 'PLAINTEXT', 'PLAINTEXT', '', 1, 1);
diff --git a/db/init/pg/create-table.sql b/db/init/pg/create-table.sql
index cbbb1e5e2f..08ae8f3420 100644
--- a/db/init/pg/create-table.sql
+++ b/db/init/pg/create-table.sql
@@ -1312,6 +1312,7 @@ INSERT INTO "public"."plugin_handle" VALUES ('1678997769998467072', '42', 'clien
 INSERT INTO "public"."plugin_handle" VALUES ('1678997277012557824', '42', 'clientMaxConnections', 'clientMaxConnections', 2, 1, 6, '{"required":"0","defaultValue":"20","rule":""}');
 INSERT INTO "public"."plugin_handle" VALUES ('1678997557628272640', '42', 'clientPendingAcquireTimeout', 'clientPendingAcquireTimeout', 2, 1, 5, '{"required":"0","defaultValue":"5","rule":""}');
 
+INSERT INTO "public"."plugin_handle" VALUES ('1570591265492312085', '6', 'loadBalance', 'loadBalance', 3, 2, 3, '{"required":"0","defaultValue":"random","rule":""}', '2022-05-25 18:08:01', '2022-05-25 18:08:01');
 -- ----------------------------
 -- Table structure for resource
 -- ----------------------------
diff --git a/shenyu-admin/src/main/resources/sql-script/h2/schema.sql b/shenyu-admin/src/main/resources/sql-script/h2/schema.sql
index 1ca3604984..c7f5188635 100755
--- a/shenyu-admin/src/main/resources/sql-script/h2/schema.sql
+++ b/shenyu-admin/src/main/resources/sql-script/h2/schema.sql
@@ -864,7 +864,7 @@ INSERT IGNORE INTO plugin_handle (`id`, `plugin_id`,`field`,`label`,`data_type`,
 
 INSERT IGNORE INTO plugin_handle (`id`, `plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES ('1678997557628272641', '17', 'registerAddress', 'registerAddress', 2, 3, 1,'{"required":"0","defaultValue":"127.0.0.1:2181","placeholder":"registerAddress","rule":""}');
 
-
+INSERT IGNORE INTO plugin_handle (`id`, `plugin_id`,`field`,`label`,`data_type`,`type`,`sort`,`ext_obj`) VALUES ('1678997557628272642', '15', 'loadBalance', 'loadBalance', 3, 2, 3, '{"required":"0","defaultValue":"random","rule":""}');
 
 /** insert resource for resource */
 INSERT IGNORE INTO `resource` (`id`, `parent_id`, `title`, `name`, `url`, `component`, `resource_type`, `sort`, `icon`, `is_leaf`, `is_route`, `perms`, `status`) VALUES('1346775491550474240','','SHENYU.MENU.PLUGIN.LIST','plug','/plug','PluginList','0','0','dashboard','0','0','','1');
diff --git a/shenyu-common/src/main/java/org/apache/shenyu/common/dto/convert/rule/impl/GrpcRuleHandle.java b/shenyu-common/src/main/java/org/apache/shenyu/common/dto/convert/rule/impl/GrpcRuleHandle.java
new file mode 100644
index 0000000000..2fa8a8fbf1
--- /dev/null
+++ b/shenyu-common/src/main/java/org/apache/shenyu/common/dto/convert/rule/impl/GrpcRuleHandle.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.common.dto.convert.rule.impl;
+
+import org.apache.shenyu.common.dto.convert.rule.RuleHandle;
+import org.apache.shenyu.common.enums.LoadBalanceEnum;
+
+import java.util.Objects;
+
+/**
+ * The type Grpc rule handle.
+ */
+public class GrpcRuleHandle implements RuleHandle {
+
+    /**
+     * the loadBalance.
+     * {@linkplain LoadBalanceEnum}
+     */
+    private String loadBalance = LoadBalanceEnum.RANDOM.getName();
+    
+    /**
+     * New instance Grpc rule handle.
+     *
+     * @return the Grpc rule handle
+     */
+    public static GrpcRuleHandle newInstance() {
+        return new GrpcRuleHandle();
+    }
+    
+    /**
+     * Gets the value of loadBalance.
+     *
+     * @return the value of loadBalance
+     */
+    public String getLoadBalance() {
+        return loadBalance;
+    }
+    
+    /**
+     * Sets the loadBalance.
+     *
+     * @param loadBalance loadBalance
+     */
+    public void setLoadBalance(final String loadBalance) {
+        this.loadBalance = loadBalance;
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof GrpcRuleHandle)) {
+            return false;
+        }
+        GrpcRuleHandle that = (GrpcRuleHandle) o;
+        return Objects.equals(loadBalance, that.loadBalance);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(loadBalance);
+    }
+
+    @Override
+    public String toString() {
+        return "GrpcRuleHandle{"
+                + "loadBalance='" + loadBalance + '\''
+                + '}';
+    }
+}
diff --git a/shenyu-examples/shenyu-examples-grpc/src/main/java/org/apache/shenyu/examples/grpc/ShenyuGrpcServerBuilder.java b/shenyu-examples/shenyu-examples-grpc/src/main/java/org/apache/shenyu/examples/grpc/ShenyuGrpcServerBuilder.java
index 44f773ff6b..bf4b031da6 100644
--- a/shenyu-examples/shenyu-examples-grpc/src/main/java/org/apache/shenyu/examples/grpc/ShenyuGrpcServerBuilder.java
+++ b/shenyu-examples/shenyu-examples-grpc/src/main/java/org/apache/shenyu/examples/grpc/ShenyuGrpcServerBuilder.java
@@ -19,6 +19,7 @@ package org.apache.shenyu.examples.grpc;
 
 import io.grpc.ServerBuilder;
 import org.apache.shenyu.client.grpc.server.GrpcServerBuilder;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Component;
 
 /**
@@ -27,8 +28,11 @@ import org.springframework.stereotype.Component;
 @Component
 public class ShenyuGrpcServerBuilder implements GrpcServerBuilder {
 
+    @Value("${shenyu.client.grpc.props.port}")
+    private Integer port;
+
     @Override
     public ServerBuilder<?> buildServerBuilder() {
-        return ServerBuilder.forPort(38080);
+        return ServerBuilder.forPort(port);
     }
 }
diff --git a/shenyu-integrated-test/shenyu-integrated-test-grpc/src/test/java/org/apache/shenyu/integrated/test/grpc/GrpcPluginSharedThreadPoolTest.java b/shenyu-integrated-test/shenyu-integrated-test-grpc/src/test/java/org/apache/shenyu/integrated/test/grpc/GrpcPluginSharedThreadPoolTest.java
index f90435ea9b..c220ff0ff5 100644
--- a/shenyu-integrated-test/shenyu-integrated-test-grpc/src/test/java/org/apache/shenyu/integrated/test/grpc/GrpcPluginSharedThreadPoolTest.java
+++ b/shenyu-integrated-test/shenyu-integrated-test-grpc/src/test/java/org/apache/shenyu/integrated/test/grpc/GrpcPluginSharedThreadPoolTest.java
@@ -37,7 +37,7 @@ public class GrpcPluginSharedThreadPoolTest extends AbstractPluginDataInit {
     
     @BeforeAll
     public static void setup() throws IOException {
-        String pluginResult = initPlugin(PluginEnum.GRPC.getName(), "{\"register\":\"zookeeper://shenyu-zk:2181\",\"threadpool\": \"shared\"}");
+        String pluginResult = initPlugin(PluginEnum.GRPC.getName(), "{\"register\":\"zookeeper://localhost:2181\",\"threadpool\": \"shared\"}");
         assertThat(pluginResult, is("success"));
     }
 
diff --git a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/pom.xml b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/pom.xml
index cc41d8db90..ed2c67062f 100644
--- a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/pom.xml
+++ b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/pom.xml
@@ -41,5 +41,10 @@
             <artifactId>grpc-netty</artifactId>
             <groupId>io.grpc</groupId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.shenyu</groupId>
+            <artifactId>shenyu-loadbalancer</artifactId>
+            <version>${project.version}</version>
+        </dependency>
     </dependencies>
 </project>
diff --git a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/GrpcPlugin.java b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/GrpcPlugin.java
index 11a96ef660..85ba597d5f 100644
--- a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/GrpcPlugin.java
+++ b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/GrpcPlugin.java
@@ -38,6 +38,7 @@ import org.apache.shenyu.plugin.api.utils.WebFluxResultUtils;
 import org.apache.shenyu.plugin.base.AbstractShenyuPlugin;
 import org.apache.shenyu.plugin.grpc.cache.GrpcClientCache;
 import org.apache.shenyu.plugin.grpc.client.ShenyuGrpcClient;
+import org.apache.shenyu.plugin.grpc.context.GrpcConstants;
 import org.apache.shenyu.plugin.grpc.proto.ShenyuGrpcResponse;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -80,12 +81,17 @@ public class GrpcPlugin extends AbstractShenyuPlugin {
             return WebFluxResultUtils.result(exchange, error);
         }
 
-        final ShenyuGrpcClient client = GrpcClientCache.getGrpcClient(selector.getName());
+        final ShenyuGrpcClient client = GrpcClientCache.getGrpcClient(selector.getId());
         if (Objects.isNull(client)) {
             exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
             Object error = ShenyuResultWrap.error(exchange, ShenyuResultEnum.GRPC_CLIENT_NULL);
             return WebFluxResultUtils.result(exchange, error);
         }
+        // load balance context
+        Context.current().withValue(GrpcConstants.GRPC_SELECTOR_ID, selector.getId()).attach();
+        Context.current().withValue(GrpcConstants.GRPC_RULE_ID, rule.getId()).attach();
+        Context.current().withValue(GrpcConstants.GRPC_REMOTE_ADDRESS,
+                Objects.requireNonNull(exchange.getRequest().getRemoteAddress()).getAddress().getHostAddress()).attach();
 
         GrpcExtInfo extInfo = GsonUtils.getGson().fromJson(metaData.getRpcExt(), GrpcExtInfo.class);
         CallOptions callOptions = CallOptions.DEFAULT.withDeadlineAfter(extInfo.timeout, TimeUnit.MILLISECONDS);
diff --git a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/cache/ApplicationConfigCache.java b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/cache/ApplicationConfigCache.java
index 79b603c843..e28f8e5adf 100644
--- a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/cache/ApplicationConfigCache.java
+++ b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/cache/ApplicationConfigCache.java
@@ -23,12 +23,16 @@ import com.google.common.cache.LoadingCache;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.shenyu.common.constant.Constants;
 import org.apache.shenyu.common.dto.SelectorData;
+import org.apache.shenyu.common.dto.convert.rule.impl.GrpcRuleHandle;
 import org.apache.shenyu.common.dto.convert.selector.GrpcUpstream;
 import org.apache.shenyu.common.exception.ShenyuException;
 import org.apache.shenyu.common.utils.GsonUtils;
-import org.apache.shenyu.plugin.grpc.resolver.ShenyuServiceInstance;
+import org.apache.shenyu.plugin.base.cache.CommonHandleCache;
+import org.apache.shenyu.plugin.base.utils.BeanHolder;
+import org.apache.shenyu.plugin.base.utils.CacheKeyUtils;
 import org.apache.shenyu.plugin.grpc.resolver.ShenyuServiceInstanceLists;
 import org.springframework.lang.NonNull;
+import org.springframework.util.StringUtils;
 
 import java.util.List;
 import java.util.Map;
@@ -36,13 +40,17 @@ import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ExecutionException;
 import java.util.function.Consumer;
-import java.util.stream.Collectors;
+import java.util.function.Supplier;
 
 /**
  * Grpc config cache.
  */
 public final class ApplicationConfigCache {
-    
+
+    private final Supplier<CommonHandleCache<String, List<GrpcUpstream>>> grpcUpstreamCachedHandle = new BeanHolder<>(CommonHandleCache::new);
+
+    private final Supplier<CommonHandleCache<String, GrpcRuleHandle>> ruleCachedHandle = new BeanHolder<>(CommonHandleCache::new);
+
     private final LoadingCache<String, ShenyuServiceInstanceLists> cache = CacheBuilder.newBuilder()
             .maximumSize(Constants.CACHE_MAX_COUNT)
             .build(new CacheLoader<String, ShenyuServiceInstanceLists>() {
@@ -52,12 +60,12 @@ public final class ApplicationConfigCache {
                     return new ShenyuServiceInstanceLists(key);
                 }
             });
-    
-    private final Map<String, Consumer<Object>> listener = new ConcurrentHashMap<>();
+
+    private final Map<String, Consumer<Object>> watchUpstreamListener = new ConcurrentHashMap<>();
     
     private ApplicationConfigCache() {
     }
-    
+
     /**
      * Get shenyuServiceInstanceList.
      *
@@ -73,39 +81,34 @@ public final class ApplicationConfigCache {
     }
     
     /**
-     * Init prx.
+     * handlerSelector.
      *
      * @param selectorData selectorData
      */
-    public void initPrx(final SelectorData selectorData) {
-        try {
-            final List<GrpcUpstream> upstreamList = GsonUtils.getInstance().fromList(selectorData.getHandle(), GrpcUpstream.class);
-            if (CollectionUtils.isEmpty(upstreamList)) {
-                invalidate(selectorData.getName());
-                return;
-            }
-            ShenyuServiceInstanceLists shenyuServiceInstances = cache.get(selectorData.getName());
-            List<ShenyuServiceInstance> instances = shenyuServiceInstances.getShenyuServiceInstances();
-            instances.clear();
-            instances.addAll(upstreamList.stream().map(this::build).collect(Collectors.toList()));
-            Consumer<Object> consumer = listener.get(selectorData.getName());
-            if (Objects.nonNull(consumer)) {
-                consumer.accept(System.currentTimeMillis());
-            }
-        } catch (ExecutionException e) {
-            throw new ShenyuException(e.getCause());
+    public void handlerSelector(final SelectorData selectorData) {
+        final List<GrpcUpstream> upstreamList = GsonUtils.getInstance().fromList(selectorData.getHandle(), GrpcUpstream.class);
+        if (CollectionUtils.isEmpty(upstreamList)) {
+            invalidate(selectorData.getId());
+            return;
+        }
+        grpcUpstreamCachedHandle.get().cachedHandle(selectorData.getId(), upstreamList);
+        Consumer<Object> consumer = watchUpstreamListener.get(selectorData.getId());
+        if (Objects.nonNull(consumer)) {
+            consumer.accept(System.currentTimeMillis());
         }
     }
     
     /**
      * invalidate client.
      *
-     * @param contextPath contextPath
+     * @param selectorId selectorId
      */
-    public void invalidate(final String contextPath) {
-        cache.invalidate(contextPath);
-        listener.remove(contextPath);
-        GrpcClientCache.removeClient(contextPath);
+    public void invalidate(final String selectorId) {
+        grpcUpstreamCachedHandle.get().removeHandle(selectorId);
+        cache.invalidate(selectorId);
+        watchUpstreamListener.remove(selectorId);
+        ruleCachedHandle.get().removeHandle(CacheKeyUtils.INST.getKey(selectorId, Constants.DEFAULT_RULE));
+        GrpcClientCache.removeClient(selectorId);
     }
     
     /**
@@ -115,7 +118,7 @@ public final class ApplicationConfigCache {
      * @param consumer consumer
      */
     public void watch(final String key, final Consumer<Object> consumer) {
-        listener.put(key, consumer);
+        watchUpstreamListener.put(key, consumer);
     }
     
     /**
@@ -126,15 +129,48 @@ public final class ApplicationConfigCache {
     public static ApplicationConfigCache getInstance() {
         return ApplicationConfigCacheInstance.INSTANCE;
     }
-    
-    private ShenyuServiceInstance build(final GrpcUpstream grpcUpstream) {
-        String[] ipAndPort = grpcUpstream.getUpstreamUrl().split(":");
-        ShenyuServiceInstance instance = new ShenyuServiceInstance(ipAndPort[0], Integer.parseInt(ipAndPort[1]));
-        instance.setWeight(grpcUpstream.getWeight());
-        instance.setStatus(grpcUpstream.isStatus());
-        return instance;
+
+    /**
+     * handlerRule.
+     *
+     * @param ruleDataKey ruleDataKey
+     * @param ruleHandle ruleHandle
+     */
+    public void cacheRuleHandle(final String ruleDataKey, final String ruleHandle) {
+        final String handler = StringUtils.hasText(ruleHandle) ? ruleHandle : "{}";
+        ruleCachedHandle.get().cachedHandle(ruleDataKey, GsonUtils.getInstance().fromJson(handler, GrpcRuleHandle.class));
     }
-    
+
+    /**
+     * getCacheRuleHandle.
+     *
+     * @param ruleDataKey ruleDataKey
+     * @return {@link GrpcRuleHandle}
+     */
+    public GrpcRuleHandle getCacheRuleHandle(final String ruleDataKey) {
+        return ruleCachedHandle.get().obtainHandle(ruleDataKey);
+    }
+
+    /**
+     * removeRuleHandle.
+     *
+     * @param ruleDataKey ruleDataKey
+     */
+    public void removeRuleHandle(final String ruleDataKey) {
+        ruleCachedHandle.get().removeHandle(ruleDataKey);
+    }
+
+    /**
+     * getGrpcUpstreamListCache.
+     *
+     * @param selectorId selectorId
+     * @return {@link List GrpcUpstream}
+     */
+    public List<GrpcUpstream> getGrpcUpstreamListCache(final String selectorId) {
+        return grpcUpstreamCachedHandle.get().obtainHandle(selectorId);
+    }
+
+
     /**
      * The type Application config cache instance.
      */
diff --git a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/cache/GrpcClientCache.java b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/cache/GrpcClientCache.java
index abc4939934..f9aeb512fa 100644
--- a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/cache/GrpcClientCache.java
+++ b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/cache/GrpcClientCache.java
@@ -48,29 +48,29 @@ public final class GrpcClientCache {
     /**
      * Init client.
      *
-     * @param contextPath contextPath
+     * @param selectorId selectorId
      */
-    public static void initGrpcClient(final String contextPath) {
-        MapUtils.computeIfAbsent(CLIENT_CACHE, contextPath, s -> GrpcClientBuilder.buildClient(contextPath));
+    public static void initGrpcClient(final String selectorId) {
+        MapUtils.computeIfAbsent(CLIENT_CACHE, selectorId, s -> GrpcClientBuilder.buildClient(selectorId));
     }
     
     /**
      * Get the client.
      *
-     * @param contextPath contextPath
+     * @param selectorId selectorId
      * @return ShenyuGrpcClient shenyuGrpcClient
      */
-    public static ShenyuGrpcClient getGrpcClient(final String contextPath) {
-        return CLIENT_CACHE.get(contextPath);
+    public static ShenyuGrpcClient getGrpcClient(final String selectorId) {
+        return CLIENT_CACHE.get(selectorId);
     }
     
     /**
      * Remove client.
      *
-     * @param contextPath contextPath
+     * @param selectorId selectorId
      */
-    public static void removeClient(final String contextPath) {
-        ShenyuGrpcClient grpcClient = CLIENT_CACHE.remove(contextPath);
+    public static void removeClient(final String selectorId) {
+        ShenyuGrpcClient grpcClient = CLIENT_CACHE.remove(selectorId);
         if (Objects.nonNull(grpcClient)) {
             grpcClient.close();
         }
diff --git a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/client/GrpcClientBuilder.java b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/client/GrpcClientBuilder.java
index 388bd215af..734bcae1e3 100644
--- a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/client/GrpcClientBuilder.java
+++ b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/client/GrpcClientBuilder.java
@@ -32,6 +32,7 @@ import org.apache.shenyu.plugin.grpc.intercept.ContextClientInterceptor;
 import org.apache.shenyu.plugin.grpc.loadbalance.LoadBalancerStrategy;
 import org.apache.shenyu.plugin.grpc.loadbalance.RandomLoadBalancerProvider;
 import org.apache.shenyu.plugin.grpc.loadbalance.RoundRobinLoadBalancerProvider;
+import org.apache.shenyu.plugin.grpc.loadbalance.ShenyuLoadBalancerProvider;
 import org.apache.shenyu.plugin.grpc.resolver.ShenyuNameResolverProvider;
 import org.springframework.beans.factory.NoSuchBeanDefinitionException;
 
@@ -47,6 +48,7 @@ public final class GrpcClientBuilder {
     static {
         LoadBalancerRegistry.getDefaultRegistry().register(new RandomLoadBalancerProvider());
         LoadBalancerRegistry.getDefaultRegistry().register(new RoundRobinLoadBalancerProvider());
+        LoadBalancerRegistry.getDefaultRegistry().register(new ShenyuLoadBalancerProvider());
         NameResolverRegistry.getDefaultRegistry().register(new ShenyuNameResolverProvider());
     }
 
@@ -56,14 +58,14 @@ public final class GrpcClientBuilder {
     /**
      * Build the client.
      *
-     * @param contextPath contextPath
+     * @param selectorId selectorId
      * @return ShenyuGrpcClient  shenyuGrpcClient
      */
-    public static ShenyuGrpcClient buildClient(final String contextPath) {
-        URI url = URI.create(PluginEnum.GRPC.getName() + "://" + contextPath);
+    public static ShenyuGrpcClient buildClient(final String selectorId) {
+        URI url = URI.create(PluginEnum.GRPC.getName() + "://" + selectorId);
         ManagedChannelBuilder<?> builder = ManagedChannelBuilder.forTarget(url.toString())
                 .intercept(new ContextClientInterceptor())
-                .defaultLoadBalancingPolicy(LoadBalancerStrategy.RANDOM.getStrategy())
+                .defaultLoadBalancingPolicy(LoadBalancerStrategy.SHENYU.getStrategy())
                 .usePlaintext()
                 .maxInboundMessageSize(100 * 1024 * 1024)
                 .executor(buildExecutor())
diff --git a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/loadbalance/LoadBalancerStrategy.java b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/context/GrpcConstants.java
similarity index 57%
copy from shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/loadbalance/LoadBalancerStrategy.java
copy to shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/context/GrpcConstants.java
index da29a16e41..208efebf8c 100644
--- a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/loadbalance/LoadBalancerStrategy.java
+++ b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/context/GrpcConstants.java
@@ -15,34 +15,38 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.plugin.grpc.loadbalance;
+package org.apache.shenyu.plugin.grpc.context;
+
+import io.grpc.Context;
 
 /**
- * LoadBalancerStrategy.
+ * GrpcConstants.
  */
-public enum LoadBalancerStrategy {
+public interface GrpcConstants {
 
     /**
-     * Random load balancer strategy.
+     * grpc gray release selector id.
      */
-    RANDOM("random"),
+    Context.Key<String> GRPC_SELECTOR_ID = Context.key("grpcSelectorId");
+
     /**
-     * Round robin load balancer strategy.
+     * grpc gray release rule id.
      */
-    ROUND_ROBIN("round-robin");
+    Context.Key<String> GRPC_RULE_ID = Context.key("grpcRuleId");
 
-    private final String strategy;
+    /**
+     * grpc remote address.
+     */
+    Context.Key<String> GRPC_REMOTE_ADDRESS = Context.key("grpcRemoteAddress");
 
-    LoadBalancerStrategy(final String strategy) {
-        this.strategy = strategy;
-    }
+    /**
+     * selectorCachedHandle.
+     */
+    Context.Key<String> SELECTOR_CACHED_HANDLE = Context.key("selectorCachedHandle");
 
     /**
-     * Gets strategy.
-     *
-     * @return the strategy
+     * GrpcConstants.
      */
-    public String getStrategy() {
-        return strategy;
+    default void findGrpcConstants() {
     }
 }
diff --git a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/handler/GrpcPluginDataHandler.java b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/handler/GrpcPluginDataHandler.java
index 584a8dcacf..af9de289ce 100644
--- a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/handler/GrpcPluginDataHandler.java
+++ b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/handler/GrpcPluginDataHandler.java
@@ -17,13 +17,16 @@
 
 package org.apache.shenyu.plugin.grpc.handler;
 
+import org.apache.shenyu.common.constant.Constants;
 import org.apache.shenyu.common.dto.PluginData;
+import org.apache.shenyu.common.dto.RuleData;
 import org.apache.shenyu.common.dto.SelectorData;
 import org.apache.shenyu.common.dto.convert.plugin.GrpcRegisterConfig;
 import org.apache.shenyu.common.enums.PluginEnum;
 import org.apache.shenyu.common.utils.GsonUtils;
 import org.apache.shenyu.common.utils.Singleton;
 import org.apache.shenyu.plugin.base.handler.PluginDataHandler;
+import org.apache.shenyu.plugin.base.utils.CacheKeyUtils;
 import org.apache.shenyu.plugin.grpc.cache.ApplicationConfigCache;
 import org.apache.shenyu.plugin.grpc.cache.GrpcClientCache;
 
@@ -51,19 +54,32 @@ public class GrpcPluginDataHandler implements PluginDataHandler {
 
     @Override
     public void handlerSelector(final SelectorData selectorData) {
-        if (Objects.isNull(selectorData.getName())) {
+        if (Objects.isNull(selectorData.getId())) {
             return;
         }
-        GrpcClientCache.initGrpcClient(selectorData.getName());
-        ApplicationConfigCache.getInstance().initPrx(selectorData);
+        if (!selectorData.getContinued()) {
+            ApplicationConfigCache.getInstance().cacheRuleHandle(CacheKeyUtils.INST.getKey(selectorData.getId(), Constants.DEFAULT_RULE), "{}");
+        }
+        ApplicationConfigCache.getInstance().handlerSelector(selectorData);
+        GrpcClientCache.initGrpcClient(selectorData.getId());
     }
 
     @Override
     public void removeSelector(final SelectorData selectorData) {
-        if (Objects.isNull(selectorData.getName())) {
+        if (Objects.isNull(selectorData.getId())) {
             return;
         }
-        ApplicationConfigCache.getInstance().invalidate(selectorData.getName());
+        ApplicationConfigCache.getInstance().invalidate(selectorData.getId());
+    }
+
+    @Override
+    public void handlerRule(final RuleData ruleData) {
+        ApplicationConfigCache.getInstance().cacheRuleHandle(ruleData.getId(), ruleData.getHandle());
+    }
+
+    @Override
+    public void removeRule(final RuleData ruleData) {
+        ApplicationConfigCache.getInstance().removeRuleHandle(ruleData.getId());
     }
 
     @Override
diff --git a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/loadbalance/LoadBalancerStrategy.java b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/loadbalance/LoadBalancerStrategy.java
index da29a16e41..4207b67f56 100644
--- a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/loadbalance/LoadBalancerStrategy.java
+++ b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/loadbalance/LoadBalancerStrategy.java
@@ -29,7 +29,11 @@ public enum LoadBalancerStrategy {
     /**
      * Round robin load balancer strategy.
      */
-    ROUND_ROBIN("round-robin");
+    ROUND_ROBIN("round-robin"),
+    /**
+     * Shenyu load balancer strategy.
+     */
+    SHENYU("SHENYU");
 
     private final String strategy;
 
diff --git a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/resolver/ShenyuNameResolverProvider.java b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/loadbalance/ShenyuLoadBalancerProvider.java
similarity index 52%
copy from shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/resolver/ShenyuNameResolverProvider.java
copy to shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/loadbalance/ShenyuLoadBalancerProvider.java
index 2cabaecee7..ded3035ffa 100644
--- a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/resolver/ShenyuNameResolverProvider.java
+++ b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/loadbalance/ShenyuLoadBalancerProvider.java
@@ -15,37 +15,42 @@
  * limitations under the License.
  */
 
-package org.apache.shenyu.plugin.grpc.resolver;
+package org.apache.shenyu.plugin.grpc.loadbalance;
 
-import io.grpc.NameResolver;
-import io.grpc.NameResolverProvider;
-import io.grpc.internal.GrpcUtil;
-import org.apache.shenyu.common.enums.PluginEnum;
+import io.grpc.LoadBalancer;
+import io.grpc.LoadBalancerProvider;
+import org.apache.shenyu.plugin.grpc.loadbalance.picker.AbstractReadyPicker;
+import org.apache.shenyu.plugin.grpc.loadbalance.picker.ShenyuPicker;
 
-import java.net.URI;
+import java.util.List;
 
 /**
- * ShenyuNameResolverProvider.
+ * ShenyuLoadBalancerProvider.
  */
-public class ShenyuNameResolverProvider extends NameResolverProvider {
+public class ShenyuLoadBalancerProvider extends LoadBalancerProvider {
 
     @Override
-    public NameResolver newNameResolver(final URI targetUri, final NameResolver.Args args) {
-        return new ShenyuNameResolver(targetUri.getPath(), args, GrpcUtil.SHARED_CHANNEL_EXECUTOR);
+    public boolean isAvailable() {
+        return true;
     }
 
     @Override
-    protected boolean isAvailable() {
-        return true;
+    public int getPriority() {
+        return 6;
     }
 
     @Override
-    protected int priority() {
-        return 6;
+    public String getPolicyName() {
+        return LoadBalancerStrategy.SHENYU.getStrategy();
     }
 
     @Override
-    public String getDefaultScheme() {
-        return PluginEnum.GRPC.getName();
+    public LoadBalancer newLoadBalancer(final LoadBalancer.Helper helper) {
+        return new AbstractLoadBalancer(helper) {
+            @Override
+            protected AbstractReadyPicker newPicker(final List<Subchannel> list) {
+                return new ShenyuPicker(list);
+            }
+        };
     }
 }
diff --git a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/loadbalance/SubChannelCopy.java b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/loadbalance/SubChannelCopy.java
index 089f7e3fea..98cce5166b 100644
--- a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/loadbalance/SubChannelCopy.java
+++ b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/loadbalance/SubChannelCopy.java
@@ -32,6 +32,8 @@ public class SubChannelCopy {
 
     private final String status;
 
+    private final String url;
+
     private final LoadBalancer.Subchannel channel;
 
     private final EquivalentAddressGroup addressGroup;
@@ -49,6 +51,7 @@ public class SubChannelCopy {
         this.weight = SubChannels.getWeight(channel);
         this.state = SubChannels.getStateInfo(channel);
         this.status = SubChannels.getStatus(channel);
+        this.url = SubChannels.getUrl(channel);
     }
 
     /**
@@ -96,6 +99,15 @@ public class SubChannelCopy {
         return state;
     }
 
+    /**
+     * url.
+     *
+     * @return Url
+     */
+    public String getUrl() {
+        return url;
+    }
+
     @Override
     public boolean equals(final Object o) {
         if (this == o) {
@@ -106,11 +118,12 @@ public class SubChannelCopy {
         }
         SubChannelCopy that = (SubChannelCopy) o;
         return weight == that.weight && Objects.equals(status, that.status) && Objects.equals(channel, that.channel)
-                && Objects.equals(addressGroup, that.addressGroup) && Objects.equals(state, that.state);
+                && Objects.equals(addressGroup, that.addressGroup) && Objects.equals(state, that.state)
+                && Objects.equals(url, that.url);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(weight, status, channel, addressGroup, state);
+        return Objects.hash(weight, status, channel, addressGroup, state, url);
     }
 }
diff --git a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/loadbalance/SubChannels.java b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/loadbalance/SubChannels.java
index 629b96cc3d..d3bdc20529 100644
--- a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/loadbalance/SubChannels.java
+++ b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/loadbalance/SubChannels.java
@@ -35,6 +35,8 @@ public final class SubChannels {
     private static final Attributes.Key<Ref<Integer>> WEIGHT_KEY = Attributes.Key.create("weight");
     
     private static final Attributes.Key<Ref<String>> STATSU_KEY = Attributes.Key.create("status");
+
+    private static final Attributes.Key<Ref<String>> URL_KEY = Attributes.Key.create("url");
     
     private SubChannels() {
     }
@@ -66,12 +68,14 @@ public final class SubChannels {
      *
      * @param weight weight
      * @param status status
+     * @param url url
      * @return Attributes attributes
      */
-    public static Attributes createAttributes(final int weight, final String status) {
+    public static Attributes createAttributes(final int weight, final String status, final String url) {
         return Attributes.newBuilder()
                 .set(WEIGHT_KEY, new Ref<>(weight))
                 .set(STATSU_KEY, new Ref<>(status))
+                .set(URL_KEY, new Ref<>(url))
                 .build();
     }
     
@@ -94,6 +98,16 @@ public final class SubChannels {
     public static String getStatus(final LoadBalancer.Subchannel subchannel) {
         return getAttributeValue(subchannel, STATSU_KEY, "true");
     }
+
+    /**
+     * Get url.
+     *
+     * @param subchannel subchannel
+     * @return String url
+     */
+    public static String getUrl(final LoadBalancer.Subchannel subchannel) {
+        return getAttributeValue(subchannel, URL_KEY, null);
+    }
     
     /**
      * Get ConnectivityStateInfo.
@@ -160,7 +174,7 @@ public final class SubChannels {
         setAttributeValue(subchannel, WEIGHT_KEY, attributes);
         setAttributeValue(subchannel, STATSU_KEY, attributes);
     }
-    
+
     static final class Ref<T> {
         
         private T value;
diff --git a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/loadbalance/picker/ShenyuPicker.java b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/loadbalance/picker/ShenyuPicker.java
new file mode 100644
index 0000000000..ef71b3ef98
--- /dev/null
+++ b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/loadbalance/picker/ShenyuPicker.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.shenyu.plugin.grpc.loadbalance.picker;
+
+import io.grpc.LoadBalancer;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.shenyu.common.dto.convert.rule.impl.GrpcRuleHandle;
+import org.apache.shenyu.common.dto.convert.selector.GrpcUpstream;
+import org.apache.shenyu.loadbalancer.entity.Upstream;
+import org.apache.shenyu.loadbalancer.factory.LoadBalancerFactory;
+import org.apache.shenyu.plugin.grpc.cache.ApplicationConfigCache;
+import org.apache.shenyu.plugin.grpc.context.GrpcConstants;
+import org.apache.shenyu.plugin.grpc.loadbalance.SubChannelCopy;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Shenyu picker.
+ */
+public class ShenyuPicker extends AbstractReadyPicker {
+
+    private final RandomPicker randomPicker;
+
+    public ShenyuPicker(final List<LoadBalancer.Subchannel> list) {
+        super(list);
+        randomPicker = new RandomPicker(list);
+    }
+
+    @Override
+    protected SubChannelCopy pick(final List<SubChannelCopy> list) {
+
+        String grpcRuleId = GrpcConstants.GRPC_RULE_ID.get();
+        String selectorId = GrpcConstants.GRPC_SELECTOR_ID.get();
+        String remoteAddressIp = GrpcConstants.GRPC_REMOTE_ADDRESS.get();
+        final GrpcRuleHandle cacheRuleHandle = ApplicationConfigCache.getInstance().getCacheRuleHandle(grpcRuleId);
+        List<GrpcUpstream> grpcUpstreams = ApplicationConfigCache.getInstance().getGrpcUpstreamListCache(selectorId);
+        if (CollectionUtils.isNotEmpty(grpcUpstreams)) {
+            Upstream upstream = LoadBalancerFactory.selector(convertUpstreamList(grpcUpstreams), cacheRuleHandle.getLoadBalance(), remoteAddressIp);
+            if (StringUtils.isBlank(upstream.getUrl()) && StringUtils.isBlank(upstream.getGroup()) && StringUtils.isBlank(upstream.getVersion())) {
+                return randomPicker.pick(list);
+            }
+
+            final List<SubChannelCopy> invokerGrays = list.stream().filter(each -> each.getUrl().equals(upstream.getUrl())).collect(Collectors.toList());
+            return invokerGrays.stream().findFirst().orElse(null);
+        }
+        return randomPicker.pick(list);
+    }
+
+    private List<Upstream> convertUpstreamList(final List<GrpcUpstream> grpcUpstreams) {
+        return grpcUpstreams.stream().map(u -> Upstream.builder()
+                .protocol(u.getProtocol())
+                .url(u.getUpstreamUrl())
+                .weight(u.getWeight())
+                .status(u.isStatus())
+                .timestamp(u.getTimestamp())
+                .build()).collect(Collectors.toList());
+    }
+
+}
diff --git a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/resolver/ShenyuNameResolver.java b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/resolver/ShenyuNameResolver.java
index 10f2ffeb0c..8be71f24ec 100644
--- a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/resolver/ShenyuNameResolver.java
+++ b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/resolver/ShenyuNameResolver.java
@@ -20,20 +20,20 @@ package org.apache.shenyu.plugin.grpc.resolver;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
 import io.grpc.Attributes;
+import io.grpc.EquivalentAddressGroup;
 import io.grpc.NameResolver;
 import io.grpc.Status;
-import io.grpc.EquivalentAddressGroup;
 import io.grpc.SynchronizationContext;
 import io.grpc.internal.SharedResourceHolder;
-import java.util.Collections;
 import org.apache.commons.collections4.CollectionUtils;
-import org.apache.shenyu.plugin.grpc.loadbalance.GrpcAttributeUtils;
+import org.apache.shenyu.common.dto.convert.selector.GrpcUpstream;
 import org.apache.shenyu.plugin.grpc.cache.ApplicationConfigCache;
+import org.apache.shenyu.plugin.grpc.loadbalance.GrpcAttributeUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicReference;
@@ -59,7 +59,7 @@ public class ShenyuNameResolver extends NameResolver implements Consumer<Object>
 
     private final SynchronizationContext syncContext;
 
-    private List<ShenyuServiceInstance> instanceList = Lists.newArrayList();
+    private List<GrpcUpstream> instanceList = Lists.newArrayList();
 
     private final SharedResourceHolder.Resource<Executor> executorResource;
 
@@ -124,16 +124,16 @@ public class ShenyuNameResolver extends NameResolver implements Consumer<Object>
 
         private final Listener2 savedListener;
 
-        private final List<ShenyuServiceInstance> savedInstanceList;
+        private final List<GrpcUpstream> savedInstanceList;
 
-        Resolve(final Listener2 listener, final List<ShenyuServiceInstance> instanceList) {
+        Resolve(final Listener2 listener, final List<GrpcUpstream> instanceList) {
             this.savedListener = Objects.requireNonNull(listener, "listener");
             this.savedInstanceList = Objects.requireNonNull(instanceList, "instanceList");
         }
 
         @Override
         public void run() {
-            final AtomicReference<List<ShenyuServiceInstance>> resultContainer = new AtomicReference<>();
+            final AtomicReference<List<GrpcUpstream>> resultContainer = new AtomicReference<>();
             try {
                 resultContainer.set(resolveInternal());
             } catch (final Exception e) {
@@ -143,7 +143,7 @@ public class ShenyuNameResolver extends NameResolver implements Consumer<Object>
             } finally {
                 ShenyuNameResolver.this.syncContext.execute(() -> {
                     ShenyuNameResolver.this.resolving = false;
-                    final List<ShenyuServiceInstance> newInstanceList = resultContainer.get();
+                    final List<GrpcUpstream> newInstanceList = resultContainer.get();
                     if (Objects.nonNull(newInstanceList) && ShenyuNameResolver.this.listener != null) {
                         ShenyuNameResolver.this.instanceList = newInstanceList;
                     }
@@ -151,27 +151,26 @@ public class ShenyuNameResolver extends NameResolver implements Consumer<Object>
             }
         }
 
-        private List<ShenyuServiceInstance> resolveInternal() {
+        private List<GrpcUpstream> resolveInternal() {
             final String name = ShenyuNameResolver.this.appName;
-            ShenyuServiceInstanceLists shenyuServiceInstanceLists = ApplicationConfigCache.getInstance().get(name);
-            List<ShenyuServiceInstance> newInstanceList = shenyuServiceInstanceLists.getCopyInstances();
-            LOG.info("Got {} candidate servers for {}", newInstanceList.size(), name);
+            List<GrpcUpstream> grpcUpstreamList = ApplicationConfigCache.getInstance().getGrpcUpstreamListCache(name);
+            LOG.info("Got {} candidate servers for {}", grpcUpstreamList.size(), name);
 
-            if (CollectionUtils.isEmpty(newInstanceList)) {
+            if (CollectionUtils.isEmpty(grpcUpstreamList)) {
                 LOG.info("No servers found for {}", name);
                 this.savedListener.onError(Status.UNAVAILABLE.withDescription("No servers found for " + name));
                 return Lists.newArrayList();
             }
 
-            if (!needsToUpdateConnections(newInstanceList)) {
+            if (!needsToUpdateConnections(grpcUpstreamList)) {
                 LOG.info("Nothing has changed... skipping update for {}", name);
                 return Collections.emptyList();
             }
 
             LOG.info("Ready to update server list for {}", name);
-            final List<EquivalentAddressGroup> targets = newInstanceList.stream()
+            final List<EquivalentAddressGroup> targets = grpcUpstreamList.stream()
                     .map(instance -> {
-                        LOG.info("Found gRPC server {}:{} for {}", instance.getHost(), instance.getPort(), name);
+                        LOG.info("Found gRPC server {} for {}", instance.getUpstreamUrl(), name);
                         return ShenyuResolverHelper.convertToEquivalentAddressGroup(instance);
                     }).collect(Collectors.toList());
 
@@ -181,38 +180,14 @@ public class ShenyuNameResolver extends NameResolver implements Consumer<Object>
                     .build());
             LOG.info("Done updating server list for {}", name);
 
-            return newInstanceList;
+            return grpcUpstreamList;
         }
 
-        private boolean needsToUpdateConnections(final List<ShenyuServiceInstance> newInstanceList) {
+        private boolean needsToUpdateConnections(final List<GrpcUpstream> newInstanceList) {
             if (!Objects.equals(this.savedInstanceList.size(), newInstanceList.size())) {
                 return true;
             }
-
-            for (final ShenyuServiceInstance instance : this.savedInstanceList) {
-                final String host = instance.getHost();
-                final int port = instance.getPort();
-                boolean isSame = newInstanceList.stream().anyMatch(newInstance -> host.equals(newInstance.getHost())
-                        && port == newInstance.getPort()
-                        && isMetadataEquals(instance.getMetadata(), newInstance.getMetadata()));
-                if (!isSame) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        private boolean isMetadataEquals(final Map<String, String> metadata,
-                                         final Map<String, String> newMetadata) {
-            final String[] keys = {"weight", "status"};
-            for (String key : keys) {
-                final String value = metadata.get(key);
-                final String newValue = newMetadata.get(key);
-                if (!Objects.equals(value, newValue)) {
-                    return false;
-                }
-            }
-            return true;
+            return this.savedInstanceList.stream().anyMatch(instance -> !newInstanceList.contains(instance));
         }
     }
 }
diff --git a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/resolver/ShenyuNameResolverProvider.java b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/resolver/ShenyuNameResolverProvider.java
index 2cabaecee7..edfaf83d92 100644
--- a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/resolver/ShenyuNameResolverProvider.java
+++ b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/resolver/ShenyuNameResolverProvider.java
@@ -31,7 +31,7 @@ public class ShenyuNameResolverProvider extends NameResolverProvider {
 
     @Override
     public NameResolver newNameResolver(final URI targetUri, final NameResolver.Args args) {
-        return new ShenyuNameResolver(targetUri.getPath(), args, GrpcUtil.SHARED_CHANNEL_EXECUTOR);
+        return new ShenyuNameResolver(targetUri.getHost(), args, GrpcUtil.SHARED_CHANNEL_EXECUTOR);
     }
 
     @Override
diff --git a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/resolver/ShenyuResolverHelper.java b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/resolver/ShenyuResolverHelper.java
index a1acd4c35d..5d919c68e5 100644
--- a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/resolver/ShenyuResolverHelper.java
+++ b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/resolver/ShenyuResolverHelper.java
@@ -19,6 +19,7 @@ package org.apache.shenyu.plugin.grpc.resolver;
 
 import io.grpc.Attributes;
 import io.grpc.EquivalentAddressGroup;
+import org.apache.shenyu.common.dto.convert.selector.GrpcUpstream;
 import org.apache.shenyu.plugin.grpc.loadbalance.SubChannels;
 
 import java.net.InetSocketAddress;
@@ -37,8 +38,9 @@ public final class ShenyuResolverHelper {
      * @param instance instance
      * @return EquivalentAddressGroup
      */
-    public static EquivalentAddressGroup convertToEquivalentAddressGroup(final ShenyuServiceInstance instance) {
-        return new EquivalentAddressGroup(new InetSocketAddress(instance.getHost(), instance.getPort()), createAttributes(instance));
+    public static EquivalentAddressGroup convertToEquivalentAddressGroup(final GrpcUpstream instance) {
+        String[] ipAndPort = instance.getUpstreamUrl().split(":");
+        return new EquivalentAddressGroup(new InetSocketAddress(ipAndPort[0], Integer.parseInt(ipAndPort[1])), createAttributes(instance));
     }
     
     /**
@@ -47,7 +49,8 @@ public final class ShenyuResolverHelper {
      * @param instance instance
      * @return Attributes
      */
-    private static Attributes createAttributes(final ShenyuServiceInstance instance) {
-        return SubChannels.createAttributes(instance.getWeight(), instance.getStatus());
+    private static Attributes createAttributes(final GrpcUpstream instance) {
+        return SubChannels.createAttributes(instance.getWeight(), String.valueOf(instance.isStatus()),
+                instance.getUpstreamUrl());
     }
 }
diff --git a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/test/java/org/apache/shenyu/plugin/grpc/GrpcPluginTest.java b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/test/java/org/apache/shenyu/plugin/grpc/GrpcPluginTest.java
index 23fe0f1555..1e95bd419b 100644
--- a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/test/java/org/apache/shenyu/plugin/grpc/GrpcPluginTest.java
+++ b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/test/java/org/apache/shenyu/plugin/grpc/GrpcPluginTest.java
@@ -78,6 +78,7 @@ public class GrpcPluginTest {
         when(context.getBean(ShenyuResult.class)).thenReturn(new DefaultShenyuResult());
 
         when(selector.getName()).thenReturn("/grpc");
+        when(selector.getId()).thenReturn("grpcId");
     }
 
     @Test
diff --git a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/test/java/org/apache/shenyu/plugin/grpc/cache/ApplicationConfigCacheTest.java b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/test/java/org/apache/shenyu/plugin/grpc/cache/ApplicationConfigCacheTest.java
index 8e579f3e73..39be026b7c 100644
--- a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/test/java/org/apache/shenyu/plugin/grpc/cache/ApplicationConfigCacheTest.java
+++ b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/test/java/org/apache/shenyu/plugin/grpc/cache/ApplicationConfigCacheTest.java
@@ -59,12 +59,6 @@ public class ApplicationConfigCacheTest {
         assertNotNull(this.applicationConfigCache);
     }
     
-    @Test
-    public void testInitPrx() {
-        this.applicationConfigCache.initPrx(selector);
-        assertNotNull(applicationConfigCache.get(selector.getName()));
-    }
-    
     @Test
     public void testGet() {
         assertNotNull(this.applicationConfigCache.get("/test"));
diff --git a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/test/java/org/apache/shenyu/plugin/grpc/handler/GrpcPluginDataHandlerTest.java b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/test/java/org/apache/shenyu/plugin/grpc/handler/GrpcPluginDataHandlerTest.java
index 52ae39517e..42881f2d8e 100644
--- a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/test/java/org/apache/shenyu/plugin/grpc/handler/GrpcPluginDataHandlerTest.java
+++ b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/test/java/org/apache/shenyu/plugin/grpc/handler/GrpcPluginDataHandlerTest.java
@@ -62,20 +62,20 @@ public class GrpcPluginDataHandlerTest {
     
     @Test
     public void testHandlerSelector() {
-        when(selectorData.getName()).thenReturn(null);
+        when(selectorData.getId()).thenReturn(null);
         grpcPluginDataHandler.handlerSelector(selectorData);
-        when(selectorData.getName()).thenReturn("/grpc");
+        when(selectorData.getId()).thenReturn("selectorId");
         grpcPluginDataHandler.handlerSelector(selectorData);
-        assertNotNull(GrpcClientCache.getGrpcClient(selectorData.getName()));
+        assertNotNull(GrpcClientCache.getGrpcClient(selectorData.getId()));
     }
     
     @Test
     public void testRemoveSelector() {
-        when(selectorData.getName()).thenReturn(null);
+        when(selectorData.getId()).thenReturn(null);
         grpcPluginDataHandler.removeSelector(selectorData);
-        when(selectorData.getName()).thenReturn("/grpc");
+        when(selectorData.getId()).thenReturn("selectorId");
         grpcPluginDataHandler.removeSelector(selectorData);
-        final List<ShenyuServiceInstance> shenyuServiceInstances = ApplicationConfigCache.getInstance().get(selectorData.getName()).getShenyuServiceInstances();
+        final List<ShenyuServiceInstance> shenyuServiceInstances = ApplicationConfigCache.getInstance().get(selectorData.getId()).getShenyuServiceInstances();
         assertTrue(CollectionUtils.isEmpty(shenyuServiceInstances), "shenyuServiceInstances mast is empty");
     }
     
diff --git a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/test/java/org/apache/shenyu/plugin/grpc/loadbalance/picker/RandomPickerTest.java b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/test/java/org/apache/shenyu/plugin/grpc/loadbalance/picker/RandomPickerTest.java
index 03cf73082f..1ace0b28d5 100644
--- a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/test/java/org/apache/shenyu/plugin/grpc/loadbalance/picker/RandomPickerTest.java
+++ b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/test/java/org/apache/shenyu/plugin/grpc/loadbalance/picker/RandomPickerTest.java
@@ -49,7 +49,7 @@ public class RandomPickerTest {
     
     @BeforeEach
     public void setUp() {
-        Attributes attributes = SubChannels.createAttributes(1, "ok");
+        Attributes attributes = SubChannels.createAttributes(1, "ok", "127.0.0.1:3888");
         LoadBalancer.Subchannel subchannel =
                 SubChannels.createSubChannel(new UnitTestReadHelper(), mock(EquivalentAddressGroup.class), attributes);
         List<LoadBalancer.Subchannel> list = new LinkedList<>();
diff --git a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/test/java/org/apache/shenyu/plugin/grpc/loadbalance/picker/RoundRobinPickerTest.java b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/test/java/org/apache/shenyu/plugin/grpc/loadbalance/picker/RoundRobinPickerTest.java
index ed37870e8f..564ddce038 100644
--- a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/test/java/org/apache/shenyu/plugin/grpc/loadbalance/picker/RoundRobinPickerTest.java
+++ b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/test/java/org/apache/shenyu/plugin/grpc/loadbalance/picker/RoundRobinPickerTest.java
@@ -44,7 +44,7 @@ public class RoundRobinPickerTest {
     
     @BeforeEach
     public void setUp() {
-        Attributes attributes = SubChannels.createAttributes(1, "ok");
+        Attributes attributes = SubChannels.createAttributes(1, "ok", "127.0.0.1:3888");
         LoadBalancer.Subchannel subchannel =
                 SubChannels.createSubChannel(new UnitTestReadHelper(), mock(EquivalentAddressGroup.class), attributes);
         List<LoadBalancer.Subchannel> list = new LinkedList<>();
diff --git a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/test/java/org/apache/shenyu/plugin/grpc/resolver/ShenyuResolverHelperTest.java b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/test/java/org/apache/shenyu/plugin/grpc/resolver/ShenyuResolverHelperTest.java
index 1d51672521..1201d91bc7 100644
--- a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/test/java/org/apache/shenyu/plugin/grpc/resolver/ShenyuResolverHelperTest.java
+++ b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/test/java/org/apache/shenyu/plugin/grpc/resolver/ShenyuResolverHelperTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.shenyu.plugin.grpc.resolver;
 
+import org.apache.shenyu.common.dto.convert.selector.GrpcUpstream;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
@@ -30,15 +31,15 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
 @ExtendWith(MockitoExtension.class)
 public class ShenyuResolverHelperTest {
 
-    private ShenyuServiceInstance serviceInstance;
+    private GrpcUpstream grpcUpstream;
 
     @BeforeEach
     public void setUp() {
-        serviceInstance = new ShenyuServiceInstance("localhost", 8080);
+        grpcUpstream = GrpcUpstream.builder().upstreamHost("localhost:38888").upstreamUrl("localhost:38888").status(true).build();
     }
 
     @Test
     public void convertToEquivalentAddressGroup() {
-        assertNotNull(ShenyuResolverHelper.convertToEquivalentAddressGroup(serviceInstance));
+        assertNotNull(ShenyuResolverHelper.convertToEquivalentAddressGroup(grpcUpstream));
     }
 }