@Secured(resource = Commons.NACOS_CORE_CONTEXT_V2 + "/loader", action = ActionTypes.WRITE)
    @GetMapping("/smartReloadCluster")
    public ResponseEntity<String> smartReload(HttpServletRequest request,
            @RequestParam(value = "loaderFactor", required = false) String loaderFactorStr,
            @RequestParam(value = "force", required = false) String force) {
        
        LOGGER.info("Smart reload request receive,requestIp={}", getRemoteIp(request));
        
        Map<String, Object> serverLoadMetrics = getServerLoadMetrics();
        Object avgString = serverLoadMetrics.get("avg");
        List<ServerLoaderMetrics> details = (List<ServerLoaderMetrics>) serverLoadMetrics.get("detail");
        int avg = Integer.parseInt(avgString.toString());
        float loaderFactor =
                StringUtils.isBlank(loaderFactorStr) ? RemoteUtils.LOADER_FACTOR : Float.parseFloat(loaderFactorStr);
        int overLimitCount = (int) (avg * (1 + loaderFactor));
        int lowLimitCount = (int) (avg * (1 - loaderFactor));
        
        List<ServerLoaderMetrics> overLimitServer = new ArrayList<>();
        List<ServerLoaderMetrics> lowLimitServer = new ArrayList<>();
        
        for (ServerLoaderMetrics metrics : details) {
            int sdkCount = Integer.parseInt(metrics.getMetric().get(SDK_CONNECTION_COUNT_METRIC));
            if (sdkCount > overLimitCount) {
                overLimitServer.add(metrics);
            }
            if (sdkCount < lowLimitCount) {
                lowLimitServer.add(metrics);
            }
        }
        
        // desc by sdkConCount
        overLimitServer.sort((o1, o2) -> {
            Integer sdkCount1 = Integer.valueOf(o1.getMetric().get(SDK_CONNECTION_COUNT_METRIC));
            Integer sdkCount2 = Integer.valueOf(o2.getMetric().get(SDK_CONNECTION_COUNT_METRIC));
            return sdkCount1.compareTo(sdkCount2) * -1;
        });
        
        LOGGER.info("Over load limit server list ={}", overLimitServer);
        
        //asc by sdkConCount
        lowLimitServer.sort((o1, o2) -> {
            Integer sdkCount1 = Integer.valueOf(o1.getMetric().get(SDK_CONNECTION_COUNT_METRIC));
            Integer sdkCount2 = Integer.valueOf(o2.getMetric().get(SDK_CONNECTION_COUNT_METRIC));
            return sdkCount1.compareTo(sdkCount2);
        });
        
        LOGGER.info("Low load limit server list ={}", lowLimitServer);
        AtomicBoolean result = new AtomicBoolean(true);
        
        for (int i = 0; i < overLimitServer.size() & i < lowLimitServer.size(); i++) {
            ServerReloadRequest serverLoaderInfoRequest = new ServerReloadRequest();
            serverLoaderInfoRequest.setReloadCount(overLimitCount);
            serverLoaderInfoRequest.setReloadServer(lowLimitServer.get(i).address);
            Member member = serverMemberManager.find(overLimitServer.get(i).address);
            
            LOGGER.info("Reload task submit ,fromServer ={},toServer={}, ", overLimitServer.get(i).address,
                    lowLimitServer.get(i).address);
            
            if (serverMemberManager.getSelf().equals(member)) {
                try {
                    serverReloaderRequestHandler.handle(serverLoaderInfoRequest, new RequestMeta());
                } catch (NacosException e) {
                    LOGGER.error("Fail to loader self server", e);
                    result.set(false);
                }
            } else {
                
                try {
                    clusterRpcClientProxy.asyncRequest(member, serverLoaderInfoRequest, new RequestCallBack() {
                        @Override
                        public Executor getExecutor() {
                            return null;
                        }
                        
                        @Override
                        public long getTimeout() {
                            return 100L;
                        }
                        
                        @Override
                        public void onResponse(Response response) {
                            if (response == null || !response.isSuccess()) {
                                LOGGER.error("Fail to loader member={},response={}", member.getAddress(), response);
                                result.set(false);
                                
                            }
                        }
                        
                        @Override
                        public void onException(Throwable e) {
                            LOGGER.error("Fail to loader member={}", member.getAddress(), e);
                            result.set(false);
                        }
                    });
                } catch (NacosException e) {
                    LOGGER.error("Fail to loader member={}", member.getAddress(), e);
                    result.set(false);
                }
            }
        }
        
        return ResponseEntity.ok().body(result.get() ? SUCCESS_RESULT : FAIL_RESULT);
    }
@Test
    void testSmartReload() throws NacosException {
        EnvUtil.setEnvironment(new MockEnvironment());
        Member member = new Member();
        member.setIp("1.1.1.1");
        member.setPort(8848);
        ServerAbilities serverAbilities = new ServerAbilities();
        ServerRemoteAbility serverRemoteAbility = new ServerRemoteAbility();
        serverRemoteAbility.setSupportRemoteConnection(true);
        serverAbilities.setRemoteAbility(serverRemoteAbility);
        member.setAbilities(serverAbilities);
        Mockito.when(serverMemberManager.allMembersWithoutSelf()).thenReturn(Collections.singletonList(member));
        
        Map<String, String> metrics = new HashMap<>();
        metrics.put("conCount", "1");
        metrics.put("sdkConCount", "1");
        ServerLoaderInfoResponse serverLoaderInfoResponse = new ServerLoaderInfoResponse();
        serverLoaderInfoResponse.setLoaderMetrics(metrics);
        Mockito.when(serverLoaderInfoRequestHandler.handle(Mockito.any(), Mockito.any())).thenReturn(serverLoaderInfoResponse);
        
        Mockito.when(serverMemberManager.getSelf()).thenReturn(member);
        
        MockHttpServletRequest httpServletRequest = new MockHttpServletRequest();
        ResponseEntity<String> result = serverLoaderController.smartReload(httpServletRequest, "1", null);
        
        assertEquals("Ok", result.getBody());
        
    }