Dragos Roban
Dragos Roban

Reputation: 599

How to make a grpc client to call multiple servers?

So far I've built a simple client-server architecture and manage it to work. I am able to send a request and get back a valid response.

My problem it's how do I make the client to have multiple grpc servers to be able to distribute the work. Suppose I have a master (client) which sends requests to mutiple servers which are on different machines (therefore different IP's. Is there something that might help me on the client side? Have a list of hosts and ports and create a load balancer / mannagedchannel factory? The thing is here that I want to have multiple machines connected to one master machine in a distributed system. Each request in grpc it's a file which the server (worker) computes it and return a response.

Thank you. So far here is the code for the client/server with grpc which works very fine.

Client side

@Component
public class DocumentParserClient {

    private static final Logger LOGGER = LoggerFactory.getLogger(DocumentParserClient.class);
    private static final String GRPC_HOST = "localhost";
    private static final int GRPC_PORT_I1 = 6565;
    private static final int GRPC_PORT_I2 = 6566;

    private ManagedChannel managedChannel;
    private WikiDocParserGrpc.WikiDocParserBlockingStub wikiDocParserBlockingStub;

    @PostConstruct
    private void init() {
        this.managedChannel = ManagedChannelBuilder.forAddress(GRPC_HOST, GRPC_PORT_I1).usePlaintext(true).build();
        this.wikiDocParserBlockingStub = WikiDocParserGrpc.newBlockingStub(managedChannel);
    }

    public String parseDocument(WikiOWrapperDto wikiOWrapperDto) {
        long start = System.currentTimeMillis();
        LOGGER.info("client sending {}",start);
        WikiOWrapper wikiOWrapper = GrpcDtoTransform.wrapINPUTFromDtoToGRPC(wikiOWrapperDto);
        LOGGER.info("client parsing {}", System.currentTimeMillis() - start);
        TokenCompressorDoc tokenCompressorDoc = wikiDocParserBlockingStub.parseWikiDOC(wikiOWrapper);
        LOGGER.info("client received {}", System.currentTimeMillis() - start);
        return "Success";
    }

}

Server side

@GRpcService
public class WikiDocParserGrpcService extends WikiDocParserGrpc.WikiDocParserImplBase {

    private static final Logger LOGGER = LoggerFactory.getLogger(WikiDocParserGrpcService.class);
    private JSoupParser jSoupParser;

    @Autowired
    public WikiDocParserGrpcService(JSoupParser jSoupParser) {
        this.jSoupParser = jSoupParser;
    }

    @Override
    public void parseWikiDOC(WikiOWrapper wikiOWrapper, StreamObserver<TokenCompressorDoc> responseObserver) {
        long start = System.currentTimeMillis();
        LOGGER.info("server received {}", start);
        WikiOWrapperDto wikiOWrapperDto = GrpcDtoTransform.wrapOUTPUTfromGrpcToDto(wikiOWrapper);
        TokenCompressorDocDto tokenCompressorDocDto = jSoupParser.parseJsonParseWrapperFromObject(wikiOWrapperDto);
        responseObserver.onNext(GrpcDtoTransform.wrapOUTPUTFromGRPCToDto(tokenCompressorDocDto));
        responseObserver.onCompleted();
        LOGGER.info("server responded in {}", System.currentTimeMillis()- start);
    }
}

Upvotes: 0

Views: 9674

Answers (2)

Dragos Roban
Dragos Roban

Reputation: 599

For every one who follows this topic, including @DazWilkin who specified to use a proxy. I used NGINX and it's quite the best approach and works just fine.

Follow https://medium.com/@alextan/grpc-load-balancing-with-nginx-673d5d4df708 to a simple guide and then you can extend to TSL etc.

Thanks.

Upvotes: 0

DazWilkin
DazWilkin

Reputation: 40051

Have a look at the approaches summarized here with pros-and-cons for each:

https://grpc.io/blog/loadbalancing/

Your most important decision is whether to (a) thicken your client to include code that manages a roster of multiple servers and determine how to route traffic to them; (b) use an external proxy or load-balancer to abstract this decision-making.

If you choose option (b), I encourage you to focus on L7 (HTTP/2) load-balancing rather than TCP. gRPC requires HTTP/2 and uses sessions for streaming. For this reason, routing is more complicated than with L7 and REST. Increasingly, industry-proven proxies including Envoy, NGINX and HAProxy support HTTP/2 and gRPC.

Upvotes: 2

Related Questions