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

Headers and timeouts for streaming RPCs #1715

Closed
maja42 opened this issue Oct 2, 2020 · 4 comments
Closed

Headers and timeouts for streaming RPCs #1715

maja42 opened this issue Oct 2, 2020 · 4 comments
Labels

Comments

@maja42
Copy link

maja42 commented Oct 2, 2020

📚 Documentation

I'm using grpc-gateway behind an nginX-proxy and want to provide streaming support from server-to-client via the API.
The protocol works pretty flawless after some hickups, but there's one issue I'm not sure how to correctly solve:

Streaming only works if proxies are not buffering the responses. As soon as the gateway calls Flush() on the http.ResponseWriter, the http-client/browser should be able to read the line.

By default, nginX performs buffering (which is a good thing), and this can be controlled via http headers: http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering

What's the best way to set the X-Accel-Buffering response-header to off for streaming-RPCs only? Inside an http-interceptor, I don't know if the called method returns a stream or not. Inside the grpc-client interceptor I don't have access to the http.ResponseWriter (I could get access to it by storing it in context.Context, which is an ugly workaround).

(I could propably use a combination of an grpc-client interceptor, grpc header-metadata and OutgoingHeaderMatcher to get it working, but this it's also ugly)

I have a similar problem with API-Timeouts:
For unary gRPC-calls I want a timeout of 10 seconds (configurable via runtime.DefaultContextTimeout). But for streaming gRPCs a timeout doesn't really make sense, and I don't want the client/browser to always send a timeout-header.

Questions + Documentation:

  • How can I add headers/trailers for streaming rpcs only?
  • How can I configure different timeouts for unary rpcs and streaming rpcs?

Documentation:

  • Timeout-Handling and runtime.DefaultContextTimeout is not documented
  • Update the documentation with the fact that http-proxies can interfere with streaming-rpcs
@maja42
Copy link
Author

maja42 commented Oct 2, 2020

For timeouts, I can probably keep the runtime.DefaultContextTimeout disabled and add my own context.WithTimeout inside the grpc-client interceptors.
I can use a different timeout in grpc.WithChainUnaryInterceptor than in grpc.WithStreamInterceptor. If this is the intended solution, it should be documented. However, the timeout would only track grpc-calls, and would not cover execution times inside the gateway (which is okay I guess?).

@johanbrandhorst
Copy link
Collaborator

Timeouts specifically can be controlled with the Grpc-Timeout header: https://github.com/grpc-ecosystem/grpc-gateway#supported.

Where do you want to add the headers/trailers? The gRPC gateway will translate any headers you prefix with Grpc-Metadata- to gRPC metadata that you can then use in your server implementation. I don't know how to configure nginx. Maybe this is the sort of thing we could use the slack support channel for? It's on Gophers Slack, #grpc-gateway.

@maja42
Copy link
Author

maja42 commented Oct 5, 2020

After a short slack discussion:
grpc-gateway uses the same default-timeout for both unary- and streaming RPCs. Callers can define their own timeout in an http-header.
A custom timeout must be attached to each http-call that calls a long-running streaming RPC if the default-timeout is too short.

My current solution/workaround for configuring different default-timeouts for unary and streaming RPCs:
It's possible to disable the grpc-timeout behaviour by setting runtime.DefaultContextTimeout = 0. Then, later in the stack, it's possible to register unary- and stream-interceptors on the grpc-client, which can use different default-timeouts on context.WithTimeout.
To get custom timeouts working with that solution, the grpc-timeout header can be read inside an http-interceptor, attached to the context and later read by the grpc-client-interceptors. And don't forget to delete the grpc-timeout inside the http-interceptor, otherwise it will trigger the grpc timeout-handling and you have both the custom- and default timeout on top of each other.

@stale
Copy link

stale bot commented Dec 4, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

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

No branches or pull requests

2 participants