1598401593
In modern microservice architecture, we can categorize microservices into two main groups based on their interaction and communication. The first group of microservices acts as external-facing microservices, which are directly exposed to consumers. They are mainly HTTP-based APIs that use conventional text-based messaging payloads (JSON, XML, etc.) that are optimized for external developers, and use Representational State Transfer (REST) as the de facto communication technology.
REST’s ubiquity and rich ecosystem play a vital role in the success of these external-facing microservices. OpenAPIprovides well-defined specifications for describing, producing, consuming, and visualizing these REST APIs. API management systems work well with these APIs and provide security, rate limiting, caching, and monetizing along with business requirements. GraphQL can be an alternative for the HTTP-based REST APIs but it is out of scope for this article.
The other group of microservices are internal and don’t communicate with external systems or external developers. These microservices interact with each other to complete a given set of tasks. Internal microservices use either synchronous or asynchronous communication. In many cases, we can see the use of REST APIs over HTTP as a synchronous mode but that would not be the best technology to use. In this article, we will take a closer look at how we can leverage a binary protocol such as gRPC which can be an optimized communication protocol for inter-service communication
**NGINX Plus is the complete application delivery platform for the modern web. **Start your 30 day free trial.
gRPC is a relatively new Remote Procedure Call (RPC) API paradigm for inter-service communications. Like all other RPCs, it allows directly invoking methods on a server application on a different machine as if it were a local object. Same as other binary protocols like Thrift and Avro, gRPC uses an interface description language (IDL) to define a service contract. gRPC uses HTTP/2, the latest network transport protocol, as the default transport protocol and this makes gRPC fast and robust compared to REST over HTTP/1.1.
You can define the gRPC service contract by using Protocol Buffers where each service definition specifies the number of methods with the expected input and output messages with the data structure of the parameters and return types. Using major programming language provided tools, a server-side skeleton and client-side code (stub) can be generated using the same Protocol Buffers file which defines the service contract.
Figure 1: A segment of an online retail shop microservices architecture
One of the main benefits of microservice architecture is to build different services by using the most appropriate programming language rather than building everything in one language. Figure 1 illustrates a segment of an online retail shop microservice architecture, where four microservices are implemented in Ballerina (referred to as Ballerina in the rest of the article) and Golang working together to provide some functionality of the retail online shop. Since gRPC is supported by many major programming languages, when we define the service contracts, implementation can be carried out with a well-suited programming language.
Let’s define service contracts for each service.
syntax="proto3";
package retail_shop;
service OrderService {
rpc UpdateOrder(Item) returns (Order);
}
message Item {
string itemNumber = 1;
int32 quantity = 2;
}
message Order {
string itemNumber = 1;
int32 totalQuantity = 2;
float subTotal = 3;
Listing 1: Service contract for Order microservice (order.proto)
The Order microservice will get shopping items and the quantity and return the subtotal. Here I use the Ballerina gRPC tool to generate a gRPC service boilerplate code and the stub/client respectively.
$ ballerina grpc --mode service --input proto/order.proto --output gen_code
This generates the OrderService server boilerplate code.
import ballerina/grpc;
listener grpc:Listener ep = new (9090);
service OrderService on ep {
resource function UpdateOrder(grpc:Caller caller, Item value) {
// Implementation goes here.
// You should return an Order
}
}
public type Order record {|
string itemNumber = "";
int totalQuantity = 0;
float subTotal = 0.0;
|};
public type Item record {|
string itemNumber = "";
int quantity = 0;
|};
#go language #microservices #grpc #ballerina #development #architecture & design #article
1598401593
In modern microservice architecture, we can categorize microservices into two main groups based on their interaction and communication. The first group of microservices acts as external-facing microservices, which are directly exposed to consumers. They are mainly HTTP-based APIs that use conventional text-based messaging payloads (JSON, XML, etc.) that are optimized for external developers, and use Representational State Transfer (REST) as the de facto communication technology.
REST’s ubiquity and rich ecosystem play a vital role in the success of these external-facing microservices. OpenAPIprovides well-defined specifications for describing, producing, consuming, and visualizing these REST APIs. API management systems work well with these APIs and provide security, rate limiting, caching, and monetizing along with business requirements. GraphQL can be an alternative for the HTTP-based REST APIs but it is out of scope for this article.
The other group of microservices are internal and don’t communicate with external systems or external developers. These microservices interact with each other to complete a given set of tasks. Internal microservices use either synchronous or asynchronous communication. In many cases, we can see the use of REST APIs over HTTP as a synchronous mode but that would not be the best technology to use. In this article, we will take a closer look at how we can leverage a binary protocol such as gRPC which can be an optimized communication protocol for inter-service communication
**NGINX Plus is the complete application delivery platform for the modern web. **Start your 30 day free trial.
gRPC is a relatively new Remote Procedure Call (RPC) API paradigm for inter-service communications. Like all other RPCs, it allows directly invoking methods on a server application on a different machine as if it were a local object. Same as other binary protocols like Thrift and Avro, gRPC uses an interface description language (IDL) to define a service contract. gRPC uses HTTP/2, the latest network transport protocol, as the default transport protocol and this makes gRPC fast and robust compared to REST over HTTP/1.1.
You can define the gRPC service contract by using Protocol Buffers where each service definition specifies the number of methods with the expected input and output messages with the data structure of the parameters and return types. Using major programming language provided tools, a server-side skeleton and client-side code (stub) can be generated using the same Protocol Buffers file which defines the service contract.
Figure 1: A segment of an online retail shop microservices architecture
One of the main benefits of microservice architecture is to build different services by using the most appropriate programming language rather than building everything in one language. Figure 1 illustrates a segment of an online retail shop microservice architecture, where four microservices are implemented in Ballerina (referred to as Ballerina in the rest of the article) and Golang working together to provide some functionality of the retail online shop. Since gRPC is supported by many major programming languages, when we define the service contracts, implementation can be carried out with a well-suited programming language.
Let’s define service contracts for each service.
syntax="proto3";
package retail_shop;
service OrderService {
rpc UpdateOrder(Item) returns (Order);
}
message Item {
string itemNumber = 1;
int32 quantity = 2;
}
message Order {
string itemNumber = 1;
int32 totalQuantity = 2;
float subTotal = 3;
Listing 1: Service contract for Order microservice (order.proto)
The Order microservice will get shopping items and the quantity and return the subtotal. Here I use the Ballerina gRPC tool to generate a gRPC service boilerplate code and the stub/client respectively.
$ ballerina grpc --mode service --input proto/order.proto --output gen_code
This generates the OrderService server boilerplate code.
import ballerina/grpc;
listener grpc:Listener ep = new (9090);
service OrderService on ep {
resource function UpdateOrder(grpc:Caller caller, Item value) {
// Implementation goes here.
// You should return an Order
}
}
public type Order record {|
string itemNumber = "";
int totalQuantity = 0;
float subTotal = 0.0;
|};
public type Item record {|
string itemNumber = "";
int quantity = 0;
|};
#go language #microservices #grpc #ballerina #development #architecture & design #article
1599854400
Go announced Go 1.15 version on 11 Aug 2020. Highlighted updates and features include Substantial improvements to the Go linker, Improved allocation for small objects at high core counts, X.509 CommonName deprecation, GOPROXY supports skipping proxies that return errors, New embedded tzdata package, Several Core Library improvements and more.
As Go promise for maintaining backward compatibility. After upgrading to the latest Go 1.15 version, almost all existing Golang applications or programs continue to compile and run as older Golang version.
#go #golang #go 1.15 #go features #go improvement #go package #go new features
1648332000
gRPC-Go
The Go implementation of gRPC: A high performance, open source, general RPC framework that puts mobile and HTTP/2 first. For more information see the Go gRPC docs, or jump directly into the quick start.
With Go module support (Go 1.11+), simply add the following import
import "google.golang.org/grpc"
to your code, and then go [build|run|test]
will automatically fetch the necessary dependencies.
Otherwise, to install the grpc-go
package, run the following command:
$ go get -u google.golang.org/grpc
Note: If you are trying to access
grpc-go
from China, see the FAQ below.
The golang.org
domain may be blocked from some countries. go get
usually produces an error like the following when this happens:
$ go get -u google.golang.org/grpc
package google.golang.org/grpc: unrecognized import path "google.golang.org/grpc" (https fetch: Get https://google.golang.org/grpc?go-get=1: dial tcp 216.239.37.1:443: i/o timeout)
To build Go code, there are several options:
Set up a VPN and access google.golang.org through that.
Without Go module support: git clone
the repo manually:
git clone https://github.com/grpc/grpc-go.git $GOPATH/src/google.golang.org/grpc
You will need to do the same for all of grpc's dependencies in golang.org
, e.g. golang.org/x/net
.
With Go module support: it is possible to use the replace
feature of go mod
to create aliases for golang.org packages. In your project's directory:
go mod edit -replace=google.golang.org/grpc=github.com/grpc/grpc-go@latest
go mod tidy
go mod vendor
go build -mod=vendor
Again, this will need to be done for all transitive dependencies hosted on golang.org as well. For details, refer to golang/go issue #28652.
Ensure your gRPC-Go version is require
d at the appropriate version in the same module containing the generated .pb.go
files. For example, SupportPackageIsVersion6
needs v1.27.0
, so in your go.mod
file:
module <your module name>
require (
google.golang.org/grpc v1.27.0
)
Update the proto
package, gRPC package, and rebuild the .proto
files:
go get -u github.com/golang/protobuf/{proto,protoc-gen-go}
go get -u google.golang.org/grpc
protoc --go_out=plugins=grpc:. *.proto
The default logger is controlled by environment variables. Turn everything on like this:
$ export GRPC_GO_LOG_VERBOSITY_LEVEL=99
$ export GRPC_GO_LOG_SEVERITY_LEVEL=info
"code = Unavailable desc = transport is closing"
This error means the connection the RPC is using was closed, and there are many possible reasons, including:
It can be tricky to debug this because the error happens on the client side but the root cause of the connection being closed is on the server side. Turn on logging on both client and server, and see if there are any transport errors.
Author: Grpc
Source Code: https://github.com/grpc/grpc-go
License: Apache-2.0 License
1597438200
We have been building software applications for many years using various tools, technologies, architectural patterns and best practices. It is evident that many software applications become large complex monolith over a period for various reasons. A monolith software application is like a large ball of spaghetti with criss-cross dependencies among its constituent modules. It becomes more complex to develop, deploy and maintain monoliths, constraining the agility and competitive advantages of development teams. Also, let us not undermine the challenge of clearing any sort of technical debt monoliths accumulate, as changing part of monolith code may have cascading impact of destabilizing a working software in production.
Over the years, architectural patterns such as Service Oriented Architecture (SOA) and Microservices have emerged as alternatives to Monoliths.
SOA was arguably the first architectural pattern aimed at solving the typical monolith issues by breaking down a large complex software application to sub-systems or “services”. All these services communicate over a common enterprise service bus (ESB). However, these sub-systems or services are actually mid-sized monoliths, as they share the same database. Also, more and more service-aware logic gets added to ESB and it becomes the single point of failure.
Microservice as an architectural pattern has gathered steam due to large scale adoption by companies like Amazon, Netflix, SoundCloud, Spotify etc. It breaks downs a large software application to a number of loosely coupled microservices. Each microservice is responsible for doing specific discrete tasks, can have its own database and can communicate with other microservices through Application Programming Interfaces (APIs) to solve a large complex business problem. Each microservice can be developed, deployed and maintained independently as long as it operates without breaching a well-defined set of APIs called contract to communicate with other microservices.
#microservice architecture #microservice #scaling #thought leadership #microservices build #microservice
1599055326
The shift towards microservices and modular applications makes testing more important and more challenging at the same time. You have to make sure that the microservices running in containers perform well and as intended, but you can no longer rely on conventional testing strategies to get the job done.
This is where new testing approaches are needed. Testing your microservices applications require the right approach, a suitable set of tools, and immense attention to details. This article will guide you through the process of testing your microservices and talk about the challenges you will have to overcome along the way. Let’s get started, shall we?
Traditionally, testing a monolith application meant configuring a test environment and setting up all of the application components in a way that matched the production environment. It took time to set up the testing environment, and there were a lot of complexities around the process.
Testing also requires the application to run in full. It is not possible to test monolith apps on a per-component basis, mainly because there is usually a base code that ties everything together, and the app is designed to run as a complete app to work properly.
Microservices running in containers offer one particular advantage: universal compatibility. You don’t have to match the testing environment with the deployment architecture exactly, and you can get away with testing individual components rather than the full app in some situations.
Of course, you will have to embrace the new cloud-native approach across the pipeline. Rather than creating critical dependencies between microservices, you need to treat each one as a semi-independent module.
The only monolith or centralized portion of the application is the database, but this too is an easy challenge to overcome. As long as you have a persistent database running on your test environment, you can perform tests at any time.
Keep in mind that there are additional things to focus on when testing microservices.
Test containers are the method of choice for many developers. Unlike monolith apps, which lets you use stubs and mocks for testing, microservices need to be tested in test containers. Many CI/CD pipelines actually integrate production microservices as part of the testing process.
As mentioned before, there are many ways to test microservices effectively, but the one approach that developers now use reliably is contract testing. Loosely coupled microservices can be tested in an effective and efficient way using contract testing, mainly because this testing approach focuses on contracts; in other words, it focuses on how components or microservices communicate with each other.
Syntax and semantics construct how components communicate with each other. By defining syntax and semantics in a standardized way and testing microservices based on their ability to generate the right message formats and meet behavioral expectations, you can rest assured knowing that the microservices will behave as intended when deployed.
#testing #software testing #test automation #microservice architecture #microservice #test #software test automation #microservice best practices #microservice deployment #microservice components