This article discusses how to make server streaming calls using gRPC in Go, including implementing a client and server application.
Abstract
The article explains the concept of server streaming in gRPC, where the client sends a single request and the server responds with a stream of messages. The author demonstrates this through a project that creates a Documents service with a gRPC endpoint for fetching documents. The endpoint does not require any request message, and the server sends streaming responses to the client. The article covers the definition of the documents.proto file, the generation of Go code for the proto file, and the implementation of the server and client Go applications. The author also provides instructions for running the server and client applications.
Opinions
The author finds server streaming useful when the server needs to perform bulk operations and can send objects one by one using streaming.
The client can stop accepting messages from the server at any point in time, either because it already got what it wanted or because the server is taking too long to send messages.
The author suggests pushing the content of the proto folder to Github and then importing it from there or putting the content inside the packages/src folder for the go version path to solve the issue of local imports.
The author uses dummy data and the sleep function to simulate some latency in the server.
The client waits until the server finishes streaming messages.
The author finds it useful to implement a server streaming rpc response and expresses gratitude to the reader for taking the time to read the series.
The author recommends trying out an AI service that provides the same performance and functions as ChatGPT Plus(GPT-4) but is more cost-effective.
gRPC: How to Make Server Streaming Calls
In this article, I’ll cover a gRPC call using Server Streaming response— implementing a client and server Go applications.
In a server streaming rpc call, the client sends a single request, and the server responds with a stream of messages. This is useful when the server needs to do bulks operations, and instead of waiting until the server finishes processing the data, the server can send objects one by one using streaming.
Server Streaming Response
Project Description
For this project, we will create a Documents service with one gRPC endpoint that will allow the client to send a request to fetch documents.
The endpoint will not require any request message, so we will send an empty hash.
The server then will process some documents and start sending streaming responses to the client.
The client can also stop accepting messages from the server at any point in time, either because it already got what it wanted, or because the server is taking too long to send messages.
Let’s create another folder inside the grpc_calls, and call it server_stream.
Inside this folder create the following structure.
gRPC Server Stream Folder Structure
The definition of the documents.proto file is the following:
In this proto file I defined the service documents, the endpoint, and the corresponding messages for this request.
For this endpoint, the client will not need to send any data in the request message, so we are declaring it as an empty request.
For the response, the server will send a message of type Document.
Proto file definitions:
GetDocuments: This is the rpc endpoint definition, it accepts and empty message in the request, and returns a stream of GetDocumentsRes.
EmptyReq: This is the request message.
GetDocumentsRes: This is the response message, and it has one field called document, of type Document.
Document: This message represents a document object, with name, document type, and size fields.
Let’s now generate the go code for this proto file.
Inside the proto folder run the following command:
Now we can move on and implement the server. This is the code for the server go application.
Again, for this file, we first create a new grpc server that will listen on port 3000, then we register the documents service and start listening for connections.
Now, as you can see, I am importing proto_server_stream package. Because Go will complain if you have local imports.
To solve this issue you can do the following:
Push the content of the proto folder to Github and then import it from there.
Put the content of the proto folder inside the packages/src folder for your go version path. In my case this is the path:
golang/1.15.5/packages/src
Inside this folder, I created a proto_server_stream folder and pasted the files from the proto folder that contains the generated code, and the documents.proto file.
That way I can import the package without pushing it to Github. Take the approach you consider more convenient.
For the GetDocuments function, we first initialize some dummy data, then we iterate through the documents, perform some validations, and use the stream object to start sending streaming responses to the client.
We also use the sleep function to simulate some latency in the server.
Let’s implement the client code.
For the client code, we create a new client-server on port 3000, using the NewDocumentsClient method provided by the documents package.
For the fetchDocuments function, we first initialize the request message, in this case, is an empty one. Then it gets the stream object and starts receiving streaming messages from the server.
As I said before, the client can also decide when to stop receiving messages from the server, in this case, the client waits until the server finishes streaming messages.
That is the necessary code for the client and server go applications, if you read the last article about client streaming requests, you can see that the difference in the definition of the proto file is really small. As well as the implementation for the client and server.
We can now try it out. Go to the console, inside the server folder, start the server with the following command.
go run .
Server Go Application Logs
Then start the client as well with the same command, but under the client folder.
Client Go Application Logs
Awesome, we’ve implemented a server streaming rpc response.
I hope you find it useful. In the next article of the series, we’ll tackle Bi-Directional streaming.