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 7192a2c07c admin adapter discovery local mode (#5176)
7192a2c07c is described below

commit 7192a2c07c0160dadf9e15f9d5cb1f519d6d31bf
Author: 杨文杰 <[email protected]>
AuthorDate: Tue Oct 24 13:17:15 2023 +0800

    admin adapter discovery local mode (#5176)
    
    * admin adapter discovery local mode
    
    * change ut
    
    * change ut
    
    * change ut
    
    * use local mode to default mode
    
    * use local mode to default mode
    
    * use local mode to default mode
    
    * add grpc handler
    
    * add grpc handler
    
    * add grpc handler
    
    * add grpc handler
    
    * use local mode to default mode
    
    * add grpc handler
    
    * add grpc handler
    
    * Update HttpSyncDataService.java
    
    ---------
    
    Co-authored-by: dragon-zhang <[email protected]>
    Co-authored-by: Misaya295 <[email protected]>
    Co-authored-by: yunlongn <[email protected]>
    Co-authored-by: xiaoyu <[email protected]>
    Co-authored-by: moremind <[email protected]>
---
 .../admin/mapper/DiscoveryHandlerMapper.java       |  7 +++
 .../admin/model/entity/DiscoveryUpstreamDO.java    |  1 +
 .../shenyu/admin/service/DiscoveryService.java     | 20 +++++++
 .../admin/service/DiscoveryUpstreamService.java    | 26 +++++++++
 .../admin/service/impl/DiscoveryServiceImpl.java   | 47 +++++++++++++++-
 .../service/impl/DiscoveryUpstreamServiceImpl.java | 28 ++++++++++
 .../AbstractShenyuClientRegisterServiceImpl.java   | 42 ++++++++++++++-
 .../ShenyuClientRegisterDivideServiceImpl.java     | 17 ++++--
 .../shenyu/admin/utils/CommonUpstreamUtils.java    | 49 ++++++++++++-----
 .../resources/mappers/discovery-handler-sqlmap.xml | 12 +++++
 ...bstractShenyuClientRegisterServiceImplTest.java | 15 ++++++
 .../AbstractContextRefreshedEventListener.java     | 23 ++++----
 .../core/constant/ShenyuClientConstants.java       | 20 ++++---
 .../init/SpringMvcClientEventListenerTest.java     |  2 +
 .../shenyu/e2e/testcase/grpc/GrpcPluginTest.java   |  8 +++
 .../plugin/grpc/cache/ApplicationConfigCache.java  | 32 ++++++++---
 .../handler/GrpcDiscoveryUpstreamDataHandler.java  | 63 ++++++++++++++++++++++
 .../client/grpc/ShenyuGrpcClientConfiguration.java | 16 +++++-
 .../ShenyuSpringWebSocketClientConfiguration.java  | 10 ++++
 .../ShenyuSpringMvcClientConfiguration.java        |  8 +--
 .../plugin/grpc/GrpcPluginConfiguration.java       | 13 +++++
 .../websocket/WebSocketPluginConfiguration.java    |  3 +-
 .../shenyu/sync/data/http/HttpSyncDataService.java |  2 +-
 23 files changed, 413 insertions(+), 51 deletions(-)

diff --git 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/DiscoveryHandlerMapper.java
 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/DiscoveryHandlerMapper.java
index 3b7dd39de8..d86e94a41e 100644
--- 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/DiscoveryHandlerMapper.java
+++ 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/mapper/DiscoveryHandlerMapper.java
@@ -111,4 +111,11 @@ public interface DiscoveryHandlerMapper extends 
ExistProvider {
      */
     List<DiscoveryHandlerDO> selectByDiscoveryId(@Param("discoveryId")String 
discoveryId);
 
+    /**
+     * selectBySelectorId.
+     *
+     * @param selectorId selectorId
+     * @return DiscoveryHandlerDO
+     */
+    DiscoveryHandlerDO selectBySelectorId(String selectorId);
 }
diff --git 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/entity/DiscoveryUpstreamDO.java
 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/entity/DiscoveryUpstreamDO.java
index dbceaeb0e7..9f7b003aeb 100644
--- 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/entity/DiscoveryUpstreamDO.java
+++ 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/model/entity/DiscoveryUpstreamDO.java
@@ -235,6 +235,7 @@ public class DiscoveryUpstreamDO extends BaseDO {
                     .status(item.getStatus())
                     .weight(item.getWeight())
                     .props(item.getProps())
+                    .url(item.getUrl())
                     .dateUpdated(currentTime).build();
             if (StringUtils.hasLength(item.getId())) {
                 discoveryUpstreamDO.setId(item.getId());
diff --git 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/DiscoveryService.java
 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/DiscoveryService.java
index 477132a565..5d670d0ded 100644
--- 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/DiscoveryService.java
+++ 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/DiscoveryService.java
@@ -18,6 +18,7 @@
 package org.apache.shenyu.admin.service;
 
 import org.apache.shenyu.admin.model.dto.DiscoveryDTO;
+import org.apache.shenyu.admin.model.dto.DiscoveryHandlerDTO;
 import org.apache.shenyu.admin.model.vo.DiscoveryVO;
 import org.apache.shenyu.register.common.dto.DiscoveryConfigRegisterDTO;
 
@@ -73,4 +74,23 @@ public interface DiscoveryService {
      * syncData.
      */
     void syncData();
+
+
+    /**
+     * findDiscoveryHandlerBySelectorId.
+     *
+     * @param selectorId selectorId
+     * @return DiscoveryHandlerDTO
+     */
+    DiscoveryHandlerDTO findDiscoveryHandlerBySelectorId(String selectorId);
+
+
+    /**
+     * registerDefaultDiscovery.
+     *
+     * @param selectorId selectorId
+     * @param pluginName pluginName
+     * @return discoveryHandlerId
+     */
+    String registerDefaultDiscovery(String selectorId, String pluginName);
 }
diff --git 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/DiscoveryUpstreamService.java
 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/DiscoveryUpstreamService.java
index 6cadc4bcbf..e4c3f20bcb 100644
--- 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/DiscoveryUpstreamService.java
+++ 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/DiscoveryUpstreamService.java
@@ -19,6 +19,7 @@ package org.apache.shenyu.admin.service;
 
 import org.apache.shenyu.admin.model.dto.DiscoveryUpstreamDTO;
 import org.apache.shenyu.common.dto.DiscoverySyncData;
+import org.apache.shenyu.common.dto.DiscoveryUpstreamData;
 
 import java.util.List;
 
@@ -32,6 +33,14 @@ public interface DiscoveryUpstreamService {
      */
     String createOrUpdate(DiscoveryUpstreamDTO discoveryUpstreamDTO);
 
+
+    /**
+     * nativeCreateOrUpdate.
+     *
+     * @param discoveryUpstreamDTO discoveryUpstreamDTO
+     */
+    void nativeCreateOrUpdate(DiscoveryUpstreamDTO discoveryUpstreamDTO);
+
     /**
      * delete.
      *
@@ -46,4 +55,21 @@ public interface DiscoveryUpstreamService {
      * @return DiscoverySyncDataList
      */
     List<DiscoverySyncData> listAll();
+
+    /**
+     * findBySelectorId.
+     *
+     * @param selectorId selectorId
+     * @return DiscoveryUpstreamDataList
+     */
+    List<DiscoveryUpstreamData> findBySelectorId(String selectorId);
+
+
+    /**
+     * deleteBySelectorIdAndUrl.
+     *
+     * @param selectorId selectorId
+     * @param url        url
+     */
+    void deleteBySelectorIdAndUrl(String selectorId, String url);
 }
diff --git 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryServiceImpl.java
 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryServiceImpl.java
index f47be5aa44..9f0686c734 100644
--- 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryServiceImpl.java
+++ 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryServiceImpl.java
@@ -17,10 +17,13 @@
 
 package org.apache.shenyu.admin.service.impl;
 
+import org.apache.shenyu.admin.discovery.DiscoveryLevel;
+import org.apache.shenyu.admin.discovery.DiscoveryMode;
+import org.apache.shenyu.admin.model.dto.DiscoveryHandlerDTO;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.shenyu.admin.discovery.DiscoveryLevel;
 import org.apache.shenyu.admin.discovery.DiscoveryProcessor;
+import org.apache.shenyu.admin.mapper.DiscoveryRelMapper;
 import org.apache.shenyu.admin.discovery.DiscoveryProcessorHolder;
 import org.apache.shenyu.admin.mapper.DiscoveryHandlerMapper;
 import org.apache.shenyu.admin.mapper.DiscoveryMapper;
@@ -28,6 +31,7 @@ import org.apache.shenyu.admin.mapper.ProxySelectorMapper;
 import org.apache.shenyu.admin.model.dto.DiscoveryDTO;
 import org.apache.shenyu.admin.model.entity.DiscoveryDO;
 import org.apache.shenyu.admin.model.entity.DiscoveryHandlerDO;
+import org.apache.shenyu.admin.model.entity.DiscoveryRelDO;
 import org.apache.shenyu.admin.model.enums.DiscoveryTypeEnum;
 import org.apache.shenyu.admin.model.vo.DiscoveryVO;
 import org.apache.shenyu.admin.service.DiscoveryService;
@@ -60,15 +64,19 @@ public class DiscoveryServiceImpl implements 
DiscoveryService {
 
     private final DiscoveryHandlerMapper discoveryHandlerMapper;
 
+    private final DiscoveryRelMapper discoveryRelMapper;
+
     private final DiscoveryProcessorHolder discoveryProcessorHolder;
 
     public DiscoveryServiceImpl(final DiscoveryMapper discoveryMapper,
                                 final ProxySelectorMapper proxySelectorMapper,
+                                final DiscoveryRelMapper discoveryRelMapper,
                                 final DiscoveryHandlerMapper 
discoveryHandlerMapper,
                                 final DiscoveryProcessorHolder 
discoveryProcessorHolder) {
         this.discoveryMapper = discoveryMapper;
         this.discoveryProcessorHolder = discoveryProcessorHolder;
         this.proxySelectorMapper = proxySelectorMapper;
+        this.discoveryRelMapper = discoveryRelMapper;
         this.discoveryHandlerMapper = discoveryHandlerMapper;
     }
 
@@ -193,4 +201,41 @@ public class DiscoveryServiceImpl implements 
DiscoveryService {
             });
         });
     }
+
+    @Override
+    public DiscoveryHandlerDTO findDiscoveryHandlerBySelectorId(final String 
selectorId) {
+        DiscoveryHandlerDO discoveryHandlerDO = 
discoveryHandlerMapper.selectBySelectorId(selectorId);
+        return DiscoveryTransfer.INSTANCE.mapToDTO(discoveryHandlerDO);
+    }
+
+    @Override
+    public String registerDefaultDiscovery(final String selectorId, final 
String pluginName) {
+        DiscoveryHandlerDO discoveryHandlerDB = 
discoveryHandlerMapper.selectBySelectorId(selectorId);
+        if (Objects.nonNull(discoveryHandlerDB)) {
+            return discoveryHandlerDB.getId();
+        }
+        DiscoveryDO discoveryDO = new DiscoveryDO();
+        String discoveryId = UUIDUtils.getInstance().generateShortUuid();
+        discoveryDO.setLevel(DiscoveryLevel.PLUGIN.getCode());
+        discoveryDO.setName(pluginName + "_default_discovery");
+        discoveryDO.setPluginName(pluginName);
+        discoveryDO.setType(DiscoveryMode.LOCAL.name().toLowerCase());
+        discoveryDO.setId(discoveryId);
+        discoveryMapper.insertSelective(discoveryDO);
+        DiscoveryHandlerDO discoveryHandlerDO = new DiscoveryHandlerDO();
+        String discoveryHandlerId = 
UUIDUtils.getInstance().generateShortUuid();
+        discoveryHandlerDO.setId(discoveryHandlerId);
+        discoveryHandlerDO.setDiscoveryId(discoveryId);
+        discoveryHandlerDO.setHandler("{}");
+        discoveryHandlerDO.setProps("{}");
+        discoveryHandlerMapper.insertSelective(discoveryHandlerDO);
+        DiscoveryRelDO discoveryRelDO = new DiscoveryRelDO();
+        String discoveryRelId = UUIDUtils.getInstance().generateShortUuid();
+        discoveryRelDO.setDiscoveryHandlerId(discoveryHandlerId);
+        discoveryRelDO.setId(discoveryRelId);
+        discoveryRelDO.setSelectorId(selectorId);
+        discoveryRelDO.setPluginName(pluginName);
+        discoveryRelMapper.insertSelective(discoveryRelDO);
+        return discoveryHandlerId;
+    }
 }
diff --git 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryUpstreamServiceImpl.java
 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryUpstreamServiceImpl.java
index a9359274b1..066e71c3a4 100644
--- 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryUpstreamServiceImpl.java
+++ 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/DiscoveryUpstreamServiceImpl.java
@@ -38,9 +38,11 @@ import org.apache.shenyu.admin.utils.ShenyuResultMessage;
 import org.apache.shenyu.common.dto.DiscoverySyncData;
 import org.apache.shenyu.common.dto.DiscoveryUpstreamData;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.StringUtils;
 
 import java.util.List;
+import java.util.Objects;
 import java.util.stream.Collectors;
 
 @Service
@@ -90,6 +92,16 @@ public class DiscoveryUpstreamServiceImpl implements 
DiscoveryUpstreamService {
                 ? update(discoveryUpstreamDTO) : create(discoveryUpstreamDTO);
     }
 
+    @Override
+    public void nativeCreateOrUpdate(final DiscoveryUpstreamDTO 
discoveryUpstreamDTO) {
+        DiscoveryUpstreamDO discoveryUpstreamDO = 
DiscoveryUpstreamDO.buildDiscoveryUpstreamDO(discoveryUpstreamDTO);
+        if (StringUtils.hasLength(discoveryUpstreamDTO.getId())) {
+            discoveryUpstreamMapper.updateSelective(discoveryUpstreamDO);
+        } else {
+            discoveryUpstreamMapper.insert(discoveryUpstreamDO);
+        }
+    }
+
     /**
      * delete.
      *
@@ -154,6 +166,22 @@ public class DiscoveryUpstreamServiceImpl implements 
DiscoveryUpstreamService {
         return ShenyuResultMessage.UPDATE_SUCCESS;
     }
 
+    @Override
+    public List<DiscoveryUpstreamData> findBySelectorId(final String 
selectorId) {
+        DiscoveryHandlerDO discoveryHandlerDO = 
discoveryHandlerMapper.selectBySelectorId(selectorId);
+        List<DiscoveryUpstreamDO> discoveryUpstreamDOS = 
discoveryUpstreamMapper.selectByDiscoveryHandlerId(discoveryHandlerDO.getId());
+        return 
discoveryUpstreamDOS.stream().map(DiscoveryTransfer.INSTANCE::mapToData).collect(Collectors.toList());
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void deleteBySelectorIdAndUrl(final String selectorId, final String 
url) {
+        DiscoveryHandlerDO discoveryHandlerDO = 
discoveryHandlerMapper.selectBySelectorId(selectorId);
+        if (Objects.nonNull(discoveryHandlerDO)) {
+            discoveryUpstreamMapper.deleteByUrl(discoveryHandlerDO.getId(), 
url);
+        }
+    }
+
     private void fetchAll(final String discoveryHandlerId) {
         List<DiscoveryUpstreamDO> discoveryUpstreamDOS = 
discoveryUpstreamMapper.selectByDiscoveryHandlerId(discoveryHandlerId);
         DiscoveryHandlerDO discoveryHandlerDO = 
discoveryHandlerMapper.selectById(discoveryHandlerId);
diff --git 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/register/AbstractShenyuClientRegisterServiceImpl.java
 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/register/AbstractShenyuClientRegisterServiceImpl.java
index aecb2888a0..fe12411a9f 100644
--- 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/register/AbstractShenyuClientRegisterServiceImpl.java
+++ 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/register/AbstractShenyuClientRegisterServiceImpl.java
@@ -20,17 +20,23 @@ package org.apache.shenyu.admin.service.register;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.shenyu.admin.listener.DataChangedEvent;
+import org.apache.shenyu.admin.model.dto.DiscoveryUpstreamDTO;
 import org.apache.shenyu.admin.model.dto.RuleConditionDTO;
 import org.apache.shenyu.admin.model.dto.RuleDTO;
 import org.apache.shenyu.admin.model.entity.SelectorDO;
 import org.apache.shenyu.admin.service.MetaDataService;
 import org.apache.shenyu.admin.service.RuleService;
 import org.apache.shenyu.admin.service.SelectorService;
+import org.apache.shenyu.admin.service.DiscoveryService;
+import org.apache.shenyu.admin.service.DiscoveryUpstreamService;
+
 import org.apache.shenyu.admin.service.impl.UpstreamCheckService;
 import org.apache.shenyu.admin.service.manager.RegisterApiDocService;
 import org.apache.shenyu.admin.utils.CommonUpstreamUtils;
 import org.apache.shenyu.admin.utils.ShenyuResultMessage;
 import org.apache.shenyu.common.constant.AdminConstants;
+import org.apache.shenyu.common.dto.DiscoverySyncData;
+import org.apache.shenyu.common.dto.DiscoveryUpstreamData;
 import org.apache.shenyu.common.dto.SelectorData;
 import org.apache.shenyu.common.dto.convert.selector.CommonUpstream;
 import org.apache.shenyu.common.enums.ConfigGroupEnum;
@@ -84,6 +90,12 @@ public abstract class 
AbstractShenyuClientRegisterServiceImpl extends FallbackSh
     @Resource
     private RegisterApiDocService registerApiDocService;
 
+    @Resource
+    private DiscoveryService discoveryService;
+
+    @Resource
+    private DiscoveryUpstreamService discoveryUpstreamService;
+
     /**
      * Selector handler string.
      *
@@ -158,7 +170,8 @@ public abstract class 
AbstractShenyuClientRegisterServiceImpl extends FallbackSh
         if (CollectionUtils.isEmpty(uriList)) {
             return "";
         }
-        SelectorDO selectorDO = 
selectorService.findByNameAndPluginName(selectorName, 
PluginNameAdapter.rpcTypeAdapter(rpcType()));
+        String pluginName = PluginNameAdapter.rpcTypeAdapter(rpcType());
+        SelectorDO selectorDO = 
selectorService.findByNameAndPluginName(selectorName, pluginName);
         if (Objects.isNull(selectorDO)) {
             throw new ShenyuException("doRegister Failed to execute,wait to 
retry.");
         }
@@ -174,11 +187,36 @@ public abstract class 
AbstractShenyuClientRegisterServiceImpl extends FallbackSh
             // update db
             selectorService.updateSelective(selectorDO);
             // publish change event.
-            eventPublisher.publishEvent(new 
DataChangedEvent(ConfigGroupEnum.SELECTOR, DataEventTypeEnum.UPDATE, 
Collections.singletonList(selectorData)));
+            doDiscoveryLocal(selectorDO, pluginName, validUriList);
         }
         return ShenyuResultMessage.SUCCESS;
     }
 
+    protected void doDiscoveryLocal(final SelectorDO selectorDO, final String 
pluginName, final List<URIRegisterDTO> uriList) {
+        String discoveryHandlerId = 
discoveryService.registerDefaultDiscovery(selectorDO.getId(), pluginName);
+        for (URIRegisterDTO uriRegisterDTO : uriList) {
+            DiscoveryUpstreamDTO discoveryUpstreamDTO = 
CommonUpstreamUtils.buildDefaultDiscoveryUpstreamDTO(uriRegisterDTO.getHost(), 
uriRegisterDTO.getPort(), uriRegisterDTO.getProtocol());
+            discoveryUpstreamDTO.setDiscoveryHandlerId(discoveryHandlerId);
+            
discoveryUpstreamService.nativeCreateOrUpdate(discoveryUpstreamDTO);
+        }
+        DiscoverySyncData discoverySyncData = fetch(selectorDO.getId(), 
selectorDO.getName(), pluginName);
+        eventPublisher.publishEvent(new 
DataChangedEvent(ConfigGroupEnum.DISCOVER_UPSTREAM, DataEventTypeEnum.UPDATE, 
Collections.singletonList(discoverySyncData)));
+    }
+
+    protected DiscoverySyncData fetch(final String selectorId, final String 
selectorName, final String pluginName) {
+        List<DiscoveryUpstreamData> discoveryUpstreamDataList = 
discoveryUpstreamService.findBySelectorId(selectorId);
+        DiscoverySyncData discoverySyncData = new DiscoverySyncData();
+        discoverySyncData.setUpstreamDataList(discoveryUpstreamDataList);
+        discoverySyncData.setPluginName(pluginName);
+        discoverySyncData.setSelectorId(selectorId);
+        discoverySyncData.setSelectorName(selectorName);
+        return discoverySyncData;
+    }
+
+    protected void removeDiscoveryUpstream(final String selectorId, final 
String url) {
+        discoveryUpstreamService.deleteBySelectorIdAndUrl(selectorId, url);
+    }
+
     /**
      * Gets meta data service.
      *
diff --git 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/register/ShenyuClientRegisterDivideServiceImpl.java
 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/register/ShenyuClientRegisterDivideServiceImpl.java
index 066c9bd491..0c08cc4b1f 100644
--- 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/register/ShenyuClientRegisterDivideServiceImpl.java
+++ 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/service/register/ShenyuClientRegisterDivideServiceImpl.java
@@ -27,6 +27,7 @@ import org.apache.shenyu.admin.service.SelectorService;
 import org.apache.shenyu.admin.service.converter.DivideSelectorHandleConverter;
 import org.apache.shenyu.admin.utils.CommonUpstreamUtils;
 import org.apache.shenyu.common.constant.Constants;
+import org.apache.shenyu.common.dto.DiscoverySyncData;
 import org.apache.shenyu.common.dto.SelectorData;
 import org.apache.shenyu.common.dto.convert.rule.impl.DivideRuleHandle;
 import org.apache.shenyu.common.dto.convert.selector.DivideUpstream;
@@ -115,11 +116,12 @@ public class ShenyuClientRegisterDivideServiceImpl 
extends AbstractContextPathRe
                 .map(dto -> 
CommonUpstreamUtils.buildDivideUpstream(dto.getProtocol(), dto.getHost(), 
dto.getPort()))
                 .collect(Collectors.toCollection(CopyOnWriteArrayList::new));
     }
-    
+
     @Override
     public String offline(final String selectorName, final 
List<URIRegisterDTO> uriList) {
         final SelectorService selectorService = getSelectorService();
-        SelectorDO selectorDO = 
selectorService.findByNameAndPluginName(selectorName, 
PluginNameAdapter.rpcTypeAdapter(rpcType()));
+        String pluginName = PluginNameAdapter.rpcTypeAdapter(rpcType());
+        SelectorDO selectorDO = 
selectorService.findByNameAndPluginName(selectorName, pluginName);
         if (Objects.isNull(selectorDO)) {
             return Constants.SUCCESS;
         }
@@ -136,7 +138,16 @@ public class ShenyuClientRegisterDivideServiceImpl extends 
AbstractContextPathRe
         // update db
         selectorService.updateSelective(selectorDO);
         // publish change event.
-        getEventPublisher().publishEvent(new 
DataChangedEvent(ConfigGroupEnum.SELECTOR, DataEventTypeEnum.UPDATE, 
Collections.singletonList(selectorData)));
+        doRemoveAndSendEvent(needToRemove, selectorDO, pluginName);
         return Constants.SUCCESS;
     }
+
+    private void doRemoveAndSendEvent(final List<DivideUpstream> needToRemove, 
final SelectorDO selectorDO, final String pluginName) {
+        for (DivideUpstream divideUpstream : needToRemove) {
+            removeDiscoveryUpstream(selectorDO.getId(), 
divideUpstream.getUpstreamUrl());
+        }
+        DiscoverySyncData discoverySyncData = fetch(selectorDO.getId(), 
selectorDO.getName(), pluginName);
+        getEventPublisher().publishEvent(new 
DataChangedEvent(ConfigGroupEnum.DISCOVER_UPSTREAM, DataEventTypeEnum.UPDATE, 
Collections.singletonList(discoverySyncData)));
+    }
+
 }
diff --git 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/utils/CommonUpstreamUtils.java
 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/utils/CommonUpstreamUtils.java
index c37d862167..766fff1faf 100644
--- 
a/shenyu-admin/src/main/java/org/apache/shenyu/admin/utils/CommonUpstreamUtils.java
+++ 
b/shenyu-admin/src/main/java/org/apache/shenyu/admin/utils/CommonUpstreamUtils.java
@@ -18,6 +18,7 @@
 package org.apache.shenyu.admin.utils;
 
 import org.apache.commons.lang3.StringUtils;
+import org.apache.shenyu.admin.model.dto.DiscoveryUpstreamDTO;
 import org.apache.shenyu.common.constant.Constants;
 import org.apache.shenyu.common.dto.convert.selector.CommonUpstream;
 import org.apache.shenyu.common.dto.convert.selector.DivideUpstream;
@@ -38,7 +39,9 @@ import java.util.stream.Collectors;
 public class CommonUpstreamUtils {
 
     private static final String LOCALHOST = "localhost";
-    
+
+    private static final Integer DEFAULT_WEIGHT = 50;
+
     /**
      * Build divide upstream divide upstream.
      *
@@ -55,6 +58,24 @@ public class CommonUpstreamUtils {
                 .build();
     }
 
+    /**
+     * buildDefaultDiscoveryUpstreamDTO.
+     *
+     * @param host     host
+     * @param port     port
+     * @param protocol protocol
+     * @return DiscoveryUpstreamDTO
+     */
+    public static DiscoveryUpstreamDTO buildDefaultDiscoveryUpstreamDTO(final 
String host, final Integer port, final String protocol) {
+        DiscoveryUpstreamDTO discoveryUpstreamDTO = new DiscoveryUpstreamDTO();
+        discoveryUpstreamDTO.setProps("{}");
+        discoveryUpstreamDTO.setUrl(buildUrl(host, port));
+        discoveryUpstreamDTO.setProtocol(protocol);
+        discoveryUpstreamDTO.setStatus(0);
+        discoveryUpstreamDTO.setWeight(DEFAULT_WEIGHT);
+        return discoveryUpstreamDTO;
+    }
+
     /**
      * Build alive divide upstream.
      *
@@ -64,7 +85,7 @@ public class CommonUpstreamUtils {
     public static DivideUpstream buildDefaultAliveDivideUpstream(final String 
upstreamUrl) {
         return DivideUpstream.builder().upstreamHost(LOCALHOST)
                 .protocol("http://";).upstreamUrl(upstreamUrl)
-                .weight(50).warmup(Constants.WARMUP_TIME)
+                .weight(DEFAULT_WEIGHT).warmup(Constants.WARMUP_TIME)
                 .timestamp(System.currentTimeMillis()).build();
     }
 
@@ -72,8 +93,8 @@ public class CommonUpstreamUtils {
      * Build divide upstream divide upstream.
      *
      * @param protocol the protocol
-     * @param host the host
-     * @param port the port
+     * @param host     the host
+     * @param port     the port
      * @return the divide upstream
      */
     public static DivideUpstream buildDivideUpstream(final String protocol, 
final String host, final Integer port) {
@@ -88,7 +109,7 @@ public class CommonUpstreamUtils {
     /**
      * Build alive divide upstream.
      *
-     * @param protocol the protocol
+     * @param protocol    the protocol
      * @param upstreamUrl the upstreamUrl
      * @return the divide upstream
      */
@@ -103,13 +124,13 @@ public class CommonUpstreamUtils {
      * Build websocket upstream divide upstream.
      *
      * @param protocol the protocol
-     * @param host the host
-     * @param port the port
+     * @param host     the host
+     * @param port     the port
      * @return the websocket upstream
      */
     public static WebSocketUpstream buildWebSocketUpstream(final String 
protocol, final String host, final Integer port) {
         return WebSocketUpstream.builder().host(LOCALHOST).protocol(protocol)
-                .upstreamUrl(buildUrl(host, port)).weight(50)
+                .upstreamUrl(buildUrl(host, port)).weight(DEFAULT_WEIGHT)
                 .warmup(Constants.WARMUP_TIME)
                 .timestamp(System.currentTimeMillis())
                 .status(Objects.nonNull(port) && StringUtils.isNotBlank(host))
@@ -126,7 +147,7 @@ public class CommonUpstreamUtils {
     public static DubboUpstream buildDefaultDubboUpstream(final String host, 
final Integer port) {
         return DubboUpstream.builder().upstreamHost(LOCALHOST)
                 .protocol("dubbo://").upstreamUrl(buildUrl(host, port))
-                .weight(50).warmup(Constants.WARMUP_TIME)
+                .weight(DEFAULT_WEIGHT).warmup(Constants.WARMUP_TIME)
                 .timestamp(System.currentTimeMillis())
                 .status(Objects.nonNull(port) && StringUtils.isNotBlank(host))
                 .build();
@@ -140,7 +161,7 @@ public class CommonUpstreamUtils {
      */
     public static DubboUpstream buildAliveDubboUpstream(final String 
upstreamUrl) {
         return DubboUpstream.builder().upstreamHost(LOCALHOST)
-                .protocol("dubbo://").upstreamUrl(upstreamUrl).weight(50)
+                
.protocol("dubbo://").upstreamUrl(upstreamUrl).weight(DEFAULT_WEIGHT)
                 .warmup(Constants.WARMUP_TIME)
                 .timestamp(System.currentTimeMillis())
                 .build();
@@ -155,7 +176,7 @@ public class CommonUpstreamUtils {
      */
     public static GrpcUpstream buildDefaultGrpcUpstream(final String host, 
final Integer port) {
         return GrpcUpstream.builder().upstreamUrl(buildUrl(host, port))
-                .weight(50).timestamp(System.currentTimeMillis())
+                .weight(DEFAULT_WEIGHT).timestamp(System.currentTimeMillis())
                 .status(Objects.nonNull(port) && StringUtils.isNotBlank(host))
                 .build();
     }
@@ -180,7 +201,7 @@ public class CommonUpstreamUtils {
      */
     public static TarsUpstream buildDefaultTarsUpstream(final String host, 
final Integer port) {
         return TarsUpstream.builder().upstreamUrl(buildUrl(host, port))
-                .weight(50).warmup(Constants.WARMUP_TIME)
+                .weight(DEFAULT_WEIGHT).warmup(Constants.WARMUP_TIME)
                 .timestamp(System.currentTimeMillis())
                 .status(Objects.nonNull(port) && StringUtils.isNotBlank(host))
                 .build();
@@ -193,7 +214,7 @@ public class CommonUpstreamUtils {
      * @return the tars upstream
      */
     public static TarsUpstream buildAliveTarsUpstream(final String 
upstreamUrl) {
-        return TarsUpstream.builder().upstreamUrl(upstreamUrl).weight(50)
+        return 
TarsUpstream.builder().upstreamUrl(upstreamUrl).weight(DEFAULT_WEIGHT)
                 .warmup(Constants.WARMUP_TIME)
                 .timestamp(System.currentTimeMillis())
                 .build();
@@ -214,7 +235,7 @@ public class CommonUpstreamUtils {
                         upstream.isStatus(), upstream.getTimestamp()))
                 .collect(Collectors.toList());
     }
-    
+
     /**
      * Build url string.
      *
diff --git 
a/shenyu-admin/src/main/resources/mappers/discovery-handler-sqlmap.xml 
b/shenyu-admin/src/main/resources/mappers/discovery-handler-sqlmap.xml
index 17a33a81f2..a3f0a86cdc 100644
--- a/shenyu-admin/src/main/resources/mappers/discovery-handler-sqlmap.xml
+++ b/shenyu-admin/src/main/resources/mappers/discovery-handler-sqlmap.xml
@@ -76,6 +76,18 @@
         where discovery_id = #{discoveryId , jdbcType=LONGVARCHAR}
     </select>
 
+    <select id="selectBySelectorId" 
resultType="org.apache.shenyu.admin.model.entity.DiscoveryHandlerDO">
+        SELECT
+        dh.id,
+        dh.date_created,
+        dh.date_updated,
+        dh.discovery_id,
+        dh.handler,
+        dh.listener_node
+        FROM discovery_handler dh inner join discovery_rel dr on dh.id = 
dr.discovery_handler_id
+        WHERE dr.selector_id = #{selectorId, jdbcType=VARCHAR}
+    </select>
+
     <insert id="insert" keyColumn="id" keyProperty="id" useGeneratedKeys="true"
             
parameterType="org.apache.shenyu.admin.model.entity.DiscoveryHandlerDO">
         INSERT INTO discovery_handler
diff --git 
a/shenyu-admin/src/test/java/org/apache/shenyu/admin/service/register/AbstractShenyuClientRegisterServiceImplTest.java
 
b/shenyu-admin/src/test/java/org/apache/shenyu/admin/service/register/AbstractShenyuClientRegisterServiceImplTest.java
index 12e99226a5..e9f23ca524 100644
--- 
a/shenyu-admin/src/test/java/org/apache/shenyu/admin/service/register/AbstractShenyuClientRegisterServiceImplTest.java
+++ 
b/shenyu-admin/src/test/java/org/apache/shenyu/admin/service/register/AbstractShenyuClientRegisterServiceImplTest.java
@@ -29,6 +29,7 @@ import org.apache.shenyu.admin.service.MetaDataService;
 import org.apache.shenyu.admin.service.impl.UpstreamCheckService;
 import org.apache.shenyu.admin.service.manager.RegisterApiDocService;
 import org.apache.shenyu.admin.utils.ShenyuResultMessage;
+import org.apache.shenyu.common.dto.DiscoverySyncData;
 import org.apache.shenyu.common.dto.SelectorData;
 import org.apache.shenyu.common.dto.convert.selector.CommonUpstream;
 import org.apache.shenyu.common.exception.ShenyuException;
@@ -208,6 +209,20 @@ public final class 
AbstractShenyuClientRegisterServiceImplTest {
             return "buildHandle";
         }
 
+        @Override
+        protected void doDiscoveryLocal(final SelectorDO selectorDO, final 
String pluginName, final List<URIRegisterDTO> uriList) {
+
+        }
+
+        @Override
+        protected DiscoverySyncData fetch(final String selectorId, final 
String selectorName, final String pluginName) {
+            return new DiscoverySyncData();
+        }
+
+        @Override
+        protected void removeDiscoveryUpstream(final String selectorId, final 
String url) {
+        }
+
         @Override
         public String rpcType() {
             return "grpc";
diff --git 
a/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/client/AbstractContextRefreshedEventListener.java
 
b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/client/AbstractContextRefreshedEventListener.java
index 0ac55612be..133761c2a4 100644
--- 
a/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/client/AbstractContextRefreshedEventListener.java
+++ 
b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/client/AbstractContextRefreshedEventListener.java
@@ -86,7 +86,7 @@ public abstract class 
AbstractContextRefreshedEventListener<T, A extends Annotat
     private final ShenyuClientRegisterEventPublisher publisher = 
ShenyuClientRegisterEventPublisher.getInstance();
 
     private final AtomicBoolean registered = new AtomicBoolean(false);
-    
+
     private final Map<Method, MetaDataRegisterDTO> metaDataMap = new 
ConcurrentHashMap<>();
 
     private final String appName;
@@ -98,9 +98,11 @@ public abstract class 
AbstractContextRefreshedEventListener<T, A extends Annotat
     private final String host;
 
     private final String port;
-    
+
     private ApplicationContext context;
 
+    private final Boolean isDiscoveryLocalMode;
+
     /**
      * Instantiates a new context refreshed event listener.
      *
@@ -120,6 +122,7 @@ public abstract class 
AbstractContextRefreshedEventListener<T, A extends Annotat
         this.ipAndPort = props.getProperty(ShenyuClientConstants.IP_PORT);
         this.host = props.getProperty(ShenyuClientConstants.HOST);
         this.port = props.getProperty(ShenyuClientConstants.PORT);
+        this.isDiscoveryLocalMode = 
Boolean.valueOf(props.getProperty(ShenyuClientConstants.DISCOVERY_LOCAL_MODE_KEY));
         publisher.start(shenyuClientRegisterRepository);
     }
 
@@ -133,7 +136,9 @@ public abstract class 
AbstractContextRefreshedEventListener<T, A extends Annotat
         if (!registered.compareAndSet(false, true)) {
             return;
         }
-        publisher.publishEvent(buildURIRegisterDTO(context, beans));
+        if (isDiscoveryLocalMode) {
+            publisher.publishEvent(buildURIRegisterDTO(context, beans));
+        }
         beans.forEach(this::handle);
         Map<String, Object> apiModules = 
context.getBeansWithAnnotation(ApiModule.class);
         apiModules.forEach((k, v) -> handleApiDoc(v, beans));
@@ -214,7 +219,7 @@ public abstract class 
AbstractContextRefreshedEventListener<T, A extends Annotat
         }
         return list;
     }
-    
+
     private String buildExtJson(final Method method) {
         final MetaDataRegisterDTO metaData = metaDataMap.get(method);
         if (Objects.isNull(metaData)) {
@@ -230,11 +235,11 @@ public abstract class 
AbstractContextRefreshedEventListener<T, A extends Annotat
         ext = customApiDocExt(ext);
         return GsonUtils.getInstance().toJson(ext);
     }
-    
+
     protected ApiDocRegisterDTO.ApiExt customApiDocExt(final 
ApiDocRegisterDTO.ApiExt ext) {
         return ext;
     }
-    
+
     private String buildDocumentJson(final List<String> tags, final String 
path, final Method method) {
         Map<String, Object> documentMap = ImmutableMap.<String, 
Object>builder()
                 .put("tags", tags)
@@ -330,7 +335,7 @@ public abstract class 
AbstractContextRefreshedEventListener<T, A extends Annotat
     public ShenyuClientRegisterEventPublisher getPublisher() {
         return publisher;
     }
-    
+
     /**
      * Get the metadata map.
      *
@@ -339,7 +344,7 @@ public abstract class 
AbstractContextRefreshedEventListener<T, A extends Annotat
     public Map<Method, MetaDataRegisterDTO> getMetaDataMap() {
         return metaDataMap;
     }
-    
+
     /**
      * Get the app name.
      *
@@ -385,7 +390,7 @@ public abstract class 
AbstractContextRefreshedEventListener<T, A extends Annotat
     public String getPort() {
         return StringUtils.isBlank(this.port) ? "-1" : this.port;
     }
-    
+
     /**
      * Get the context.
      *
diff --git 
a/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/constant/ShenyuClientConstants.java
 
b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/constant/ShenyuClientConstants.java
index 4f9d74b31b..bfac42fe71 100644
--- 
a/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/constant/ShenyuClientConstants.java
+++ 
b/shenyu-client/shenyu-client-core/src/main/java/org/apache/shenyu/client/core/constant/ShenyuClientConstants.java
@@ -21,22 +21,26 @@ package org.apache.shenyu.client.core.constant;
  * ShenyuClientConstants.
  */
 public final class ShenyuClientConstants {
-    
+
     /**
      * the constant of APP_NAME.
      */
     public static final String APP_NAME = "appName";
-    
+
     /**
      * the constant of CONTEXT_PATH.
      */
     public static final String CONTEXT_PATH = "contextPath";
-    
+
+    public static final String DISCOVERY_LOCAL_MODE_KEY = "discoveryLocalMode";
+
+    public static final String DISCOVERY_LOCAL_MODE = "local";
+
     /**
      * the constant of IS_FULL.
      */
     public static final String IS_FULL = "isFull";
-    
+
     /**
      * The constant HTTP.
      */
@@ -51,22 +55,22 @@ public final class ShenyuClientConstants {
      * The constant PROTOCOL.
      */
     public static final String PROTOCOL = "protocol";
-    
+
     /**
      * the constant of HOST.
      */
     public static final String HOST = "host";
-    
+
     /**
      * the constant of PORT.
      */
     public static final String PORT = "port";
-    
+
     /**
      * the constant of IP_PORT.
      */
     public static final String IP_PORT = "ipAndPort";
-    
+
     /**
      * the constant of SERVICE_NAME.
      */
diff --git 
a/shenyu-client/shenyu-client-http/shenyu-client-springmvc/src/test/java/org/apache/shenyu/client/springmvc/init/SpringMvcClientEventListenerTest.java
 
b/shenyu-client/shenyu-client-http/shenyu-client-springmvc/src/test/java/org/apache/shenyu/client/springmvc/init/SpringMvcClientEventListenerTest.java
index 09681b3b43..f7c900cb3c 100644
--- 
a/shenyu-client/shenyu-client-http/shenyu-client-springmvc/src/test/java/org/apache/shenyu/client/springmvc/init/SpringMvcClientEventListenerTest.java
+++ 
b/shenyu-client/shenyu-client-http/shenyu-client-springmvc/src/test/java/org/apache/shenyu/client/springmvc/init/SpringMvcClientEventListenerTest.java
@@ -17,6 +17,7 @@
 
 package org.apache.shenyu.client.springmvc.init;
 
+import org.apache.shenyu.client.core.constant.ShenyuClientConstants;
 import 
org.apache.shenyu.client.core.exception.ShenyuClientIllegalArgumentException;
 import 
org.apache.shenyu.client.core.register.ShenyuClientRegisterRepositoryFactory;
 import org.apache.shenyu.client.springmvc.annotation.ShenyuSpringMvcClient;
@@ -140,6 +141,7 @@ public class SpringMvcClientEventListenerTest {
         }
         properties.setProperty("username", "admin");
         properties.setProperty("password", "123456");
+        properties.setProperty(ShenyuClientConstants.DISCOVERY_LOCAL_MODE_KEY, 
Boolean.TRUE.toString());
         PropertiesConfig config = new PropertiesConfig();
         config.setProps(properties);
         ShenyuRegisterCenterConfig mockRegisterCenter = new 
ShenyuRegisterCenterConfig();
diff --git 
a/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-grpc/src/test/java/org/apache/shenyu/e2e/testcase/grpc/GrpcPluginTest.java
 
b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-grpc/src/test/java/org/apache/shenyu/e2e/testcase/grpc/GrpcPluginTest.java
index 8e5ad64cc7..580d04b2be 100644
--- 
a/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-grpc/src/test/java/org/apache/shenyu/e2e/testcase/grpc/GrpcPluginTest.java
+++ 
b/shenyu-e2e/shenyu-e2e-case/shenyu-e2e-case-grpc/src/test/java/org/apache/shenyu/e2e/testcase/grpc/GrpcPluginTest.java
@@ -25,9 +25,13 @@ import org.apache.shenyu.e2e.engine.annotation.ShenYuTest;
 import org.apache.shenyu.e2e.engine.scenario.specification.CaseSpec;
 import org.apache.shenyu.e2e.enums.ServiceTypeEnum;
 import org.junit.jupiter.api.BeforeAll;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.util.LinkedMultiValueMap;
 import org.springframework.util.MultiValueMap;
 
+import java.util.Map;
+
 @ShenYuTest(environments = {
         @ShenYuTest.Environment(
                 serviceName = "shenyu-e2e-admin",
@@ -50,6 +54,8 @@ import org.springframework.util.MultiValueMap;
 })
 public class GrpcPluginTest {
 
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(GrpcPluginTest.class);
+
     @BeforeAll
     void setup(final AdminClient adminClient, final GatewayClient 
gatewayClient) throws Exception {
 
@@ -66,6 +72,8 @@ public class GrpcPluginTest {
         formData.add("sort", "310");
         formData.add("config", 
"{\"multiSelectorHandle\":\"1\",\"multiRuleHandle\":\"0\",\"threadpool\":\"shared\"}");
         adminClient.changePluginStatus("15", formData);
+        Map<String, Integer> plugins = gatewayClient.getPlugins();
+        LOGGER.info("shenyu e2e plugin list ={}", plugins);
         WaitDataSync.waitGatewayPluginUse(gatewayClient, 
"org.apache.shenyu.plugin.grpc.GrpcPlugin");
     }
 
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 e28f8e5adf..f7a4f30b9d 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
@@ -62,7 +62,7 @@ public final class ApplicationConfigCache {
             });
 
     private final Map<String, Consumer<Object>> watchUpstreamListener = new 
ConcurrentHashMap<>();
-    
+
     private ApplicationConfigCache() {
     }
 
@@ -79,7 +79,7 @@ public final class ApplicationConfigCache {
             throw new ShenyuException(e.getCause());
         }
     }
-    
+
     /**
      * handlerSelector.
      *
@@ -97,7 +97,25 @@ public final class ApplicationConfigCache {
             consumer.accept(System.currentTimeMillis());
         }
     }
-    
+
+    /**
+     * handlerUpstream.
+     *
+     * @param selectorId   selectorId
+     * @param upstreamList upstreamList
+     */
+    public void handlerUpstream(final String selectorId, final 
List<GrpcUpstream> upstreamList) {
+        if (CollectionUtils.isEmpty(upstreamList)) {
+            invalidate(selectorId);
+            return;
+        }
+        grpcUpstreamCachedHandle.get().cachedHandle(selectorId, upstreamList);
+        Consumer<Object> consumer = watchUpstreamListener.get(selectorId);
+        if (Objects.nonNull(consumer)) {
+            consumer.accept(System.currentTimeMillis());
+        }
+    }
+
     /**
      * invalidate client.
      *
@@ -110,7 +128,7 @@ public final class ApplicationConfigCache {
         
ruleCachedHandle.get().removeHandle(CacheKeyUtils.INST.getKey(selectorId, 
Constants.DEFAULT_RULE));
         GrpcClientCache.removeClient(selectorId);
     }
-    
+
     /**
      * Refresh.
      *
@@ -120,7 +138,7 @@ public final class ApplicationConfigCache {
     public void watch(final String key, final Consumer<Object> consumer) {
         watchUpstreamListener.put(key, consumer);
     }
-    
+
     /**
      * Gets instance.
      *
@@ -179,9 +197,9 @@ public final class ApplicationConfigCache {
          * The Instance.
          */
         static final ApplicationConfigCache INSTANCE = new 
ApplicationConfigCache();
-        
+
         private ApplicationConfigCacheInstance() {
-        
+
         }
     }
 }
diff --git 
a/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/handler/GrpcDiscoveryUpstreamDataHandler.java
 
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/handler/GrpcDiscoveryUpstreamDataHandler.java
new file mode 100644
index 0000000000..70bf9262dc
--- /dev/null
+++ 
b/shenyu-plugin/shenyu-plugin-proxy/shenyu-plugin-rpc/shenyu-plugin-grpc/src/main/java/org/apache/shenyu/plugin/grpc/handler/GrpcDiscoveryUpstreamDataHandler.java
@@ -0,0 +1,63 @@
+/*
+ * 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.handler;
+
+import org.apache.shenyu.common.dto.DiscoverySyncData;
+import org.apache.shenyu.common.dto.DiscoveryUpstreamData;
+import org.apache.shenyu.common.dto.convert.selector.GrpcUpstream;
+import org.apache.shenyu.common.enums.PluginEnum;
+import org.apache.shenyu.plugin.base.handler.DiscoveryUpstreamDataHandler;
+import org.apache.shenyu.plugin.grpc.cache.ApplicationConfigCache;
+import org.springframework.util.ObjectUtils;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ *  GrpcDiscoveryUpstreamDataHandler.
+ */
+public class GrpcDiscoveryUpstreamDataHandler implements 
DiscoveryUpstreamDataHandler {
+
+    @Override
+    public void handlerDiscoveryUpstreamData(final DiscoverySyncData 
discoverySyncData) {
+        if (Objects.isNull(discoverySyncData) || 
Objects.isNull(discoverySyncData.getSelectorId())) {
+            return;
+        }
+        
ApplicationConfigCache.getInstance().handlerUpstream(discoverySyncData.getSelectorId(),
 convertUpstreamList(discoverySyncData.getUpstreamDataList()));
+    }
+
+    private List<GrpcUpstream> convertUpstreamList(final 
List<DiscoveryUpstreamData> upstreamList) {
+        if (ObjectUtils.isEmpty(upstreamList)) {
+            return Collections.emptyList();
+        }
+        return upstreamList.stream().map(u -> GrpcUpstream.builder()
+                .protocol(u.getProtocol())
+                .upstreamUrl(u.getUrl())
+                .weight(u.getWeight())
+                .status(0 == u.getStatus())
+                .timestamp(u.getDateUpdated().getTime())
+                .build()).collect(Collectors.toList());
+    }
+
+    @Override
+    public String pluginName() {
+        return PluginEnum.GRPC.getName();
+    }
+}
diff --git 
a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-grpc/src/main/java/org/apache/springboot/starter/client/grpc/ShenyuGrpcClientConfiguration.java
 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-grpc/src/main/java/org/apache/springboot/starter/client/grpc/ShenyuGrpcClientConfiguration.java
index fe170d64e6..230ffc2657 100644
--- 
a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-grpc/src/main/java/org/apache/springboot/starter/client/grpc/ShenyuGrpcClientConfiguration.java
+++ 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-grpc/src/main/java/org/apache/springboot/starter/client/grpc/ShenyuGrpcClientConfiguration.java
@@ -17,6 +17,7 @@
 
 package org.apache.springboot.starter.client.grpc;
 
+import org.apache.shenyu.client.core.constant.ShenyuClientConstants;
 import org.apache.shenyu.client.grpc.GrpcClientEventListener;
 import org.apache.shenyu.client.grpc.server.GrpcServerBuilder;
 import org.apache.shenyu.client.grpc.server.GrpcServerRunner;
@@ -29,6 +30,9 @@ import 
org.springframework.boot.autoconfigure.ImportAutoConfiguration;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+
+import java.util.Properties;
 
 /**
  * Grpc type client bean postprocessor.
@@ -45,13 +49,21 @@ public class ShenyuGrpcClientConfiguration {
     /**
      * Grpc client event listener.
      *
-     * @param clientConfig the client config
+     * @param clientConfig                   the client config
+     * @param env                            env
      * @param shenyuClientRegisterRepository the shenyu client register 
repository
      * @return the grpc client bean post processor
      */
     @Bean
     public GrpcClientEventListener grpcClientEventListener(final 
ShenyuClientConfig clientConfig,
-                                                                final 
ShenyuClientRegisterRepository shenyuClientRegisterRepository) {
+                                                           final Environment 
env,
+                                                           final 
ShenyuClientRegisterRepository shenyuClientRegisterRepository) {
+        ShenyuClientConfig.ClientPropertiesConfig clientPropertiesConfig = 
clientConfig.getClient().get(RpcTypeEnum.GRPC.getName());
+        Properties props = clientPropertiesConfig == null ? null : 
clientPropertiesConfig.getProps();
+        String discoveryMode = env.getProperty("shenyu.discovery.mode", 
ShenyuClientConstants.DISCOVERY_LOCAL_MODE);
+        if (props != null) {
+            props.setProperty(ShenyuClientConstants.DISCOVERY_LOCAL_MODE_KEY, 
Boolean.valueOf(ShenyuClientConstants.DISCOVERY_LOCAL_MODE.equals(discoveryMode)).toString());
+        }
         return new 
GrpcClientEventListener(clientConfig.getClient().get(RpcTypeEnum.GRPC.getName()),
 shenyuClientRegisterRepository);
     }
     
diff --git 
a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-spring-websocket/src/main/java/org/apache/shenyu/springboot/starter/client/spring/websocket/ShenyuSpringWebSocketClientConfiguration.java
 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-spring-websocket/src/main/java/org/apache/shenyu/springboot/starter/client/spring/websocket/ShenyuSpringWebSocketClientConfiguration.java
index 8da0dad933..3111eeef18 100644
--- 
a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-spring-websocket/src/main/java/org/apache/shenyu/springboot/starter/client/spring/websocket/ShenyuSpringWebSocketClientConfiguration.java
+++ 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-spring-websocket/src/main/java/org/apache/shenyu/springboot/starter/client/spring/websocket/ShenyuSpringWebSocketClientConfiguration.java
@@ -32,6 +32,8 @@ import 
org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.core.env.Environment;
+import java.util.Properties;
 
 /**
  * The type shenyu websocket client http configuration.
@@ -50,12 +52,20 @@ public class ShenyuSpringWebSocketClientConfiguration {
      *
      * @param clientConfig                   the client config
      * @param shenyuClientRegisterRepository the shenyu client register 
repository
+     * @param env env
      * @return the spring web socket client event listener
      */
     @Bean
     public SpringWebSocketClientEventListener 
springWebSocketClientEventListener(
             final ShenyuClientConfig clientConfig,
+            final Environment env,
             final ShenyuClientRegisterRepository 
shenyuClientRegisterRepository) {
+        ShenyuClientConfig.ClientPropertiesConfig clientPropertiesConfig = 
clientConfig.getClient().get(RpcTypeEnum.WEB_SOCKET.getName());
+        Properties props = clientPropertiesConfig == null ? null : 
clientPropertiesConfig.getProps();
+        String discoveryMode = env.getProperty("shenyu.discovery.mode", 
ShenyuClientConstants.DISCOVERY_LOCAL_MODE);
+        if (props != null) {
+            props.setProperty(ShenyuClientConstants.DISCOVERY_LOCAL_MODE_KEY, 
Boolean.valueOf(ShenyuClientConstants.DISCOVERY_LOCAL_MODE.equals(discoveryMode)).toString());
+        }
         return new 
SpringWebSocketClientEventListener(clientConfig.getClient().get(RpcTypeEnum.WEB_SOCKET.getName()),
 shenyuClientRegisterRepository);
     }
 
diff --git 
a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-springmvc/src/main/java/org/apache/shenyu/springboot/starter/client/springmvc/ShenyuSpringMvcClientConfiguration.java
 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-springmvc/src/main/java/org/apache/shenyu/springboot/starter/client/springmvc/ShenyuSpringMvcClientConfiguration.java
index c8db8562ee..df3c10cad4 100644
--- 
a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-springmvc/src/main/java/org/apache/shenyu/springboot/starter/client/springmvc/ShenyuSpringMvcClientConfiguration.java
+++ 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-client/shenyu-spring-boot-starter-client-springmvc/src/main/java/org/apache/shenyu/springboot/starter/client/springmvc/ShenyuSpringMvcClientConfiguration.java
@@ -63,11 +63,12 @@ public class ShenyuSpringMvcClientConfiguration {
     @Bean
     @ConditionalOnMissingBean(ClientRegisterConfiguration.class)
     public SpringMvcClientEventListener springHttpClientEventListener(final 
ShenyuClientConfig clientConfig,
-                                                                          
final ShenyuClientRegisterRepository shenyuClientRegisterRepository,
-                                                                          
final Environment env) {
+                                                                      final 
ShenyuClientRegisterRepository shenyuClientRegisterRepository,
+                                                                      final 
Environment env) {
         ClientPropertiesConfig clientPropertiesConfig = 
clientConfig.getClient().get(RpcTypeEnum.HTTP.getName());
         Properties props = clientPropertiesConfig == null ? null : 
clientPropertiesConfig.getProps();
         String applicationName = env.getProperty("spring.application.name");
+        String discoveryMode = env.getProperty("shenyu.discovery.mode", 
ShenyuClientConstants.DISCOVERY_LOCAL_MODE);
         if (props != null) {
             String appName = props.getProperty(ShenyuClientConstants.APP_NAME);
             if (StringUtils.isBlank(appName)) {
@@ -77,6 +78,7 @@ public class ShenyuSpringMvcClientConfiguration {
             if (StringUtils.isBlank(contextPath)) {
                 props.setProperty(ShenyuClientConstants.CONTEXT_PATH, 
String.format("/%s", applicationName));
             }
+            props.setProperty(ShenyuClientConstants.DISCOVERY_LOCAL_MODE_KEY, 
Boolean.valueOf(ShenyuClientConstants.DISCOVERY_LOCAL_MODE.equals(discoveryMode)).toString());
         }
         return new SpringMvcClientEventListener(clientPropertiesConfig, 
shenyuClientRegisterRepository, env);
     }
@@ -84,7 +86,7 @@ public class ShenyuSpringMvcClientConfiguration {
     /**
      * clientDiscoveryConfigRefreshedEventListener Bean.
      *
-     * @param shenyuDiscoveryConfig shenyuDiscoveryConfig
+     * @param shenyuDiscoveryConfig        shenyuDiscoveryConfig
      * @param httpClientRegisterRepository httpClientRegisterRepository
      * @return ClientDiscoveryConfigRefreshedEventListener
      */
diff --git 
a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-grpc/src/main/java/org/apache/shenyu/springboot/starter/plugin/grpc/GrpcPluginConfiguration.java
 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-grpc/src/main/java/org/apache/shenyu/springboot/starter/plugin/grpc/GrpcPluginConfiguration.java
index 32ef289d7a..0b4bb9da76 100644
--- 
a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-grpc/src/main/java/org/apache/shenyu/springboot/starter/plugin/grpc/GrpcPluginConfiguration.java
+++ 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-grpc/src/main/java/org/apache/shenyu/springboot/starter/plugin/grpc/GrpcPluginConfiguration.java
@@ -19,9 +19,11 @@ package org.apache.shenyu.springboot.starter.plugin.grpc;
 
 import org.apache.shenyu.plugin.api.ShenyuPlugin;
 import org.apache.shenyu.plugin.api.context.ShenyuContextDecorator;
+import org.apache.shenyu.plugin.base.handler.DiscoveryUpstreamDataHandler;
 import org.apache.shenyu.plugin.base.handler.PluginDataHandler;
 import org.apache.shenyu.plugin.grpc.GrpcPlugin;
 import org.apache.shenyu.plugin.grpc.context.GrpcShenyuContextDecorator;
+import org.apache.shenyu.plugin.grpc.handler.GrpcDiscoveryUpstreamDataHandler;
 import org.apache.shenyu.plugin.grpc.handler.GrpcPluginDataHandler;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.context.annotation.Bean;
@@ -54,6 +56,17 @@ public class GrpcPluginConfiguration {
         return new GrpcPluginDataHandler();
     }
 
+    /**
+     * Grpc data handler.
+     *
+     * @return the plugin data handler
+     */
+    @Bean
+    public DiscoveryUpstreamDataHandler grpcDiscoveryUpstreamDataHandler() {
+        return new GrpcDiscoveryUpstreamDataHandler();
+    }
+
+
     /**
      * Grpc shenyu context decorator.
      *
diff --git 
a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-websocket/src/main/java/org/apache/shenyu/springboot/plugin/websocket/WebSocketPluginConfiguration.java
 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-websocket/src/main/java/org/apache/shenyu/springboot/plugin/websocket/WebSocketPluginConfiguration.java
index 9a90a9e16a..4e9d8fed44 100644
--- 
a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-websocket/src/main/java/org/apache/shenyu/springboot/plugin/websocket/WebSocketPluginConfiguration.java
+++ 
b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-websocket/src/main/java/org/apache/shenyu/springboot/plugin/websocket/WebSocketPluginConfiguration.java
@@ -19,6 +19,7 @@ package org.apache.shenyu.springboot.plugin.websocket;
 
 import org.apache.shenyu.common.config.ShenyuConfig;
 import org.apache.shenyu.plugin.api.context.ShenyuContextDecorator;
+import org.apache.shenyu.plugin.base.handler.DiscoveryUpstreamDataHandler;
 import org.apache.shenyu.plugin.base.handler.PluginDataHandler;
 import org.apache.shenyu.plugin.websocket.WebSocketPlugin;
 import 
org.apache.shenyu.plugin.websocket.context.WebSocketShenyuContextDecorator;
@@ -98,7 +99,7 @@ public class WebSocketPluginConfiguration {
      * @return the websocket upstream data handler
      */
     @Bean
-    public WebSocketUpstreamDataHandler divideUpstreamDataHandler() {
+    public DiscoveryUpstreamDataHandler webSocketUpstreamDataHandler() {
         return new WebSocketUpstreamDataHandler();
     }
 
diff --git 
a/shenyu-sync-data-center/shenyu-sync-data-http/src/main/java/org/apache/shenyu/sync/data/http/HttpSyncDataService.java
 
b/shenyu-sync-data-center/shenyu-sync-data-http/src/main/java/org/apache/shenyu/sync/data/http/HttpSyncDataService.java
index 29bc0731e9..509bd12b51 100644
--- 
a/shenyu-sync-data-center/shenyu-sync-data-http/src/main/java/org/apache/shenyu/sync/data/http/HttpSyncDataService.java
+++ 
b/shenyu-sync-data-center/shenyu-sync-data-http/src/main/java/org/apache/shenyu/sync/data/http/HttpSyncDataService.java
@@ -163,7 +163,7 @@ public class HttpSyncDataService implements SyncDataService 
{
         }
         // not updated. it is likely that the current config server has not 
been updated yet. wait a moment.
         LOG.info("The config of the server[{}] has not been updated or is out 
of date. Wait for listening for changes again.", server);
-        ThreadUtils.sleep(TimeUnit.SECONDS, 30);
+        ThreadUtils.sleep(TimeUnit.SECONDS, 5);
     }
 
 

Reply via email to