-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
How to consume server-streams with JavaScript inside a Browser #1783
Comments
Hi again Maja and thank you for your detailed issue. We don't have any documentation around this already but as it happens I have had some personal experience implementing this. My recommendations are as follows:
If you end up getting this working, I'd love to add a new section about this to the docs. Let us know! |
Thanks for your quick response. Regarding 3: A downside of this approach (in contrast to websockets) is that each request requires an active connection to our backend, consuming a server port. So with multiple clients having multiple open streams, we might run into a port shortage at some time. But I guess with HTTP/2 that might not be an issue. |
I forgot to mention, you can also bridge the grpc-gateway with websockets using https://github.com/tmc/grpc-websocket-proxy. I've used it in the past and it works well. It might be preferred to a Fetch API stream. |
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. |
Okay, I finally found the time to get back to this problem. This is a problem. The max. number of simultaneous connections a browser allows is quite limited: https://stackoverflow.com/a/985704/2224996 In a POC, we only managed to open 5 streams at once (when using Chrome). Using the Fetch API doesn't help with this issue, since fetch() also count towards this limit: https://developers.cloudflare.com/workers/platform/limits Did you also face this issue and, if so, how did you solve it? |
I don't think there's anything the grpc-gateway can really do to help you here. We're not going to implement some sort of multiplexing of connections (nevermind how we'd actually do that). If you want some sort of notifications, you may need to do that in a separate RPC that is the only thing you use to stream data from the backend. Or use the websocket proxy, apparently Chrome supports 200 concurrent websocket connections. |
@maja42 This sounds like a use case were just using the Web Sockets API directly might just be better suited to your needs. |
Hi, because if those reasons we switched to grpc-web which solves all these issues. So this issue is not a problem for us anymore, but it would have been great if these limitations were documented somewhere more prominent, because it could have saved us a lot of time, and we would have figured out earlier that this technology is not suitable for our use-case. |
@paulsmithkc As a side note: We are exclusively using grpc on the backend and explicitly didn't want to use web-sockets. It would require us to write additional code for every single RPC that we expose to the UI. And splitting an API up into two different technologies (Rest + web-sockets) based on an arbitrary property (stream vs. no-stream) also doesn't look very desirable. In addition to two new technologies, we would need to test both our grpc API, and the rest/web-sockets API, vastly increasing the test-overhead. The API-documentation would also need to exist twice (once for grpc for internal backend-services, and once for rest/web-sockets. |
📚 Documentation / Question
Our UI-team struggles implementing grpc server-streams provided via the gateway.
Our use case:
We want to use backend-streams as an alternative to polling:
The REST/stream call is started as soon as the website is opened and stays active until the tab/browser is closed.
The backend sends changes regarding certain topics on this stream as soon as they appear.
As an example, consider this protobuf definition:
Each message is encoded as json and sent to the browser in a separate line of the response body.
Within JavaScript, it's then possible to read partial responses from the backend.
However, there is one issue:
Everytime JavaScript reads the (partial) response body after a new backend-message, it receives the whole response, not only the new line/message.
It seems that there is no way of telling the browser "Hey, I already read that. Please delete it and don't bother me anymore".
While this might look like a minor inconvenience at first (after all, JavaScript could remember the bytes-already-read and ignore them), it makes our use-case pretty tricky.
If the stream is active for a long time and/or a lot of messages are sent by the backend and/or if the individual response messages contain big json-objects, a lot of unneccesary data will accumulate and fill up the user's RAM.
I couldn't find any examples or documentation that shows how those streams should be consumed from the browser/JavaScript side. Is there a solution to this problem?
I'd like to avoid aborting and repeating the REST-call every few minutes after some arbitrary amount of data was received.
If this is not possible - is there a way to provide these grpc-streams via web sockets? Or, even better, via SSE (server-side-events)? What would be the correct solution for our use-case?
The text was updated successfully, but these errors were encountered: