private void reBuildRemoteClients(List<RemoteInstance> remoteInstances) {
        final Map<Address, RemoteClientAction> remoteClientCollection =
            this.usingClients.stream()
                             .collect(Collectors.toMap(
                                 RemoteClient::getAddress,
                                 client -> new RemoteClientAction(
                                     client, Action.Close)
                             ));

        final Map<Address, RemoteClientAction> latestRemoteClients =
            remoteInstances.stream()
                           .collect(Collectors.toMap(
                               RemoteInstance::getAddress,
                               remote -> new RemoteClientAction(
                                   null, Action.Create)
                           ));

        final Set<Address> unChangeAddresses = Sets.intersection(
            remoteClientCollection.keySet(), latestRemoteClients.keySet());

        unChangeAddresses.stream()
                         .filter(remoteClientCollection::containsKey)
                         .forEach(unChangeAddress -> remoteClientCollection.get(unChangeAddress)
                                                                           .setAction(Action.Unchanged));

        // make the latestRemoteClients including the new clients only
        unChangeAddresses.forEach(latestRemoteClients::remove);
        remoteClientCollection.putAll(latestRemoteClients);

        final List<RemoteClient> newRemoteClients = new LinkedList<>();
        remoteClientCollection.forEach((address, clientAction) -> {
            switch (clientAction.getAction()) {
                case Unchanged:
                    newRemoteClients.add(clientAction.getRemoteClient());
                    break;
                case Create:
                    if (address.isSelf()) {
                        RemoteClient client = new SelfRemoteClient(moduleDefineHolder, address);
                        newRemoteClients.add(client);
                    } else {
                        RemoteClient client;
                        client = new GRPCRemoteClient(moduleDefineHolder, address, 1, 3000, remoteTimeout, sslContext);
                        client.connect();
                        newRemoteClients.add(client);
                    }
                    break;
            }
        });

        //for stable ordering for rolling selector
        Collections.sort(newRemoteClients);
        this.usingClients = ImmutableList.copyOf(newRemoteClients);

        remoteClientCollection.values()
                              .stream()
                              .filter(remoteClientAction ->
                                          remoteClientAction.getAction().equals(Action.Close)
                                              && !remoteClientAction.getRemoteClient().getAddress().isSelf()
                              )
                              .forEach(remoteClientAction -> remoteClientAction.getRemoteClient().close());
    }
Compare clients between exist clients and remote instance collection. Move the clients into new client collection
which are alive to avoid create a new channel. Shutdown the clients which could not find in cluster config.
<p>
Create a gRPC client for remote instance except for self-instance.

@param remoteInstances Remote instance collection by query cluster config.
oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/remote/client/RemoteClientManager.java