armeria
armeria copied to clipboard
How about letting `ClientBuilder` expose `io.grpc.Channel`?
Hi there, we build gRPC clients with Armeria 1.16.3. I wonder whether either of the following ideas could be good:
- Let
com.linecorp.armeria.client.ClientBuilder
class expose an API to build and return aio.grpc.Channel
(implemented byArmeriaChannel
). - Let
ClientBuilder
build aio.grpc.Channel
once (at the first time whenClientBuilder#build(...)
is called) and then re-use the channel for all future invocations ofClientBuilder#build(...)
.
Here is why I think these^ ideas would benefit our use case:
- Currently we provide an abstraction called
GrpcChannel
to our users.GrpcChannel
is not aware of any stub type. Users can create stubs fromGrpcChannel
. For example,channel.createStub[StubType](...)
. - Note that the above
GrpcChannel
is a custom abstraction defined by my team and it is NOTio.grpc.Channel
. - Each
GrpcChannel
instance contains its ownClientBuilder
(decorators) andClientFactory
(connection pool). The goal is to have a clear separation of resources amongGrpcChannel
instances. Users can create and manageGrpcChannel
s by themselves. grpc-java provides a similar mental mode (example) to allow users to create stub(s) from aio.grpc.Channel
(a grpc-java interface/API). - In our current implementation, every
channel.createStub[StubType](...)
invocation requires callingClientBuilder.build(stubClass)
which creates aio.grpc.Channel
. That means when N stubs are created from ourGrpcChannel
, there are N grpc-javaio.grpc.Channel
s created (one for each stub). - This^ creates a lot of overhead to our stub creation process. Ideally we hope to let every
GrpcChannel
instance have oneio.grpc.Channel
instance from which all stubs are built. - We have done a POC for this^ idea and the performance improvement is significant. However, the POC is a bit hacky due to the fact that
ClientBuilder
does not provide an API to buildio.grpc.Channel
. Specifically, in the POC, after the first stub was created, we callstub.getChannel
to get a reference to its underlyingio.grpc.Channel
built byClientBuilder
, then cache and reuse theio.grpc.Channel
to build future stubs. IfClientBuilder
provides an API to build and return aio.grpc.Channel
(proposed idea 1), we can get rid of the hack. Or we can consider makingClientBuilder
internally build aio.grpc.Channel
once and keep reusing it for all invocations ofClientBuilder.build(stubClass)
. With this change, our code (inGrpcChannel.createStub
) can simply callClientBuilder.build(stubClass)
to build every stub sinceClientBuilder.build(stubClass)
would be much more lightweight (because theio.grpc.Channel
is reused).
Please let me know WYT. Thanks!