gRPC info
parent
d5e80d2c92
commit
1b1ddd9835
@ -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
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.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 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
BIN
images/grpc/grpc-1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 52 KiB |
Loading…
x
Reference in New Issue
Block a user