Grpc-java: one grpc server for both unary and bidi stream with netty

Created on 27 Jan 2021  路  3Comments  路  Source: grpc/grpc-java

I have a requirement to implement a grpc server in java which is capable of handling both grpc unary and bidirectional streaming.It is possible for the service that uses grpc bidi-streaming to send a large number of messages per second.(maybe 2000 messages per second or more)I have two implementations in mind and kind of confused which one suits my requirement most.

1. Use the same server for both grpc unary and grpc bidirectional.

When using this approach , since both grpc unary and bidi stream uses the same port, one boss thread will be allocated for both unary and bidi stream. So i'm not sure how well it performs in case of bidi streams receiving large number of messages per second. (I mean whether the boss thread will get busy for bidi streams and become unavailable for the unary)

final EventLoopGroup bossGroup = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors());
    final EventLoopGroup workerGroup = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors() * 2);
    int blockingQueueLength = 1000;
    final BlockingQueue blockingQueue = new LinkedBlockingQueue(blockingQueueLength);
    final Executor executor = new ThreadPoolExecutor(400, 500, 30, TimeUnit.SECONDS, blockingQueue);
    Server server = NettyServerBuilder.forPort(PORT).maxConcurrentCallsPerConnection(50)
            .keepAliveTime(60, TimeUnit.SECONDS).bossEventLoopGroup(bossGroup)
            .workerEventLoopGroup(workerGroup).addService(new ExtAuthService()).addService(new RateLimitService())
            .channelType(NioServerSocketChannel.class)
            .executor(executor).build();

    try{
        server.start();
        server.awaitTermination();
    }catch(Exception e){
        Logger.Error("Execption", new Error(e));
    }

2. Use two servers one for grpc unary and one for grpc bidi streaming.

Here the previously mentioned issue is not there since we allocate 2 boss threads one for each grpc unary and bidi stream. But for the services I'm using an executor which uses java ThreadPoolExecutor and my question is should I use 2 threadpools for the two services that use grpc unary and bidi streaming ?

final EventLoopGroup bossGroup = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors());
    final EventLoopGroup workerGroup = new NioEventLoopGroup(Runtime.getRuntime().availableProcessors() * 2);
    int blockingQueueLength = 1000;
    final BlockingQueue blockingQueue = new LinkedBlockingQueue(blockingQueueLength);
    final Executor executor = new ThreadPoolExecutor(400, 500, 30, TimeUnit.SECONDS, blockingQueue);

    // I have used here the same executor for both servers. 
    Server server1 = NettyServerBuilder.forPort(PORT_1).maxConcurrentCallsPerConnection(50)
            .keepAliveTime(60, TimeUnit.SECONDS).bossEventLoopGroup(bossGroup)
            .workerEventLoopGroup(workerGroup).addService(new ExtAuthService())
            .channelType(NioServerSocketChannel.class)
            .executor(executor).build();

    Server server2 = NettyServerBuilder.forPort(PORT_2).maxConcurrentCallsPerConnection(50)
            .keepAliveTime(60, TimeUnit.SECONDS).bossEventLoopGroup(bossGroup)
            .workerEventLoopGroup(workerGroup).addService(new RateLimitService())
            .channelType(NioServerSocketChannel.class)
            .executor(executor).build();

    try{
        server1.start();
        server2.start();
        server1.awaitTermination();
        server2.awaitTermination();
    }catch(Exception e){
        Logger.Error("Execption", new Error(e));
    }
question

Most helpful comment

I think performance-wise there won't be too much difference (2000 messages per second or more is not big). Two servers will use more resources (memory and number of connections) than one. For one-server implementation, a client can just use one connection to send two types of requests; whereas for two-server implementation, a client has to consume at least two connections.

All 3 comments

I think performance-wise there won't be too much difference (2000 messages per second or more is not big). Two servers will use more resources (memory and number of connections) than one. For one-server implementation, a client can just use one connection to send two types of requests; whereas for two-server implementation, a client has to consume at least two connections.

@dapengzhang0 thanks a lot. I went through some docs and yeah, its better to have a single server. Maybe will implement both and do a benchmark.

This was also asked and answered on StackOverflow.

Seems like this is resolved. If not, comment, and it can be reopened.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

nddipiazza picture nddipiazza  路  3Comments

nathanhleung picture nathanhleung  路  6Comments

darewreck54 picture darewreck54  路  5Comments

JBayangosB picture JBayangosB  路  3Comments

zhangkun83 picture zhangkun83  路  6Comments