Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow turning BindableService into a ServerTransportListener-like structure #11546

Open
bsideup opened this issue Sep 20, 2024 · 4 comments
Open

Comments

@bsideup
Copy link

bsideup commented Sep 20, 2024

Is your feature request related to a problem?

Currently, there is no easy way to trigger a gRPC service from an existing HTTP/2 handler.

Describe the solution you'd like

Expose a way to call a service by calling it with a raw HTTP/2 request. Something like:

ServerBuilder.forFactory(ClientTransportServersBuilder)

Describe alternatives you've considered

A custom server can be implemented, but it requires many steps and operates on low level abstractions (e.g. Netty channels, or Sockets), whereas most modern frameworks have their own HTTP/2 abstractions that can be turned into a ServerStream.

Additional context

https://github.com/bsideup/grpc-bidi uses an existing ClientCall and exposes itself (client) as a server. The current implementation requires going through the full pipeline, but all is does is parses the bytes from ClientCall without any network stack, and it could use a lean implementation where it simply parses the HTTP/2 request and turns it into a ServerStream.

@bsideup
Copy link
Author

bsideup commented Sep 20, 2024

Okay, now I feel kinda silly because it can be achieved with new ServerImplBuilder(streamTracerFactories -> new ChannelServer(streamTracerFactories, networkChannel)).

It does require the use of an internal class but for my use case it is maybe fine? Will leave it open for the discussion tho.

@ejona86
Copy link
Member

ejona86 commented Sep 20, 2024

No, it's not fine to use ServerImpl. That's clearly internal and will break on our whim.

I really don't understand what you're trying to do. But based on "exposes itself (client) as a server" sounds like a good use of InProcess transport. In-process has pretty low overhead, and with directExecutor() (which only makes sense for certain use cases) it is ~2-3 µs (based on some old benchmarks I see) for a noop RPC.

A way to call gRPC with an existing request is with the grpc-servlet API. But then you'd need to represent the "existing HTTP/2 request" in terms of the servlet API.

I see you are doing some sort of tunneling. If you haven't seen it, see if #3987 is useful at all to you.

@bsideup
Copy link
Author

bsideup commented Sep 20, 2024

Hi @ejona86! Funny that you mentioned your PR because I've previously submitted #11023 as a continuation of it, and grpc-bidi is basically the end result, extracted so it can be consumed already now (it's been in prod for 6+ months), but I hope to land it in https://github.com/grpc-ecosystem and eventually grpc-java if it gets accepted to the spec :)

Cool idea to look at grpc-servlet, thank you! I will investigate. I think I looked into in-process in the past but there were some issues with it, I could be wrong tho. Let me double check! Thanks for the pointers 👍

@ejona86
Copy link
Member

ejona86 commented Sep 20, 2024

But then you'd need to represent the "existing HTTP/2 request" in terms of the servlet API.

Beware that is doing some heavy lifting. In particular, we use the async APIs. It's more, "that's the only general-purpose HTTP API we support."

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants