Why Remote Procedure Calls (RPC) Are Better than REST

Published: July 25, 2020
Anthony
By Anthony
4 min read
Why Remote Procedure Calls (RPC) Are Better than REST

Most modern services and clients communicate with REST with JSON as a data interchange format. JSON is easy to read and most programming languages can easily parse JSON. The ease of use comes with its cons though. You can't enforce a well defined structure and protocol between the client and server. You can send extra data that the recipient doesn't care about. JSON is also pretty big in terms of size compared to protos. Let's take a look at protos and how it can solve some of those issues.

What Does a Protobuf look like?

There are different versions of proto in GRPC, but I'll be referencing proto3 which is the newest version.

syntax = "proto3";

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

A typical proto looks like this. Each field has a type (string), a field name (query), and a unique field number (1). The field number is used to figure out how to encode the field and its location.

Protos Establish a Schema

As you saw in the example earlier, the proto defined a schema of a SearchRequest. Having a schema is important because it guarantees type-safety and prevents schema-violations. The best part of protos is that you can have a server implementation in one language and a client in a different language and the proto can be consumed without any difficulty.

In GRPC, you can also define services which are like REST endpoints. Let's expand on the example from above.

syntax = "proto3";

service SearchService {
  rpc Search (SearchRequest) returns (SearchResponse);
}

message SearchRequest {
  string query = 1;
  int32 page_number = 2;
  int32 result_per_page = 3;
}

message SearchResponse {
  string response = 1;
}

Let's say we have a Go server that implements SearchService. The implementation will look something like.

type searchServer struct {}

func (s *searchServer) Search(ctx context.Context, req *pb.SearchRequest) (*pb.SearchResponse, error) {
  // TODO: Implement the Server
}

A Javascript Client can the server like so

const service = new SearchServiceClient('http://localhost:8080');

const req = new SearchRequest();
req.setQuery("AnimalCrossing");
req.setPageNumber(3);
req.setResultsPerPage(100);

service.search(req, {}, (err, resp) => {});

An equivalent client in REST would look like so:

const data = {
    query: "AnimalCrossing",
  pageNumber: 3,
  resultsPerPage: 100,
};

fetch("/search", data);

The problem with the 2nd approach is that you cannot guarentee any type safety or check for required fields without extra business logic. You can also set a field incorrectly like using page_number instead of pageNumber. I also think the RPC version is much more readable. You can tell exactly what the data is by reading the object name.

REST based APIs do not have schema out of the box. If you want to give your REST API a schema, you'll need to use something like JSON Schema.

Network Requests Transmit Less Bytes

Let's see how SearchRequest might look like in JSON vs proto. Let's say the client sets query to "animal crossing", page_number to 3, and result_per_page to 100. Once this proto is populated and serialized, it will look something like this ["animal crossing",3,100]. In JSON, you'll represent the same object like so:

{
    "query": "animal crossing",
    "page_number": 3,
    "result_per_page": 100
}

You can already tell the serialized proto version requires less characters to represent than the equivalent in JSON. This is really good for companies that need to shave as much data off each request/response to make network requests as small as possible. The only issue is the serialized proto is not easy for a human being to read.

Protos Can Be Used In a Plethora of Programming Languages

Just like REST, RPCs and protos can be consumed by any programming language. Here's some tutorials from Google on how to set up protos. There are also open source projects to set up protos for other programming languages like protobuf.js.

Conclusion

In conclusion, I'm a big fan of how RPCs define a clear and well defined schema and transmits less bytes over the wire. I also think using protos help increase the readability of the code since everything is typed and objects are initialized with the proto object. Have you used RPCs before? Do you prefer that over REST? Let me know in the comments section below.

Related Posts

Copyright 2020 © Mai Nguyen. All rights reserved.