You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shenyu.apache.org by xi...@apache.org on 2022/06/23 16:16:52 UTC

[incubator-shenyu] branch master updated: [type:refeactor] springcloud plugin use shenyu-loadbalancer (#3598)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new b769aaa5e [type:refeactor] springcloud plugin use shenyu-loadbalancer (#3598)
b769aaa5e is described below

commit b769aaa5e0ea3c061e27922e767b0f83a849bb73
Author: moremind <he...@hotmail.com>
AuthorDate: Fri Jun 24 00:16:42 2022 +0800

    [type:refeactor] springcloud plugin use shenyu-loadbalancer (#3598)
    
    * [ISSUE #3552] shenyu-plugin-springcloud use shenyu-loadbalancer
    
    * [ISSUE #3552] shenyu-plugin-springcloud use shenyu-loadbalancer
    
    * [ISSUE #3552] shenyu-plugin-springcloud use shenyu-loadbalancer
    
    * [ISSUE #3552] shenyu-plugin-springcloud use shenyu-loadbalancer
    
    * [ISSUE #3552] shenyu-plugin-springcloud use shenyu-loadbalancer
    
    * [ISSUE #3552] shenyu-plugin-springcloud use shenyu-loadbalancer
    
    * [ISSUE #3552] shenyu-plugin-springcloud use shenyu-loadbalancer
    
    * [ISSUE #3552] shenyu-plugin-springcloud use shenyu-loadbalancer
    
    * [ISSUE #3552] shenyu-plugin-springcloud use shenyu-loadbalancer
    
    * [ISSUE #3552] fix check style
---
 shenyu-bootstrap/pom.xml                           |  11 -
 .../shenyu-integrated-test-spring-cloud/pom.xml    |  16 --
 shenyu-plugin/shenyu-plugin-springcloud/pom.xml    |  20 --
 .../springcloud/loadbalance/LoadBalanceRule.java   |  66 -----
 .../client/CustomBlockingLoadBalancerClient.java   |  61 -----
 .../ShenyuSpringCloudLoadBalancerClient.java       | 305 +++++++++++++++++++++
 .../plugin/springcloud/SpringCloudPluginTest.java  |   4 +-
 .../loadbalance/LoadBalanceRuleTest.java           |  75 -----
 .../ShenyuSpringCloudLoadBalancerClientTest.java   | 202 ++++++++++++++
 .../SpringCloudPluginConfiguration.java            |  61 +----
 .../SpringCloudPluginConfigurationTest.java        |  20 --
 11 files changed, 520 insertions(+), 321 deletions(-)

diff --git a/shenyu-bootstrap/pom.xml b/shenyu-bootstrap/pom.xml
index 60cfd3aaa..eec17d6e2 100644
--- a/shenyu-bootstrap/pom.xml
+++ b/shenyu-bootstrap/pom.xml
@@ -266,17 +266,6 @@
             <artifactId>spring-cloud-commons</artifactId>
             <version>${spring-cloud-commons.version}</version>
         </dependency>
-        <dependency>
-            <groupId>org.springframework.cloud</groupId>
-            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
-            <version>${spring-cloud-netflix-ribbon.version}</version>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.springframework.cloud</groupId>
-                    <artifactId>spring-cloud-starter</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
         <!--shenyu springCloud plugin start-->
 
 
diff --git a/shenyu-integrated-test/shenyu-integrated-test-spring-cloud/pom.xml b/shenyu-integrated-test/shenyu-integrated-test-spring-cloud/pom.xml
index dc54216d3..9e87b124d 100644
--- a/shenyu-integrated-test/shenyu-integrated-test-spring-cloud/pom.xml
+++ b/shenyu-integrated-test/shenyu-integrated-test-spring-cloud/pom.xml
@@ -52,22 +52,6 @@
                 </exclusion>
             </exclusions>
         </dependency>
-
-        <dependency>
-            <groupId>org.springframework.cloud</groupId>
-            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
-            <version>${spring-cloud-netflix-ribbon.version}</version>
-            <exclusions>
-                <exclusion>
-                    <artifactId>spring-cloud-context</artifactId>
-                    <groupId>org.springframework.cloud</groupId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.springframework.cloud</groupId>
-                    <artifactId>spring-cloud-starter</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
         
         <dependency>
             <groupId>org.springframework.cloud</groupId>
diff --git a/shenyu-plugin/shenyu-plugin-springcloud/pom.xml b/shenyu-plugin/shenyu-plugin-springcloud/pom.xml
index 98bb22b14..f61c3cbf7 100644
--- a/shenyu-plugin/shenyu-plugin-springcloud/pom.xml
+++ b/shenyu-plugin/shenyu-plugin-springcloud/pom.xml
@@ -58,25 +58,5 @@
             <artifactId>shenyu-loadbalancer</artifactId>
             <version>${project.version}</version>
         </dependency>
-        <dependency>
-            <groupId>org.springframework.cloud</groupId>
-            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
-            <version>${spring-cloud-netflix-ribbon.version}</version>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.springframework.cloud</groupId>
-                    <artifactId>spring-cloud-netflix-archaius</artifactId>
-                </exclusion>
-                <exclusion>
-                    <artifactId>spring-cloud-starter</artifactId>
-                    <groupId>org.springframework.cloud</groupId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.cloud</groupId>
-            <artifactId>spring-cloud-starter-loadbalancer</artifactId>
-            <version>${spring-cloud-commons.version}</version>
-        </dependency>
     </dependencies>
 </project>
diff --git a/shenyu-plugin/shenyu-plugin-springcloud/src/main/java/org/apache/shenyu/plugin/springcloud/loadbalance/LoadBalanceRule.java b/shenyu-plugin/shenyu-plugin-springcloud/src/main/java/org/apache/shenyu/plugin/springcloud/loadbalance/LoadBalanceRule.java
deleted file mode 100644
index f6c01c86c..000000000
--- a/shenyu-plugin/shenyu-plugin-springcloud/src/main/java/org/apache/shenyu/plugin/springcloud/loadbalance/LoadBalanceRule.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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.springcloud.loadbalance;
-
-import com.netflix.loadbalancer.Server;
-import com.netflix.loadbalancer.ZoneAvoidanceRule;
-import org.apache.commons.collections4.CollectionUtils;
-import org.apache.shenyu.common.dto.convert.selector.SpringCloudSelectorHandle;
-import org.apache.shenyu.loadbalancer.cache.UpstreamCacheManager;
-import org.apache.shenyu.loadbalancer.entity.Upstream;
-import org.apache.shenyu.loadbalancer.factory.LoadBalancerFactory;
-import org.apache.shenyu.plugin.springcloud.handler.SpringCloudPluginDataHandler;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * The spring cloud loadbalancer rule.
- */
-public class LoadBalanceRule extends ZoneAvoidanceRule {
-
-    @Override
-    public Server choose(final Object key) {
-        final LoadBalanceKey loadBalanceKey = LoadBalanceKeyHolder.getLoadBalanceKey();
-        final List<Server> available = getPredicate().getEligibleServers(getLoadBalancer().getAllServers(), key);
-        if (CollectionUtils.isEmpty(available)) {
-            return null;
-        }
-        final SpringCloudSelectorHandle springCloudSelectorHandle = SpringCloudPluginDataHandler.SELECTOR_CACHED.get().obtainHandle(loadBalanceKey.getSelectorId());
-        if (!springCloudSelectorHandle.getGray()) {
-            return super.choose(key);
-        }
-        List<Upstream> divideUpstreams = UpstreamCacheManager.getInstance().findUpstreamListBySelectorId(loadBalanceKey.getSelectorId());
-        if (CollectionUtils.isEmpty(divideUpstreams)) {
-            return super.choose(key);
-        }
-        //select server from available to choose
-        final List<Upstream> choose = new ArrayList<>(available.size());
-        for (Server server : available) {
-            divideUpstreams.stream()
-                    .filter(Upstream::isStatus)
-                    .filter(upstream -> upstream.getUrl().equals(server.getHostPort()))
-                    .findFirst().ifPresent(choose::add);
-        }
-        if (CollectionUtils.isEmpty(choose)) {
-            return super.choose(key);
-        }
-        Upstream upstream = LoadBalancerFactory.selector(choose, loadBalanceKey.getLoadBalance(), loadBalanceKey.getIp());
-        return available.stream().filter(server -> server.getHostPort().equals(upstream.getUrl())).findFirst().orElse(null);
-    }
-}
diff --git a/shenyu-plugin/shenyu-plugin-springcloud/src/main/java/org/apache/shenyu/plugin/springcloud/loadbalance/client/CustomBlockingLoadBalancerClient.java b/shenyu-plugin/shenyu-plugin-springcloud/src/main/java/org/apache/shenyu/plugin/springcloud/loadbalance/client/CustomBlockingLoadBalancerClient.java
deleted file mode 100644
index 34d4c9959..000000000
--- a/shenyu-plugin/shenyu-plugin-springcloud/src/main/java/org/apache/shenyu/plugin/springcloud/loadbalance/client/CustomBlockingLoadBalancerClient.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.springcloud.loadbalance.client;
-
-import org.springframework.cloud.client.ServiceInstance;
-import org.springframework.cloud.client.loadbalancer.Request;
-import org.springframework.cloud.client.loadbalancer.Response;
-import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer;
-import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient;
-import reactor.core.publisher.Mono;
-
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-/**
- * blocking loadbalancer client.
- */
-public class CustomBlockingLoadBalancerClient extends BlockingLoadBalancerClient {
-    private final ReactiveLoadBalancer.Factory<ServiceInstance> loadBalancerClientFactory;
-
-    public CustomBlockingLoadBalancerClient(final ReactiveLoadBalancer.Factory<ServiceInstance> loadBalancerClientFactory) {
-        super(loadBalancerClientFactory);
-        this.loadBalancerClientFactory = loadBalancerClientFactory;
-    }
-
-    @Override
-    public <T> ServiceInstance choose(final String serviceId, final Request<T> request) {
-        ReactiveLoadBalancer<ServiceInstance> loadBalancer = loadBalancerClientFactory.getInstance(serviceId);
-        if (loadBalancer == null) {
-            return null;
-        }
-        CompletableFuture<Response<ServiceInstance>> f = CompletableFuture.supplyAsync(() -> Mono.from(loadBalancer.choose(request)).block());
-        Response<ServiceInstance> loadBalancerResponse = null;
-        try {
-            loadBalancerResponse = f.get(3, TimeUnit.SECONDS);
-        } catch (InterruptedException | ExecutionException | TimeoutException e) {
-            e.printStackTrace();
-        }
-        if (loadBalancerResponse == null) {
-            return null;
-        }
-        return loadBalancerResponse.getServer();
-    }
-}
diff --git a/shenyu-plugin/shenyu-plugin-springcloud/src/main/java/org/apache/shenyu/plugin/springcloud/loadbalance/client/ShenyuSpringCloudLoadBalancerClient.java b/shenyu-plugin/shenyu-plugin-springcloud/src/main/java/org/apache/shenyu/plugin/springcloud/loadbalance/client/ShenyuSpringCloudLoadBalancerClient.java
new file mode 100644
index 000000000..95318999e
--- /dev/null
+++ b/shenyu-plugin/shenyu-plugin-springcloud/src/main/java/org/apache/shenyu/plugin/springcloud/loadbalance/client/ShenyuSpringCloudLoadBalancerClient.java
@@ -0,0 +1,305 @@
+/*
+ * 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.springcloud.loadbalance.client;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.shenyu.common.dto.convert.selector.SpringCloudSelectorHandle;
+import org.apache.shenyu.loadbalancer.cache.UpstreamCacheManager;
+import org.apache.shenyu.loadbalancer.entity.Upstream;
+import org.apache.shenyu.loadbalancer.factory.LoadBalancerFactory;
+import org.apache.shenyu.plugin.springcloud.handler.SpringCloudPluginDataHandler;
+import org.apache.shenyu.plugin.springcloud.loadbalance.LoadBalanceKey;
+import org.apache.shenyu.plugin.springcloud.loadbalance.LoadBalanceKeyHolder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.cloud.client.ServiceInstance;
+import org.springframework.cloud.client.discovery.DiscoveryClient;
+import org.springframework.cloud.client.loadbalancer.CompletionContext;
+import org.springframework.cloud.client.loadbalancer.DefaultRequest;
+import org.springframework.cloud.client.loadbalancer.DefaultRequestContext;
+import org.springframework.cloud.client.loadbalancer.DefaultResponse;
+import org.springframework.cloud.client.loadbalancer.EmptyResponse;
+import org.springframework.cloud.client.loadbalancer.HttpRequestLoadBalancerRequest;
+import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
+import org.springframework.cloud.client.loadbalancer.LoadBalancerLifecycle;
+import org.springframework.cloud.client.loadbalancer.LoadBalancerLifecycleValidator;
+import org.springframework.cloud.client.loadbalancer.LoadBalancerProperties;
+import org.springframework.cloud.client.loadbalancer.LoadBalancerRequest;
+import org.springframework.cloud.client.loadbalancer.LoadBalancerRequestAdapter;
+import org.springframework.cloud.client.loadbalancer.LoadBalancerUriTools;
+import org.springframework.cloud.client.loadbalancer.Request;
+import org.springframework.cloud.client.loadbalancer.RequestData;
+import org.springframework.cloud.client.loadbalancer.RequestDataContext;
+import org.springframework.cloud.client.loadbalancer.ResponseData;
+import org.springframework.cloud.client.loadbalancer.TimedRequestContext;
+import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer;
+import org.springframework.http.HttpRequest;
+import org.springframework.http.client.ClientHttpResponse;
+import org.springframework.util.ReflectionUtils;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer.REQUEST;
+
+/**
+ * spring cloud plugin loadbalancer.
+ */
+public class ShenyuSpringCloudLoadBalancerClient implements LoadBalancerClient {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ShenyuSpringCloudLoadBalancerClient.class);
+
+    private final DiscoveryClient discoveryClient;
+
+    private final ReactiveLoadBalancer.Factory<ServiceInstance> loadBalancerClientFactory;
+
+    public ShenyuSpringCloudLoadBalancerClient(final DiscoveryClient discoveryClient,
+                                               final ReactiveLoadBalancer.Factory<ServiceInstance> loadBalancerClientFactory) {
+        this.discoveryClient = discoveryClient;
+        this.loadBalancerClientFactory = loadBalancerClientFactory;
+    }
+
+    @Override
+    public <T> T execute(final String serviceId, final LoadBalancerRequest<T> request) throws IOException {
+        String hint = getHint(serviceId);
+        LoadBalancerRequestAdapter<T, TimedRequestContext> lbRequest = new LoadBalancerRequestAdapter<>(request,
+                buildRequestContext(request, hint));
+        Set<LoadBalancerLifecycle> supportedLifecycleProcessors = getSupportedLifecycleProcessors(serviceId);
+        supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onStart(lbRequest));
+        ServiceInstance serviceInstance = choose(serviceId, lbRequest);
+        if (serviceInstance == null) {
+            supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onComplete(
+                    new CompletionContext<>(CompletionContext.Status.DISCARD, lbRequest, new EmptyResponse())));
+            throw new IllegalStateException("No instances available for " + serviceId);
+        }
+        return execute(serviceId, serviceInstance, lbRequest);
+    }
+
+    @Override
+    public <T> T execute(final String serviceId, final ServiceInstance serviceInstance, final LoadBalancerRequest<T> request) throws IOException {
+        DefaultResponse defaultResponse = new DefaultResponse(serviceInstance);
+        Set<LoadBalancerLifecycle> supportedLifecycleProcessors = getSupportedLifecycleProcessors(serviceId);
+        Request lbRequest = request instanceof Request ? (Request) request : new DefaultRequest<>();
+        supportedLifecycleProcessors
+                .forEach(lifecycle -> lifecycle.onStartRequest(lbRequest, new DefaultResponse(serviceInstance)));
+        try {
+            T response = request.apply(serviceInstance);
+            LoadBalancerProperties properties = loadBalancerClientFactory.getProperties(serviceId);
+            Object clientResponse = getClientResponse(response, properties.isUseRawStatusCodeInResponseData());
+            supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onComplete(new CompletionContext<>(CompletionContext.Status.SUCCESS,
+                            lbRequest, defaultResponse, clientResponse)));
+            return response;
+        } catch (IOException ioException) {
+            supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onComplete(
+                    new CompletionContext<>(CompletionContext.Status.FAILED, ioException, lbRequest, defaultResponse)));
+            throw ioException;
+        } catch (Exception exception) {
+            supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onComplete(
+                    new CompletionContext<>(CompletionContext.Status.FAILED, exception, lbRequest, defaultResponse)));
+            ReflectionUtils.rethrowRuntimeException(exception);
+        } finally {
+            LOG.info("execute serviceInstance error");
+        }
+        return null;
+    }
+
+    @Override
+    public URI reconstructURI(final ServiceInstance instance, final URI original) {
+        return LoadBalancerUriTools.reconstructURI(instance, original);
+    }
+
+    @Override
+    public ServiceInstance choose(final String serviceId) {
+        return choose(serviceId, REQUEST);
+    }
+
+    @Override
+    public <T> ServiceInstance choose(final String serviceId, final Request<T> request) {
+        final LoadBalanceKey loadBalanceKey = LoadBalanceKeyHolder.getLoadBalanceKey();
+        List<ServiceInstance> available = this.getServiceInstance(serviceId);
+        if (CollectionUtils.isEmpty(available)) {
+            return null;
+        }
+        final SpringCloudSelectorHandle springCloudSelectorHandle = SpringCloudPluginDataHandler.SELECTOR_CACHED.get().obtainHandle(loadBalanceKey.getSelectorId());
+        // not gray flow
+        if (!springCloudSelectorHandle.getGray()) {
+            return this.doSelect(serviceId);
+        }
+        List<Upstream> divideUpstreams = UpstreamCacheManager.getInstance().findUpstreamListBySelectorId(loadBalanceKey.getSelectorId());
+        // gray flow,but upstream is null
+        if (CollectionUtils.isEmpty(divideUpstreams)) {
+            return this.doSelect(serviceId);
+        }
+        //select server from available to choose
+        final List<Upstream> choose = new ArrayList<>(available.size());
+        for (ServiceInstance serviceInstance : available) {
+            divideUpstreams.stream()
+                    .filter(Upstream::isStatus)
+                    .filter(upstream -> Objects.equals(buildUrl(upstream), String.valueOf(serviceInstance.getUri())))
+                    .findFirst().ifPresent(choose::add);
+        }
+        if (CollectionUtils.isEmpty(choose)) {
+            return this.doSelect(serviceId);
+        }
+        // select by divideUpstreams
+        return this.doSelect(serviceId, choose);
+    }
+
+    private <T> TimedRequestContext buildRequestContext(final LoadBalancerRequest<T> delegate, final String hint) {
+        if (delegate instanceof HttpRequestLoadBalancerRequest) {
+            HttpRequest request = ((HttpRequestLoadBalancerRequest<?>) delegate).getHttpRequest();
+            if (request != null) {
+                RequestData requestData = new RequestData(request);
+                return new RequestDataContext(requestData, hint);
+            }
+        }
+        return new DefaultRequestContext(delegate, hint);
+    }
+
+    private Set<LoadBalancerLifecycle> getSupportedLifecycleProcessors(final String serviceId) {
+        return LoadBalancerLifecycleValidator.getSupportedLifecycleProcessors(
+                loadBalancerClientFactory.getInstances(serviceId, LoadBalancerLifecycle.class),
+                DefaultRequestContext.class, Object.class, ServiceInstance.class);
+    }
+
+    private <T> Object getClientResponse(final T response, final boolean useRawStatusCodes) {
+        ClientHttpResponse clientHttpResponse = null;
+        if (response instanceof ClientHttpResponse) {
+            clientHttpResponse = (ClientHttpResponse) response;
+        }
+        if (clientHttpResponse != null) {
+            try {
+                if (useRawStatusCodes) {
+                    return new ResponseData(null, clientHttpResponse);
+                }
+                return new ResponseData(clientHttpResponse, null);
+            } catch (IOException ignored) {
+            } finally {
+                clientHttpResponse.close();
+            }
+        }
+        return response;
+    }
+
+    /**
+     * build url.
+     * @param upstream upstream
+     * @return url
+     */
+    private static String buildUrl(final Upstream upstream) {
+        if (Objects.isNull(upstream)) {
+            return null;
+        }
+        String protocol = upstream.getProtocol();
+        if (StringUtils.isBlank(protocol)) {
+            protocol = "http://";
+        }
+        return protocol + upstream.getUrl().trim();
+    }
+
+    /**
+     * select serviceInstance by shenyu loadbalancer.
+     *
+     * @param serviceId serviceId
+     * @return ServiceInstance
+     */
+    private ServiceInstance doSelect(final String serviceId) {
+        List<Upstream> choose = this.buildUpstream(serviceId);
+        return this.doSelect(serviceId, choose);
+    }
+
+    /**
+     * execute loadbalancer by shenyu loadbalancer.
+     *
+     * @param serviceId serviceId
+     * @param upstreamList upstream list
+     * @return
+     */
+    private ServiceInstance doSelect(final String serviceId, final List<Upstream> upstreamList) {
+        final LoadBalanceKey loadBalanceKey = LoadBalanceKeyHolder.getLoadBalanceKey();
+        // default loadbalancer
+        if (Objects.isNull(loadBalanceKey) || StringUtils.isEmpty(loadBalanceKey.getLoadBalance())) {
+            loadBalanceKey.setLoadBalance("random");
+        }
+        Upstream upstream = LoadBalancerFactory.selector(upstreamList, loadBalanceKey.getLoadBalance(), loadBalanceKey.getIp());
+        List<ServiceInstance> instances = this.getServiceInstance(serviceId);
+
+        Optional<ServiceInstance> serviceInstance = instances.stream().filter(x -> {
+            String url = String.valueOf(x.getUri());
+            return url.equals(buildUrl(upstream));
+        }).findFirst();
+        if (serviceInstance.isPresent()) {
+            ServiceInstance instance = serviceInstance.get();
+            DefaultResponse defaultResponse = new DefaultResponse(instance);
+            return defaultResponse.getServer();
+        }
+        return null;
+    }
+
+    /**
+     * get service instance by serviceId.
+     *
+     * @param serviceId serviceId
+     * @return {@linkplain ServiceInstance}
+     */
+    private List<ServiceInstance> getServiceInstance(final String serviceId) {
+        List<String> serviceNames = discoveryClient.getServices().stream().map(String::toUpperCase).collect(Collectors.toList());
+        if (!serviceNames.contains(serviceId.toUpperCase())) {
+            return Collections.emptyList();
+        }
+        return discoveryClient.getInstances(serviceId);
+    }
+
+    /**
+     * build upstream by service instance.
+     *
+     * @param serviceId serviceId
+     * @return Upstream
+     */
+    private List<Upstream> buildUpstream(final String serviceId) {
+        List<ServiceInstance> serviceInstanceList = this.getServiceInstance(serviceId);
+        if (serviceInstanceList.isEmpty()) {
+            return Collections.emptyList();
+        }
+        return serviceInstanceList.stream().map(x -> {
+            String uri = x.getUri().toString();
+            String[] urlPart = uri.split("\\:\\//");
+            String protocol = urlPart[0];
+            String url = urlPart[1];
+            return Upstream.builder()
+                    .protocol(protocol + "://")
+                    .url(url)
+                    .build();
+        }).collect(Collectors.toList());
+    }
+
+    private String getHint(final String serviceId) {
+        LoadBalancerProperties properties = loadBalancerClientFactory.getProperties(serviceId);
+        String defaultHint = properties.getHint().getOrDefault("default", "default");
+        String hintPropertyValue = properties.getHint().get(serviceId);
+        return hintPropertyValue != null ? hintPropertyValue : defaultHint;
+    }
+}
diff --git a/shenyu-plugin/shenyu-plugin-springcloud/src/test/java/org/apache/shenyu/plugin/springcloud/SpringCloudPluginTest.java b/shenyu-plugin/shenyu-plugin-springcloud/src/test/java/org/apache/shenyu/plugin/springcloud/SpringCloudPluginTest.java
index cb4cddfe5..c43953b2b 100644
--- a/shenyu-plugin/shenyu-plugin-springcloud/src/test/java/org/apache/shenyu/plugin/springcloud/SpringCloudPluginTest.java
+++ b/shenyu-plugin/shenyu-plugin-springcloud/src/test/java/org/apache/shenyu/plugin/springcloud/SpringCloudPluginTest.java
@@ -35,6 +35,7 @@ import org.apache.shenyu.plugin.api.utils.SpringBeanUtils;
 import org.apache.shenyu.plugin.api.utils.WebFluxResultUtils;
 import org.apache.shenyu.plugin.base.utils.CacheKeyUtils;
 import org.apache.shenyu.plugin.springcloud.handler.SpringCloudPluginDataHandler;
+import org.apache.shenyu.plugin.springcloud.loadbalance.client.ShenyuSpringCloudLoadBalancerClient;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -43,7 +44,6 @@ import org.mockito.Mock;
 import org.mockito.junit.jupiter.MockitoExtension;
 import org.mockito.junit.jupiter.MockitoSettings;
 import org.mockito.quality.Strictness;
-import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient;
 import org.springframework.context.ConfigurableApplicationContext;
 import org.springframework.http.HttpMethod;
 import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
@@ -74,7 +74,7 @@ import static org.mockito.Mockito.when;
 public final class SpringCloudPluginTest {
 
     @Mock
-    private RibbonLoadBalancerClient loadBalancerClient;
+    private ShenyuSpringCloudLoadBalancerClient loadBalancerClient;
 
     private SpringCloudPlugin springCloudPlugin;
 
diff --git a/shenyu-plugin/shenyu-plugin-springcloud/src/test/java/org/apache/shenyu/plugin/springcloud/loadbalance/LoadBalanceRuleTest.java b/shenyu-plugin/shenyu-plugin-springcloud/src/test/java/org/apache/shenyu/plugin/springcloud/loadbalance/LoadBalanceRuleTest.java
deleted file mode 100644
index 8f1a2e75e..000000000
--- a/shenyu-plugin/shenyu-plugin-springcloud/src/test/java/org/apache/shenyu/plugin/springcloud/loadbalance/LoadBalanceRuleTest.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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.springcloud.loadbalance;
-
-import com.netflix.loadbalancer.BaseLoadBalancer;
-import com.netflix.loadbalancer.ILoadBalancer;
-import com.netflix.loadbalancer.Server;
-import com.netflix.loadbalancer.ZoneAvoidanceRule;
-import org.apache.shenyu.common.dto.SelectorData;
-import org.apache.shenyu.common.dto.convert.selector.DivideUpstream;
-import org.apache.shenyu.common.dto.convert.selector.SpringCloudSelectorHandle;
-import org.apache.shenyu.common.utils.GsonUtils;
-import org.apache.shenyu.plugin.springcloud.handler.SpringCloudPluginDataHandler;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * The Test Case For LoadBalanceRule.
- */
-public final class LoadBalanceRuleTest {
-
-    private LoadBalanceRule loadBalanceRule = new LoadBalanceRule();
-
-    private SpringCloudPluginDataHandler springCloudPluginDataHandler = new SpringCloudPluginDataHandler();
-
-    @Test
-    public void testChoose() {
-        LoadBalanceKey loadBalanceKey = new LoadBalanceKey();
-        loadBalanceKey.setIp("0.0.0.0");
-        loadBalanceKey.setSelectorId("1");
-        loadBalanceKey.setLoadBalance("random");
-        LoadBalanceKeyHolder.setLoadBalanceKey(loadBalanceKey);
-        ZoneAvoidanceRule zoneAvoidanceRule = new ZoneAvoidanceRule();
-        ILoadBalancer lb = new BaseLoadBalancer();
-        List<Server> list = new ArrayList<>();
-        list.add(new Server("localhost", 8080));
-        lb.addServers(list);
-        loadBalanceRule.setLoadBalancer(lb);
-        List<DivideUpstream> divideUpstreams = new ArrayList<>();
-        DivideUpstream divideUpstream = DivideUpstream.builder()
-                .upstreamUrl("localhost:8080")
-                .build();
-        divideUpstreams.add(divideUpstream);
-        final SpringCloudSelectorHandle springCloudSelectorHandle = SpringCloudSelectorHandle.builder()
-                .serviceId("serviceId")
-                .divideUpstreams(divideUpstreams)
-                .gray(true)
-                .build();
-        final SelectorData selectorData = SelectorData.builder()
-                .handle(GsonUtils.getInstance().toJson(springCloudSelectorHandle))
-                .id("1")
-                .build();
-        springCloudPluginDataHandler.handlerSelector(selectorData);
-        Server server = loadBalanceRule.choose(loadBalanceKey);
-        Assertions.assertEquals(server.getHostPort(), "localhost:8080");
-    }
-}
diff --git a/shenyu-plugin/shenyu-plugin-springcloud/src/test/java/org/apache/shenyu/plugin/springcloud/loadbalance/client/ShenyuSpringCloudLoadBalancerClientTest.java b/shenyu-plugin/shenyu-plugin-springcloud/src/test/java/org/apache/shenyu/plugin/springcloud/loadbalance/client/ShenyuSpringCloudLoadBalancerClientTest.java
new file mode 100644
index 000000000..653ee8f7c
--- /dev/null
+++ b/shenyu-plugin/shenyu-plugin-springcloud/src/test/java/org/apache/shenyu/plugin/springcloud/loadbalance/client/ShenyuSpringCloudLoadBalancerClientTest.java
@@ -0,0 +1,202 @@
+/*
+ * 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.springcloud.loadbalance.client;
+
+import org.apache.shenyu.common.dto.SelectorData;
+import org.apache.shenyu.common.dto.convert.selector.DivideUpstream;
+import org.apache.shenyu.common.dto.convert.selector.SpringCloudSelectorHandle;
+import org.apache.shenyu.common.utils.GsonUtils;
+import org.apache.shenyu.plugin.springcloud.handler.SpringCloudPluginDataHandler;
+import org.apache.shenyu.plugin.springcloud.loadbalance.LoadBalanceKey;
+import org.apache.shenyu.plugin.springcloud.loadbalance.LoadBalanceKeyHolder;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mock;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.mockito.junit.jupiter.MockitoSettings;
+import org.mockito.quality.Strictness;
+import org.springframework.cloud.client.DefaultServiceInstance;
+import org.springframework.cloud.client.ServiceInstance;
+import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClient;
+import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryProperties;
+import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * The Test Case For ShenyuSpringCloudLoadBalancerClientTest.
+ */
+@ExtendWith(MockitoExtension.class)
+@MockitoSettings(strictness = Strictness.LENIENT)
+public class ShenyuSpringCloudLoadBalancerClientTest {
+    @Mock
+    private ReactiveLoadBalancer.Factory<ServiceInstance> loadBalancerClientFactory;
+
+    private SimpleDiscoveryClient discoveryClient;
+
+    private ShenyuSpringCloudLoadBalancerClient loadBalancerClient;
+
+    private final SpringCloudPluginDataHandler springCloudPluginDataHandler = new SpringCloudPluginDataHandler();
+
+    @BeforeEach
+    public void setup() {
+        final List<DefaultServiceInstance> serviceInstanceList = new ArrayList<>();
+        DefaultServiceInstance defaultServiceInstance = new DefaultServiceInstance();
+        defaultServiceInstance.setServiceId("serviceId");
+        defaultServiceInstance.setUri(URI.create("http://localhost:8080"));
+        defaultServiceInstance.setInstanceId("serviceId");
+        defaultServiceInstance.setPort(8080);
+        defaultServiceInstance.setHost("localhost");
+        serviceInstanceList.add(defaultServiceInstance);
+        SimpleDiscoveryProperties simpleDiscoveryProperties = new SimpleDiscoveryProperties();
+        Map<String, List<DefaultServiceInstance>> serviceInstanceMap = new HashMap<>();
+        serviceInstanceMap.put(defaultServiceInstance.getInstanceId(), serviceInstanceList);
+        simpleDiscoveryProperties.setInstances(serviceInstanceMap);
+        discoveryClient = new SimpleDiscoveryClient(simpleDiscoveryProperties);
+        loadBalancerClient = new ShenyuSpringCloudLoadBalancerClient(discoveryClient, loadBalancerClientFactory);
+    }
+
+    @Test
+    public void testChoose() {
+        LoadBalanceKey loadBalanceKey = new LoadBalanceKey();
+        loadBalanceKey.setIp("0.0.0.0");
+        loadBalanceKey.setSelectorId("1");
+        loadBalanceKey.setLoadBalance("roundRobin");
+        LoadBalanceKeyHolder.setLoadBalanceKey(loadBalanceKey);
+
+        // serviceInstance is null
+        ServiceInstance serviceInstanceIsNull = loadBalancerClient.choose("test");
+        Assertions.assertNull(serviceInstanceIsNull);
+
+        // not gray flow
+        List<DivideUpstream> divideUpstreams = new ArrayList<>();
+        DivideUpstream divideUpstream = DivideUpstream.builder()
+                .upstreamUrl("localhost:8080")
+                .build();
+        divideUpstreams.add(divideUpstream);
+        final SpringCloudSelectorHandle springCloudSelectorHandle = SpringCloudSelectorHandle.builder()
+                .serviceId("serviceId")
+                .divideUpstreams(divideUpstreams)
+                .gray(false)
+                .build();
+        final SelectorData selectorData = SelectorData.builder()
+                .handle(GsonUtils.getInstance().toJson(springCloudSelectorHandle))
+                .id("1")
+                .build();
+        springCloudPluginDataHandler.handlerSelector(selectorData);
+        ServiceInstance serviceInstance = loadBalancerClient.choose("serviceId");
+        Assertions.assertNotNull(serviceInstance);
+        Assertions.assertEquals(serviceInstance.getInstanceId(), "serviceId");
+
+        // gray flow
+        springCloudSelectorHandle.setGray(true);
+        final SelectorData selectorDataGray = SelectorData.builder()
+                .handle(GsonUtils.getInstance().toJson(springCloudSelectorHandle))
+                .id("1")
+                .build();
+        springCloudPluginDataHandler.handlerSelector(selectorDataGray);
+        ServiceInstance serviceInstanceGray = loadBalancerClient.choose("serviceId");
+        Assertions.assertNotNull(serviceInstanceGray);
+        Assertions.assertEquals(serviceInstanceGray.getHost(), "localhost");
+    }
+
+    @Test
+    public void testReconstructURI() {
+        LoadBalanceKey loadBalanceKey = new LoadBalanceKey();
+        loadBalanceKey.setIp("0.0.0.0");
+        loadBalanceKey.setSelectorId("1");
+        loadBalanceKey.setLoadBalance("roundRobin");
+        LoadBalanceKeyHolder.setLoadBalanceKey(loadBalanceKey);
+        List<DivideUpstream> divideUpstreams = new ArrayList<>();
+        DivideUpstream divideUpstream = DivideUpstream.builder()
+                .upstreamUrl("localhost:8080")
+                .build();
+        divideUpstreams.add(divideUpstream);
+        final SpringCloudSelectorHandle springCloudSelectorHandle = SpringCloudSelectorHandle.builder()
+                .serviceId("serviceId")
+                .divideUpstreams(divideUpstreams)
+                .gray(false)
+                .build();
+        final SelectorData selectorData = SelectorData.builder()
+                .handle(GsonUtils.getInstance().toJson(springCloudSelectorHandle))
+                .id("1")
+                .build();
+        springCloudPluginDataHandler.handlerSelector(selectorData);
+        ServiceInstance serviceInstance = loadBalancerClient.choose("serviceId");
+        URI uri = loadBalancerClient.reconstructURI(serviceInstance, URI.create("/test"));
+        Assertions.assertEquals(uri.toString(), "http://localhost:8080/test");
+    }
+
+    @Test
+    public void testLoadBalancer() {
+        final List<DefaultServiceInstance> serviceInstances = new ArrayList<>();
+        DefaultServiceInstance defaultServiceInstance = new DefaultServiceInstance();
+        defaultServiceInstance.setServiceId("serviceId");
+        defaultServiceInstance.setUri(URI.create("http://localhost:8081"));
+        defaultServiceInstance.setInstanceId("serviceId");
+        defaultServiceInstance.setPort(8081);
+        defaultServiceInstance.setHost("localhost");
+
+        DefaultServiceInstance defaultServiceInstance2 = new DefaultServiceInstance();
+        defaultServiceInstance2.setServiceId("serviceId");
+        defaultServiceInstance2.setUri(URI.create("http://localhost:8080"));
+        defaultServiceInstance2.setInstanceId("serviceId");
+        defaultServiceInstance2.setPort(8080);
+        defaultServiceInstance2.setHost("localhost");
+        serviceInstances.add(defaultServiceInstance);
+        serviceInstances.add(defaultServiceInstance2);
+
+        SimpleDiscoveryProperties simpleDiscoveryProperties = new SimpleDiscoveryProperties();
+        Map<String, List<DefaultServiceInstance>> serviceInstanceMap = new HashMap<>();
+        serviceInstanceMap.put(defaultServiceInstance.getInstanceId(), serviceInstances);
+        simpleDiscoveryProperties.setInstances(serviceInstanceMap);
+        discoveryClient = new SimpleDiscoveryClient(simpleDiscoveryProperties);
+        loadBalancerClient = new ShenyuSpringCloudLoadBalancerClient(discoveryClient, loadBalancerClientFactory);
+
+        LoadBalanceKey loadBalanceKey = new LoadBalanceKey();
+        loadBalanceKey.setIp("0.0.0.0");
+        loadBalanceKey.setSelectorId("1");
+        loadBalanceKey.setLoadBalance("roundRobin");
+        LoadBalanceKeyHolder.setLoadBalanceKey(loadBalanceKey);
+        List<DivideUpstream> divideUpstreams = new ArrayList<>();
+        DivideUpstream divideUpstream = DivideUpstream.builder()
+                .upstreamUrl("localhost:8080")
+                .build();
+        divideUpstreams.add(divideUpstream);
+        final SpringCloudSelectorHandle springCloudSelectorHandle = SpringCloudSelectorHandle.builder()
+                .serviceId("serviceId")
+                .divideUpstreams(divideUpstreams)
+                .gray(false)
+                .build();
+        final SelectorData selectorData = SelectorData.builder()
+                .handle(GsonUtils.getInstance().toJson(springCloudSelectorHandle))
+                .id("1")
+                .build();
+        springCloudPluginDataHandler.handlerSelector(selectorData);
+        ServiceInstance serviceInstance = loadBalancerClient.choose("serviceId");
+        ServiceInstance serviceInstance2 = loadBalancerClient.choose("serviceId");
+        // if roundRobin, serviceInstance not equals serviceInstance2
+        Assertions.assertNotEquals(serviceInstance, serviceInstance2);
+    }
+}
diff --git a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-springcloud/src/main/java/org/apache/shenyu/springboot/starter/plugin/springcloud/SpringCloudPluginConfiguration.java b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-springcloud/src/main/java/org/apache/shenyu/springboot/starter/plugin/springcloud/SpringCloudPluginConfiguration.java
index b21c9d835..0a6571278 100644
--- a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-springcloud/src/main/java/org/apache/shenyu/springboot/starter/plugin/springcloud/SpringCloudPluginConfiguration.java
+++ b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-springcloud/src/main/java/org/apache/shenyu/springboot/starter/plugin/springcloud/SpringCloudPluginConfiguration.java
@@ -17,33 +17,21 @@
 
 package org.apache.shenyu.springboot.starter.plugin.springcloud;
 
-import com.netflix.client.config.CommonClientConfigKey;
-import com.netflix.client.config.IClientConfig;
-import com.netflix.loadbalancer.IRule;
-import com.netflix.loadbalancer.PollingServerListUpdater;
-import com.netflix.loadbalancer.ServerListUpdater;
-import org.apache.shenyu.common.config.ShenyuConfig;
-import org.apache.shenyu.common.constant.Constants;
 import org.apache.shenyu.plugin.api.ShenyuPlugin;
 import org.apache.shenyu.plugin.api.context.ShenyuContextDecorator;
 import org.apache.shenyu.plugin.base.handler.PluginDataHandler;
 import org.apache.shenyu.plugin.springcloud.SpringCloudPlugin;
 import org.apache.shenyu.plugin.springcloud.context.SpringCloudShenyuContextDecorator;
 import org.apache.shenyu.plugin.springcloud.handler.SpringCloudPluginDataHandler;
-import org.apache.shenyu.plugin.springcloud.loadbalance.LoadBalanceRule;
-import org.apache.shenyu.plugin.springcloud.loadbalance.client.CustomBlockingLoadBalancerClient;
+import org.apache.shenyu.plugin.springcloud.loadbalance.client.ShenyuSpringCloudLoadBalancerClient;
 import org.springframework.beans.factory.ObjectProvider;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.cloud.client.ServiceInstance;
+import org.springframework.cloud.client.discovery.DiscoveryClient;
 import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
-import org.springframework.cloud.loadbalancer.blocking.client.BlockingLoadBalancerClient;
-import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory;
-import org.springframework.cloud.netflix.ribbon.RibbonClientSpecification;
+import org.springframework.cloud.client.loadbalancer.reactive.ReactiveLoadBalancer;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Lazy;
-
-import java.util.Optional;
 
 /**
  * The type Spring cloud plugin configuration.
@@ -52,17 +40,17 @@ import java.util.Optional;
 @ConditionalOnProperty(value = {"shenyu.plugins.spring-cloud.enabled"}, havingValue = "true", matchIfMissing = true)
 public class SpringCloudPluginConfiguration {
 
-
     /**
-     * custom blocking loadbalancer.
+     * shenyu springcloud loadbalancer.
+     *
+     * @param discoveryClient discoveryClient
      * @param loadBalancerClientFactory loadBalancerFactory
-     * @return loadBalancerClient
+     * @return {@linkplain LoadBalancerClient}
      */
-    @ConditionalOnProperty(value = {"spring.cloud.loadbalancer.ribbon.enabled"}, havingValue = "false", matchIfMissing = true)
-    @ConditionalOnClass(value = BlockingLoadBalancerClient.class)
     @Bean
-    public LoadBalancerClient blockingLoadBalancerClient(final ObjectProvider<LoadBalancerClientFactory> loadBalancerClientFactory) {
-        return new CustomBlockingLoadBalancerClient(loadBalancerClientFactory.getIfAvailable());
+    public LoadBalancerClient shenyuSpringCloudLoadBalancerClient(final ObjectProvider<DiscoveryClient> discoveryClient,
+                                                         final ObjectProvider<ReactiveLoadBalancer.Factory<ServiceInstance>> loadBalancerClientFactory) {
+        return new ShenyuSpringCloudLoadBalancerClient(discoveryClient.getIfAvailable(), loadBalancerClientFactory.getIfAvailable());
     }
 
     /**
@@ -96,31 +84,4 @@ public class SpringCloudPluginConfiguration {
         return new SpringCloudPluginDataHandler();
     }
 
-    /**
-     * Custom ribbon IRule.
-     *
-     * @return ribbonClientSpecification
-     */
-    @Bean
-    public RibbonClientSpecification ribbonClientSpecification() {
-        Class<?>[] classes = new Class[]{SpringCloudClientConfiguration.class};
-        return new RibbonClientSpecification(String.join(".", Constants.DEFAULT.toLowerCase(), RibbonClientSpecification.class.getName()), classes);
-    }
-
-    static class SpringCloudClientConfiguration {
-        @Bean
-        public IRule ribbonRule() {
-            return new LoadBalanceRule();
-        }
-
-        @Lazy
-        @Bean
-        public ServerListUpdater ribbonServerListUpdater(final IClientConfig config,
-                                                         final ShenyuConfig shenyuConfig) {
-            Integer refreshInterval = Optional.ofNullable(shenyuConfig.getRibbon().getServerListRefreshInterval()).orElseGet(() -> 10000);
-            config.set(CommonClientConfigKey.ServerListRefreshInterval, refreshInterval);
-            return new PollingServerListUpdater(config);
-        }
-    }
-
 }
diff --git a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-springcloud/src/test/java/org/apache/shenyu/springboot/starter/plugin/springcloud/SpringCloudPluginConfigurationTest.java b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-springcloud/src/test/java/org/apache/shenyu/springboot/starter/plugin/springcloud/SpringCloudPluginConfigurationTest.java
index f9aebe02e..88fda9256 100644
--- a/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-springcloud/src/test/java/org/apache/shenyu/springboot/starter/plugin/springcloud/SpringCloudPluginConfigurationTest.java
+++ b/shenyu-spring-boot-starter/shenyu-spring-boot-starter-plugin/shenyu-spring-boot-starter-plugin-springcloud/src/test/java/org/apache/shenyu/springboot/starter/plugin/springcloud/SpringCloudPluginConfigurationTest.java
@@ -17,7 +17,6 @@
 
 package org.apache.shenyu.springboot.starter.plugin.springcloud;
 
-import com.netflix.loadbalancer.IRule;
 import org.apache.shenyu.common.enums.PluginEnum;
 import org.apache.shenyu.plugin.api.ShenyuPlugin;
 import org.apache.shenyu.plugin.api.context.ShenyuContextDecorator;
@@ -27,7 +26,6 @@ import org.junit.jupiter.api.Test;
 import org.springframework.boot.autoconfigure.AutoConfigurations;
 import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.boot.test.context.runner.ApplicationContextRunner;
-import org.springframework.cloud.netflix.ribbon.RibbonClientSpecification;
 import org.springframework.context.annotation.Configuration;
 
 import static org.assertj.core.api.Assertions.assertThat;
@@ -77,22 +75,4 @@ public class SpringCloudPluginConfigurationTest {
             }
         );
     }
-
-    @Test
-    public void testRibbonClientSpecification() {
-        applicationContextRunner.run(context -> {
-                RibbonClientSpecification specification = context.getBean("ribbonClientSpecification", RibbonClientSpecification.class);
-                assertNotNull(specification);
-            }
-        );
-    }
-
-    @Test
-    public void testLoadBalanceRulen() {
-        applicationContextRunner.run(context -> {
-                IRule rule = context.getBean("ribbonRule", IRule.class);
-                assertNotNull(rule);
-            }
-        );
-    }
 }