头图

gRPC is a modern, cross-platform, high-performance RPC framework. gRPC is built on ASP.NET Core and is our recommended way to build RPC services using .NET.

.NET 6 further improves gRPC's already excellent performance and adds a bunch of new features that make gRPC better than ever in modern cloud-native applications. In this post, I'll describe these new capabilities and how we're leading the industry with the first gRPC implementation that supports end-to-end HTTP/3.

gPRC Client Load Balancing

Client-side load balancing is a feature that allows gRPC clients to optimally distribute load among available servers. Client-side load balancing can eliminate the need for load balancing proxies. This has several benefits:

  • Improved performance. Proxyless means eliminating extra network hops and reducing latency because RPCs are sent directly to the gRPC server.
  • Efficient use of server resources. A load balancing proxy must parse and resend every HTTP request sent through it. Deleting an agent saves CPU and memory resources.
  • Simpler application architecture. The proxy server must be set up and configured correctly. No proxy server means fewer moving parts!

Client-side load balancing is configured when the channel is created. Two components to consider when using load balancing:

  • The parser, which resolves the address of the channel. The resolver supports getting addresses from external sources. This is also called service discovery.
  • A load balancer that creates connections and chooses the addresses that gRPC calls will use.

The following code example configures the channel to use DNS service discovery with round-robin load balancing:

var channel = GrpcChannel.ForAddress(

"dns:///my-example-host",
newGrpcChannelOptions
{
    Credentials = ChannelCredentials.Insecure,
    ServiceConfig = newServiceConfig { LoadBalancingConfigs = { newRoundRobinConfig() } }
});

var client = newGreet.GreeterClient(channel);
var response = await client.SayHelloAsync(newHelloRequest { Name = "world" });

For more information, see gPRC Client Load Balancing .

Transient failure handling with

gRPC calls may be interrupted by transient failures. Transient faults include:

  • The network connection was temporarily interrupted.
  • The service is temporarily unavailable.
  • Timeout due to server load.

When a gRPC call is interrupted, the client throws an RpcException with error details. Client applications must catch exceptions and choose how to handle errors.
var client =newGreeter.GreeterClient(channel);
try
{

var response =await client.SayHelloAsync(
    newHelloRequest{Name=".NET"});

Console.WriteLine("From server: "+ response.Message);

}
catch(RpcException ex)
{

// Write logic to inspect the error and retry
// if the error is from a transient fault.

}

Duplicating retry logic throughout the application is tedious and error-prone. Fortunately, the .NET gRPC client now has built-in support for automatic retries. Retry is centrally configured on the channel, and there are many options for customizing retry behavior using RetryPolicy.

var defaultMethodConfig =newMethodConfig
{

Names={MethodName.Default},
RetryPolicy=newRetryPolicy
{
    MaxAttempts=5,
    InitialBackoff=TimeSpan.FromSeconds(1),
    MaxBackoff=TimeSpan.FromSeconds(5),
    BackoffMultiplier=1.5,
    RetryableStatusCodes={StatusCode.Unavailable}
}

};

// Clients created with this channel will automatically retry failed calls.
var channel =GrpcChannel.ForAddress("https://localhost:5001",newGrpcChannelOptions
{

ServiceConfig=newServiceConfig{MethodConfigs={ defaultMethodConfig }}

});

For more information, see Using gRPC retries for transient failure handling .

Protobuf Performance

gRPC on .NET uses the Google.Protobuf package as the default serializer for messages. Protobuf is an efficient binary serialization format. Google.Protobuf is designed to improve performance, using code generation instead of reflection to serialize .NET objects. In .NET 5, we worked with the Protobuf team to add support for modern memory APIs such as Span<T>, ReadOnlySequence<T>, and IBufferWriter<T> to the serializer. Improvements in .NET 6 optimize an already fast serializer.
protocolbuffers/protobuf#8147 Added vectorized string serialization. SIMD instructions allow multiple characters to be processed in parallel, resulting in significant performance improvements when serializing certain string values.

privatestring _value =newstring(' ',10080);
privatebyte[] _outputBuffer =newbyte[10080];
[Benchmark]
publicvoidWriteString()
{

var span =newSpan<byte>(_outputBuffer);
WriteContext.Initialize(ref span,outWriteContext ctx);
ctx.WriteString(_value);
ctx.Flush();

}

image.png

protocolbuffers/protobuf#7645 Added a new API for creating ByteString instances. If you know the underlying data will not change, then use UnsafeByteOperations.UnsafeWrap to create a ByteString without copying the underlying data. This is useful if the application handles large byte payloads and you want to reduce the frequency of garbage collection.

gPRC download speed

gRPC users have reported slow download speeds at times. Our investigation found that HTTP/2 flow control throttles downloads when there is a delay between client and server. The server fills the receive buffer window before the client can run out, causing the server to pause sending data. gRPC messages are downloaded in start/stop bursts.

This has been in 161e0e031b57c6 dotnet/runtime#54755 . HttpClient now dynamically scales the receive buffer window. After the HTTP/2 connection is established, the client will send a ping to the server to measure latency. If there is high latency, the client automatically increases the receive buffer window, enabling fast, continuous downloads.

privateGrpcChannel _channel =GrpcChannel.ForAddress(...);
privateDownloadClient _client =newDownloadClient(_channel);

[Benchmark]
publicTaskGrpcLargeDownload()=>

_client.DownloadLargeMessageAsync(newEmptyMessage());

image.png

HTTP/3 support

gRPC over NET now supports HTTP/3. gRPC is built on top of the HTTP/3 support added to ASP.NET Core and HttpClient in .NET 6. For more information, see HTTP/3 Support in .NET 6.
.NET was the first gRPC implementation to support end-to-end HTTP/3, and we have submitted gRFC to support HTTP/3 in the future. gRPC with HTTP/3 is a highly requested feature , and it's great to see .NET leading the way.
image.png

Summary

Performance is a feature of .NET and gRPC, and .NET 6 is faster than ever. New performance-oriented features like client-side load balancing and HTTP/3 mean lower latency, higher throughput, and fewer servers. This is a save money, reduce energy consumption and build greener native cloud applications opportunities.

To try out the new features and get started with gRPC in .NET, the best place to start is to create a gRPC client and server in the ASP.NET Core tutorial.

We look forward to hearing about applications built with gRPC and .NET and your contributions in the dotnet and grpc repositories!

.NET reference documentation


微软技术栈
418 声望994 粉丝

微软技术生态官方平台。予力众生,成就不凡!微软致力于用技术改变世界,助力企业实现数字化转型。