Skip to content

Commit ef5cc48

Browse files
JamesNKwadepickett
andauthored
Add perf docs about making gRPC calls with async (#34902)
Co-authored-by: Wade Pickett <[email protected]>
1 parent 00444da commit ef5cc48

File tree

2 files changed

+28
-3
lines changed

2 files changed

+28
-3
lines changed

aspnetcore/grpc/client.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ author: jamesnk
44
description: Learn how to call gRPC services with the .NET gRPC client.
55
monikerRange: '>= aspnetcore-3.0'
66
ms.author: wpickett
7-
ms.date: 01/08/2025
7+
ms.date: 03/06/2025
88
uid: grpc/client
99
---
1010
# Call gRPC services with the .NET client
@@ -62,6 +62,8 @@ Channel and client performance and usage:
6262

6363
`GrpcChannel.ForAddress` isn't the only option for creating a gRPC client. If calling gRPC services from an ASP.NET Core app, consider [gRPC client factory integration](xref:grpc/clientfactory). gRPC integration with `HttpClientFactory` offers a centralized alternative to creating gRPC clients.
6464

65+
When calling gRPC methods, prefer using [asynchronous programming with async and await](/dotnet/csharp/asynchronous-programming/). Making gRPC calls with blocking, such as using `Task.Result` or `Task.Wait()`, prevents other tasks from using a thread. This can lead to thread pool starvation and poor performance. It could cause the app to hang with a deadlock. For more information, see [Asynchronous calls in client apps](xref:grpc/performance#asynchronous-calls-in-client-apps).
66+
6567
## Make gRPC calls
6668

6769
A gRPC call is initiated by calling a method on the client. The gRPC client will handle message serialization and addressing the gRPC call to the correct service.
@@ -87,8 +89,10 @@ Console.WriteLine("Greeting: " + response.Message);
8789

8890
Each unary service method in the `.proto` file will result in two .NET methods on the concrete gRPC client type for calling the method: an asynchronous method and a blocking method. For example, on `GreeterClient` there are two ways of calling `SayHello`:
8991

90-
* `GreeterClient.SayHelloAsync` - calls `Greeter.SayHello` service asynchronously. Can be awaited.
91-
* `GreeterClient.SayHello` - calls `Greeter.SayHello` service and blocks until complete. Don't use in asynchronous code.
92+
* `GreeterClient.SayHelloAsync` - calls the `Greeter.SayHello` service asynchronously. Can be awaited.
93+
* `GreeterClient.SayHello` - calls the `Greeter.SayHello` service and blocks until complete. Don't use in asynchronous code. Can cause performance and reliability issues.
94+
95+
For more information, see [Asynchronous calls in client apps](xref:grpc/performance#asynchronous-calls-in-client-apps).
9296

9397
### Server streaming call
9498

aspnetcore/grpc/performance.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,27 @@ For more information about garbage collection, see [Workstation and server garba
9494
> [!NOTE]
9595
> ASP.NET Core apps use server GC by default. Enabling `<ServerGarbageCollection>` is only useful in non-server gRPC client apps, for example in a gRPC client console app.
9696
97+
## Asynchronous calls in client apps
98+
99+
Prefer using [asynchronous programming with async and await](/dotnet/csharp/asynchronous-programming/) when calling gRPC methods. Making gRPC calls with blocking, such as using `Task.Result` or `Task.Wait()`, prevents other tasks from using a thread. This can lead to thread pool starvation, poor performance, and the app to hang with a deadlock.
100+
101+
All gRPC method types generate asynchronous APIs on gRPC clients. The exception is unary methods, which generate both async _and_ blocking methods.
102+
103+
Consider the following gRPC service defined in a *.proto* file:
104+
105+
```protobuf
106+
service Greeter {
107+
rpc SayHello (HelloRequest) returns (HelloReply);
108+
}
109+
```
110+
111+
Its generated `GreeterClient` type has two .NET methods for calling `SayHello`:
112+
113+
* `GreeterClient.SayHelloAsync` - calls the `Greeter.SayHello` service asynchronously. Can be awaited.
114+
* `GreeterClient.SayHello` - calls the `Greeter.SayHello` service and blocks until complete.
115+
116+
The blocking `GreeterClient.SayHello` method shouldn't be used in asynchronous code. It can cause performance and reliability issues.
117+
97118
## Load balancing
98119

99120
Some load balancers don't work effectively with gRPC. L4 (transport) load balancers operate at a connection level, by distributing TCP connections across endpoints. This approach works well for loading balancing API calls made with HTTP/1.1. Concurrent calls made with HTTP/1.1 are sent on different connections, allowing calls to be load balanced across endpoints.

0 commit comments

Comments
 (0)