Skip to content

concurrent use of client #285

@scottlamb

Description

@scottlamb

Feature Request

Crates

both tonic & tonic-build

Motivation

I want to issue a bunch of concurrent API calls over the same channel. It looks like tonic doesn't support this today given that all the client methods take&mut self. The official gRPC implementations (C++, Java, Go) all support this. It's common to have heavy concurrency over the same channel. This seems much more practical than having tons of channels and managing a pool of them from the caller for at least a few reasons:

  • ergonomics - it'd be extra work for the caller to do that pooling, especially once you get into building client-side load balancing on top of a bunch of channels to individual servers
  • efficiency - there's RAM overhead to channels (socket buffers) and even CPU overhead (health checking). With client-side load balancing these can be significant even without throwing in multiple connections to the same server.
  • limits - you could exhaust the number of local ephemeral ports and be unable to open any more channels to the same server because you've hit the fundamental TCP limit on having only one connection per (source ip, source port, destination ip, destination port). iirc, the OS also won't automatically pick an ephemeral port for you that anything else is using (even to talk to a different ip:port than you're connecting to), so that's an even more restrictive limit unless you start manually binding to ports when connecting outbound.

Proposal

API and semantics: I'd like all the generated API calls to simply take &self rather than &mut self and fire off the RPCs in parallel, subject to the server's MAX_CONCURRENT_STREAMS limit. If there are more calls than that limit, later ones block until earlier ones finish before sending. See also the max_streams test mentioned here.

Internals: I haven't looked into tonic internals at all so no opinions there.

Alternatives

I think the only reasonable alternative would be to have a cloneable client where each clone shares the underlying channel.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions