In the cloud environment, there are numerous ways in which a service-oriented architecture can be implemented using microservices. The focus is often on resource efficiency and thus cost efficiency, as well as scalability with different load windows. Today we’re looking at how to run cost-effectively microservices in the cloud.
Basically there are two established ways of running microservices, either as a serverless cloud function or as a container in a Kubernetes cluster. Serverless functions such as the popular AWS Lambda can be used with low tariffs and are easy to set up. Serverless functions become significantly more expensive above a certain load limit. The variant with containers on Kubernetes, on the other hand, is more complex, but can be scaled more cost-effectively in the long term. The Kubernetes solution is therefore dependent on rolling out containers that are built with a lowest possible footprint and available response power.
In the past, we have already looked at Quarkus as the framework of choice, with which one can quickly write a microservice in Java without any problems. But is there more? For this reason, we are focusing today on microservcies that are written in Go and provide endpoints with a different protocol that achieve even higher throughput.
This post is inspired by https://itnext.io/grpc-go-microservices-on-kubernetes-bcb6267e9f53.
gRPC - The universal remote procedure call framework
With the term Remote Procedure Call, one might vaguely recall Java’s Remote Method Invocation (shortly RMI) or EJBs (Enterprise JavaBeans), with which a Java application could call a specific method of a second Java application remotely via a network connection.
gRPC is a protocol developed by Google for calling functions in distributed systems. gRPC stands for Google Remote Procedure Call. gRPC is rated by the Cloud Native Computing Foundation as an ‘Incubating Project’. The following two main components are used:
- Protocol Buffers (shortly Protobuf) as _ Interface
Description Language _: uses gRPC as serialization for communication. A binary format is used
here, which allows the interface to respond more quickly to requests. The interface is defined semantically (and not binary) in a
.proto
\ file. This definition generates the binary format, which then functions as Interface Description Language (like e.g. JSON). - HTTP/2 as transport: The new HTTP standard has existed since 2015. This second iteration allows bidirectional communication, server pushes, header compression, multiplexing and more. gRPC uses these new features to make data transfer even faster.
For microservices, a REST interface is typically used to create communication between applications. With gRPC Google has implemented a solution with which one can communicate with each other even faster.
Features and Benefits
- Simple service definition
- Efficient because binary, scalable
- Language-independent, polyglot
- Bidirectional data exchange / streaming
- authentication
- Perfect for internal communication under services
gRPC can be used in different programming languages. Thus, a gPRC interface can be implemented relatively easily on REST endpoints, which ensures better performance with lower power requirements. It should be noted that HTTP / 2 is not yet widely used, as outdated browsers are still used on a daily basis. With gRPC Web , a JavaScript implementation for browser clients, you can also address gRPC with older browsers. If you are still using applications that can only address REST interfaces, you can use gRPC Gateway to create parallel operation via the definition file, whereby the service exposes REST and gRPC. We won’t go into more detail about this technology here, but it is certainly good to know how flexible an interface with gRPC can be.
It is important to know that you write the interface declarative in a .proto
\ - file and then use this to compile _
stub _ \ - files (Code-fragments) in the desired language. Regardless of the programming language, these blocks can be
implemented in the respective project and communicate with each other language-independent in the running application.
Supported languages for gRPC
C, C++, C#, Dart, Go, Java, Kotlin, Node.js, Objective-C, PHP, Python, Ruby.
Service definition with Google’s Protobuf
The gRPC interface uses Protobuf as IDL. This interface is written declarative in a .proto
\ - file and then
compiled with this _stub _ \ - Files (Code-fragments) in the desired language. Regardless of the programming language,
these blocks can be implemented in the respective project and communicate with each other language-independent in the
running application.
An example of a .proto file for a geographic-aware chat API could look like this:
|
|
Install and use Protobuf
How can we now build a microservice with gRPC in Go? It’s pretty easy. First we install Protobuf as follows:
|
|
For this you have to load the Go-Plugin protoc-gen-go
from:
|
|
Also ensures that the bash paths for Go are set correctly:
|
|
And also :
|
|
The following snippet is an exemplary grpcapi.proto
. We use Protobuf’s Interface Description Language to describe
our interface.
|
|
With this command the Protobuf compiler protoc
compiles the schema into a usable Go-File:
|
|
The output of protoc
is a go-file protocol.pb.go
which is placed in the same directory. The created Go-File has over
200 characters, but to ensure that we have the same output, the first line blocks can be seen here:
|
|
Microservice architecture with Go
The server
Now we write a server.go \ microservice that can receive a GrpcService
\ invocation from a client. Take a closer
look at the function func (*grpcServer) GrpcService()
.
|
|
Before the server.go can be compiled, the external dependencies must first be drawn. Simply execute the following go commands in the console:
|
|
Then you can compile and start the server.
|
|
The client
Now we write a client.go \ microservice, which carries out a GrpcService
\ invocation on a server. Take a closer
look at the function func callService()
.
|
|
Now we can also compile and run the client:
|
|
: white_check_mark: Great, it worked!
Here we see the response from the server. In doing so, we printed the entire binary output.
Grpc server on Kubernetes
Now we can deploy the whole construct in our Kubernetes cluster.
Requirements
- Docker knowledge and access to a Docker repository
- Knowledge of Kubernetes and access to a Kubernetes cluster
- If you don’t have that, feel free to see what we’re doing here
The Dockerfile for the grpc_server
:
|
|
Kubernetes Manifesto:
|
|
As soon as you are connected to the Kubernetes cluster, you can apply the manifest as follows:
|
|
Now you can find out the external IP address in order to align the client accordingly:
|
|
Now it is your turn! How much better is a gRPC interface compared to a CRUD interface?
Stay tuned!
This text was automatically translated with our golang markdown translator.