gRPC info

eiximenis 2019-11-15 10:25:24 +01:00
parent d5e80d2c92
commit 1b1ddd9835
3 changed files with 141 additions and 1 deletions

@ -20,6 +20,8 @@ Most communications between microservices are decoupled using the EventBus and t
For those explicit communications gRPC is used (instead of HTTP/JSON). gRPC is a RPC-based protocol that have great performance and low bandwidth usage, making it the best candidate for internal microservices communication. For those explicit communications gRPC is used (instead of HTTP/JSON). gRPC is a RPC-based protocol that have great performance and low bandwidth usage, making it the best candidate for internal microservices communication.
More information about gRPC and eShopOnContainers can be found [here](./gRPC.md)
## API Gateways ## API Gateways
The architecture also includes an implementation of the API Gateway pattern and Backend-For-Front-End (BFF), to publish simplified APIs and include additional security measures for hiding/securing the internal microservices from the client apps or outside consumers. The architecture also includes an implementation of the API Gateway pattern and Backend-For-Front-End (BFF), to publish simplified APIs and include additional security measures for hiding/securing the internal microservices from the client apps or outside consumers.

138
gRPC.md

@ -2,6 +2,16 @@
One of the big news on netcore 3.0 is the native support for gRPC. eShopOnContainers makes use of gRPC for internal microservice-to-microservice synchronous communication. Note that, in eShop most of the communication between microservices is decoupled and asynchronous using an Event Bus (we support RabbitMQ or Azure Service Bus). One of the big news on netcore 3.0 is the native support for gRPC. eShopOnContainers makes use of gRPC for internal microservice-to-microservice synchronous communication. Note that, in eShop most of the communication between microservices is decoupled and asynchronous using an Event Bus (we support RabbitMQ or Azure Service Bus).
gRPC is a high-perfomance communication protocol, based on HTTP/2 and protocol buffers. It should be the primary choice for direct communication between services (as oposed to other protocols like AMQP used for decoupled communication like queues or pub/sub).
Its benefits over using directly HTTP with JSON are:
* Protocol buffers are a binary, high-perfomance serialization mechanism. Depending on the language implementation protocol buffers can be up to 8x faster than JSON serialization while the messages can be around 60%-80% smaller.
* Supports streaming of data
* Contract between service and client is explicit (by using _proto_ files)
## gRPC usage in eShopOnContainers
In current implementation use of gRPC is limited to the communication between aggregators and micro services. We have following synchronous communications between services in eShop: In current implementation use of gRPC is limited to the communication between aggregators and micro services. We have following synchronous communications between services in eShop:
1. External clients (i. e. Xamarin App or Browser) to Api Gateways (BFFs): Use HTTP/REST 1. External clients (i. e. Xamarin App or Browser) to Api Gateways (BFFs): Use HTTP/REST
@ -23,3 +33,131 @@ And following BFFs are gRPC clients:
* Mobile Shopping * Mobile Shopping
* Web Shopping * Web Shopping
## gRPC implementation in eShopOnContainers
gRPC is language agnostic: all services are defined using _proto_ files (usually with the `.proto` extension). These files are based on the [protobuffer language](https://developers.google.com/protocol-buffers/docs/proto), and define the interface of the service. Based on the _proto_ file, a code for creating the server and the client can be generated for every language. The canonical tool is _protoc_ which supports generate C# code.
Starting from netcore3, gRPC is deeply integrated in both, the tooling and the framework, to make the experience of using gRPC as seamless as possible.
### Generating server or client stubs from proto file in Net Core 3
The tooling, integrated in msbuild (so it can be used by Visual Studio but also by the `dotnet build` SDK command), allows the generation of the code needed to create a gRPC server or client based on a _proto_ file. The _proto_ file has to be referenced in the `csproj` using a `<ProtoBuf>` tag (inside a `<ItemGroup>`):
```xml
<ItemGroup>
<Protobuf Include="Protos\catalog.proto" GrpcServices="Client" />
</ItemGroup>
```
The `GrpcServices` attributes is for specifying if a `Server` stub has to be generated, or a `Client` one.
>**Note** You can include as many `<Protobuf>` tags as you need.
When you compile the code (either by running _Build_ from Visual Studio or `dotnet build`) all code will be generated and placed in the `obj` folder. This is intentionally: this code should never be in the source control repository.
![obj output with auto-generated files](./images/grpc/grpc-1.png)
### Creating the gRPC server
The server stub generated code, defines an abstract base class with a set of abstract methods, that you have to implement. You will have one abstract method for every rpc method defined in the _proto_ file.
So, given a _proto_ file that define the following methods:
```
service Catalog {
rpc GetItemById (CatalogItemRequest) returns (CatalogItemResponse) {}
rpc GetItemsByIds (CatalogItemsRequest) returns (PaginatedItemsResponse) {}
```
A `CatalogBase` abstract class will be generated:
```cs
public class CatalogService : CatalogBase
{
public CatalogService()
{
}
public override async Task<CatalogItemResponse> GetItemById(CatalogItemRequest request, ServerCallContext context)
{
// Code
}
public override async Task<PaginatedItemsResponse> GetItemsByIds(CatalogItemsRequest request, ServerCallContext context)
{
// Code
}
}
```
All needed C# types for parameters and return values will be generated automatically.
### Adding the gRPC pipeline into ASP.NET Core
ASP.NET Core supports direct integration of the gRPC pipeline. Only need to use the method `MapGrpcService` of the `IEndpointRouteBuilder` in your `Startup` class:
```cs
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
endpoints.MapControllers();
endpoints.MapGrpcService<CatalogService>();
});
```
### Creating the gRPC client
If you are creating a gRPC client instead of a server, you need to create a `GrpChannel` and then a gRPC client using this channel:
```cs
var channel = GrpcChannel.ForAddress(UrlOfService);
var client = new Basket.BasketClient(channel);
```
The class `Basket.BasketClient` is the stub generated from the _proto_ file. Then you can call the methods of the `BasketClient` class.
### Using gRPC without TLS
gRPC works with HTTP/2 only. Usually when a client connects to a server, the connection is done using HTTP1.1 and promoted to HTTP/2 only if both, server and client, support HTTP/2. This promotion is performed using a protocol negotiation, usually implemented using ALPN protocol which requires TLS.
**That means, that by default, you need to have a TLS endpoint enabled to be able to use gRPC.**
However in internal microservices, maybe you don't have a TLS enabled endpoints (because those endpoints are internal). In this case you have two options:
* Open a single Kestrel endpoint, listening on HTTP/2
* Open two Kestrel endpoints, one listening on HTTP1.1 the other listening on HTTP/2
The second option is the one needed if your server must support HTTP1.1 clients other than gRPC clients. Following C# code (in `Program.cs`) shows the second approach:
```cs
WebHost.CreateDefaultBuilder(args)
.ConfigureKestrel(options =>
{
options.Listen(IPAddress.Any, ports.httpPort, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
});
options.Listen(IPAddress.Any, ports.grpcPort, listenOptions =>
{
listenOptions.Protocols = HttpProtocols.Http2;
});
})
```
But, this is not enough. We need to tell the gRPC client, that can connect directly to a HTTP/2 endpoint, without the need to have TLS. By default netcore don't allow a gRPC client connect to a non-TLS endpoint.
Following lines are needed on the client:
```cs
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2Support", true);
```
Those settings could be set only once at the beginning of the client.
## More information
* [gRPC](https://grpc.io/)
* [Introduction to gRPC services](https://docs.microsoft.com/en-us/aspnet/core/grpc/?view=aspnetcore-3.0)

BIN
images/grpc/grpc-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB