@Override
    public Status addLearners(final String groupId, final Configuration conf, final List<PeerId> learners) {
        checkLearnersOpParams(groupId, conf, learners);

        final PeerId leaderId = new PeerId();
        final Status st = getLeader(groupId, conf, leaderId);
        if (!st.isOk()) {
            return st;
        }

        if (!this.cliClientService.connect(leaderId.getEndpoint())) {
            return new Status(-1, "Fail to init channel to leader %s", leaderId);
        }
        final AddLearnersRequest.Builder rb = AddLearnersRequest.newBuilder() //
            .setGroupId(groupId) //
            .setLeaderId(leaderId.toString());
        for (final PeerId peer : learners) {
            rb.addLearners(peer.toString());
        }

        try {
            final Message result = this.cliClientService.addLearners(leaderId.getEndpoint(), rb.build(), null).get();
            return processLearnersOpResponse(groupId, result, "adding learners: %s", learners);

        } catch (final Exception e) {
            return new Status(-1, e.getMessage());
        }
    }
Cli service implementation.

@author boyan (boyan@alibaba-inc.com)
@author jiachun.fjc
jraft-core/src/main/java/com/alipay/sofa/jraft/core/CliServiceImpl.java