Learn how to build an RPC (remote procedure call) server in Go and how to make calls to procedures on the server via a client written in Node.
RPC (remote procedure call), in simple terms, is a protocol that is used for client-server applications which allows software developers to request a procedure or a function call to a remote server. In this tutorial, you will be learning how to build an RPC server in Go along with an RPC client in Node.js.
You’ll need:
In this article, we will be building a chat RPC server to send a message and return descriptive details of a user. The send message procedure will accept the message body while the other will accept the user’s name and age.
In this step, you will be building your RPC server. Start by creating a new project directory by running:
mkdir rpc-server
Change directory to the newly created folder:
cd rpc-server
A protocol buffer is a data format created by Google to enable developers to generate source code based on the data and service specified for any programming language.
Create a proto
file named chat.proto
:
touch chat.proto
Open chat.proto
with your desired editor and paste the following code:
syntax = "proto3";
package chat;
message Message {
string body = 1;
}
message Details {
string name = 1;
int32 age = 2;
}
message Response {
string body = 1;
}
service ChatService {
rpc SayHello(Message) returns (Response) {}
rpc GetDetails(Details) returns (Response) {}
}
Let us go through what each block does:
syntax = "proto3";
This specifies what version of protobuf we intend to write.
message Message {
string body = 1;
}
This declares a Message
data object that can only contain a string element with the tag body
.
message Details {
string name = 1;
int32 age = 2;
}
This declares a Details
data object that can only contain a string element with the tagged name
and an integer element with the tagged age
.
message Response {
string body = 1;
}
This declares a Response
data object that can only contain a string element with the tag body
.
service ChatService {
rpc SayHello(Message) returns (Message) {}
rpc GetDetails(Details) returns (Details) {}
}
This declares a new service called ChatService
which will contain two methods, SayHello
method which accepts the Message
data object and returns Response
and the GetDetails
method which accepts Details
and returns Response
back as well. Save and exit the file.
Note: You can learn more about protobuf here.
We will generate a protocol buffer Go code based on the proto
file we wrote in the previous step. While still being in the rpc-server
directory, run the following command:
mkdir chat
This will generate a new folder named chat
within the rpc-server
directory. This is where you place our generated Go code along with the implementation of your chat.proto
file. Run the following to generate your go code off your chat.proto
file:
protoc --go_out=plugins=grpc:chat chat.proto
Note: You can learn more about Go generated code here.
This will generate a new file named chat.pb.go
in the chat
directory created earlier.
Note: Do not modify the contents of _chat.pb.go_
.
In this step, we will be implementing the methods in ChatService
as defined in chat.proto
.
Create a new file named chat.go
:
touch chat.go
Open chat.go
with your desired editor and paste the following code:
package chat
import (
"fmt"
"golang.org/x/net/context"
"log"
)
type Server struct{}
func (s *Server) SayHello(ctx context.Context, message *Message) (*Response, error) {
log.Println("SayHello Called")
return &Response{Body: fmt.Sprintf("New Message: %s", message.Body)}, nil
}
func (s *Server) GetDetails(ctx context.Context, message *Details) (*Response, error) {
log.Println("GetDetails Called")
return &Response{Body: fmt.Sprintf("Your name is %s and you're %d years old", message.Name, message.Age)}, nil
}
Let me break down the essentials:
type Server struct{}
This acts as a server interface to this ChatService
implementation, we will be using this later on to plug into the RPC server.
The first function implements the SayHello
function, when called it will log
SayHello Called
to the console while returning the Response
object along with the message body passed to it back to the client.
The second function implements the GetDetails
function, when called it will log
GetDetails Called
to console while returning the Response
object along with a custom message containing the data passed back to the client.
Both methods return error
and a pointer reference of Response
which exists as a struct in the chat.pb.go
file generated based on what we defined in chat.proto
.
Note: Implemented methods must return a pointer reference of what was defined in the _proto_
declaration and error.
#go #node #web-development #developer