As a developer, you may start a small project with a monolith architecture using one of the many well-known frameworks. That’s a good start because it allows you to prototype fast and quickly respond to business needs. It sounds like a startup, doesn’t it?
You work on the project with your colleagues and it grows. The business is happy and has great plans for the project.
The problem with that is businesses don’t usually know anything about architecture. They shouldn’t necessarily need to — that’s your job!
Adding more and more functionalities doesn’t help the whole monolith architecture. You can try your best to keep the code neat and tidy but by adding new features to the project, it eventually becomes too much for the supposed-to-be small project.
Going forward, the decision has to be made to split the monolith into microservices. And that’s fine, everyone is trending towards microservices these days.
What is gRPC?
gRPC is an open-source, modern, high performance framework that was designed by Google to connect its data centers over a decade ago.
It’s okay if you don’t have data centers — you can use them to communicate with any services. Not only microservices, but also mobile, web, IoT, or even libraries.
By design, it is fast, compact, and scalable. It is language-agnostic, which means you can easily connect services written in different languages. All you need are defined procedures and messages for services. The rest, like implementations of clients, servers, and serialized data you get for free. They are generated by the gRPC scripts for your languages of choice. You just need to utilize them and implement what they are doing.
So, are we making contracts between clients and servers like in GraphQL, and no other communications are allowed? Pretty much! We are defining beforehand exactly what your services are offering and the exact messages for the communications. You don’t have to construct many REST endpoints, we just call a direct method on the client side. Sounds great, right?
Let me show you some other cool stuff.
Things You May Like about gRPC
Let me introduce you to some of the benefits of gRPC. In the next part, I will explore why gRPC stands out as a powerful framework for modern applications, emphasizing its efficiency, versatility, and performance. Whether you're new to gRPC or looking to deepen your understanding, I will provide valuable insights into its key advantages and practical applications.
Service Definitions
syntax = "proto3
service UserStore {
rpc GetUserDataByEmail(UserEmailRequest) returns (UserResponse);
}
message User {
string email = 1;
string firstname = 2;
string lastname = 3;
}
message UserEmailRequest {
string email = 1;
}
message UserResponse {
User user = 1;
string error = 2;
}
Let me explain step by step what we are doing here.
As you can see from the first line, this is a proto3 file. This format is used for defining methods and serializing messages. More on that subject later.
Next, we have the service definition UserStore. Let’s assume this is the service that holds all the information of our users. For now, we have only one unary (request -> response) RPC method which is called GetUserDataByEmail. It expects a request message UserEmailRequest and will return the message UserResponse.
Ok, so far so good. You can also see that we can build more complex messages with it. Like the UserResponse is defining one of the fields as a User message. That’s correct, this is a feature of a protobuf which is quite powerful and is a whole other topic.
So we have definitions. What next?
Now we need to somehow access this RPC method in our application. To do that, we use a protocol buffer compiler to generate code for clients and servers. It might look like this:
python -m grpc_tools.protoc -I../../protos — python_out=. — grpc_python_out=. ../../protos/user_store.proto
As I said before, gRPC is language agnostic and offers tools for almost every popular language. This one is for Python. You will need to generate this for each language that you use.
This compiler will generate two files for python:
user_store_pb2.py
— which contains generated classes for request and response messagesuser_store_pb2_grpc.py
— which contains generated client and server classes.
All you need to do now is import and use them — like this:
Client:
import grpc
from protos.user_store_pb2 import User, UserResponse, UserEmailRequest,
from protos.user_store_pb2_grpc import UserStoreStub
def run():
with grpc.insecure_channel('localhost:50051') as channel:
stub = _pb2_grpc.UserStoreStub(channel)
response = stub.GetUserDataByEmail(
UserEmailRequest(email="user@example.com")
)
print(f"response user: {response.user}")
if __name__ == '__main__':
logging.basicConfig()
run()
Server:
import grpc
from protos.user_store_pb2 import User, UserResponse, UserEmailRequest,
from protos.user_store_pb2_grpc import UserStoreServicer
class UserStoreServicer(UserStoreServicer):
def GetUserDataByEmail(self, request: UserEmailRequest, context):
user = … # your code for fetching the user data
return UserResponse(
user=User(
email=user.email,
firstname=user.firstname,
lastname=user.lastname
)
)
Protobufs
So far, this looks fairly easy — but why do we use protobufs? (here’s the next great thing) you don’t have to!
gRPC was designed to be not only language agnostic, but also encoding! gRPC is not a monolithic framework. You can swap out some things if you want. You can use JSON or XML for messaging if you prefer. Meanwhile, let me inform you of the benefits of using protobufs.
They are compact. Especially in comparison to JSON or XML, they’re really compact. Let’s compare how many bytes will be needed for the same information for those three data types.
If you are sending IDs only, this makes a huge difference.
But size is not the only thing. Protobufs have many features that are beneficial. To name a few:
- Protobuf fields may be marked as deprecated. This will greatly improve the way of working with multiple teams or services.
int32 old_field = 6 [deprecated = true];
- You can define enums and use them as possible values for fields. Or even map all messages to the JSON if you need.
- Built-in serialization
- Typing
And many more.
One important thing to remember! In Protobuf3 (the latest one), every field in the message is optional. This means you don’t always have to populate all defined fields. They will receive default values set to them like empty strings, e.g., 0, False, or so.
This is important considering the older version, Protobuf2, was the exact opposite. You needed to mark each field as ‘optional’ if needed.
You can find more on protobufs here.
Synchronous or Asynchronous
Life Cycles
Are there other possible communication types other than unary request -> response?
In short, yes. We have everything you might need.
Unary
Server Streaming
Client Streaming
Bidirectional Streaming
Timeouts and Canceling
Like any other communication system, you can define a timeout for responses. This is also independent of clients and servers. You can define it according to your needs. You can even cancel and RPC at any time. Keep in mind that this will not roll back anything and this feature needs to be implemented by you in the application itself.
But how is that possible, I hear you ask? What kind of sorcery is that?
Well, it’s not sorcery for sure!
Underneath, gRPC is using the newer HTTP2 transfer protocol instead of using the previous HTTP1.1. Thanks to HTTP2, we can send binaries instead of text (HTTP1.1) to support the handling of multiple requests at the same time. This standard is still new; you can find more in Introduction to HTTP/2.
Things You May Not Like about gRPC
It’s still fairly young
Tools are still emerging
Binaries
Browser support
Learning stuff
Conclusion
Mirumee guides clients through their digital transformation by providing a wide range of services from design and architecture, through business process automation to machine learning. We tailor services to the needs of organizations as diverse as governments and disruptive innovators on the ‘Forbes 30 Under 30’ list.
Learn more about who we are and what we do. Have a look through the open positions here and become a part of our team.