Spolehlivé služby gRPC s konečnými termíny a zrušením
Termíny a zrušení jsou funkce používané klienty gRPC k přerušení probíhajících volání. Tento článek popisuje, proč jsou konečné termíny a zrušení důležité a jak je používat v aplikacích .NET gRPC.
Lhůty
Konečný termín umožňuje klientovi gRPC určit, jak dlouho bude čekat na dokončení volání. Při překročení termínu se volání zruší. Nastavení konečného termínu je důležité, protože poskytuje horní limit toho, jak dlouho může volání běžet. Přestane se chovat nekonečně, aby se služby chovaly špatně, a vyčerpávající prostředky serveru. Konečné termíny jsou užitečným nástrojem pro vytváření spolehlivých aplikací a měly by být nakonfigurovány.
Konfigurace konečného termínu:
- Termín se konfiguruje
CallOptions.Deadlinepomocí při volání. - Neexistuje žádná výchozí hodnota konečného termínu. Volání gRPC nejsou časově omezená, pokud není zadaný konečný termín.
- Konečným termínem je čas UTC při překročení konečného termínu. Například je
DateTime.UtcNow.AddSeconds(5)konečný termín 5 sekund od tohoto dne. - Pokud se použije minulý nebo aktuální čas, volání okamžitě překročí konečný termín.
- Termín se odesílá s voláním gRPC do služby a nezávisle ho sleduje klient i služba. Je možné, že se volání gRPC dokončí na jednom počítači, ale ve chvíli, kdy se odpověď vrátí klientovi, byl překročen konečný termín.
Pokud dojde k překročení termínu, klient a služba mají jiné chování:
- Klient okamžitě přeruší základní požadavek HTTP a vyvolá
DeadlineExceededchybu. Klientská aplikace se může rozhodnout zachytit chybu a zobrazit uživateli zprávu o časovém limitu. - Na serveru je spuštěný požadavek HTTP přerušen a je vyvolána metoda ServerCallContext.CancellationToken. I když je požadavek HTTP přerušen, volání gRPC se na serveru bude spouštět až do dokončení metody. Je důležité, aby se token zrušení předal asynchronním metodám, aby byly zrušeny společně s voláním. Například předání tokenu zrušení asynchronním databázovým dotazům a požadavkům HTTP. Předání tokenu zrušení umožňuje, aby se zrušené volání rychle dokončilo na serveru a uvolnoval prostředky pro další volání.
Nakonfigurujte CallOptions.Deadline nastavení konečného termínu pro volání gRPC:
var client = new Greet.GreeterClient(channel);
try
{
var response = await client.SayHelloAsync(
new HelloRequest { Name = "World" },
deadline: DateTime.UtcNow.AddSeconds(5));
// Greeting: Hello World
Console.WriteLine("Greeting: " + response.Message);
}
catch (RpcException ex) when (ex.StatusCode == StatusCode.DeadlineExceeded)
{
Console.WriteLine("Greeting timeout.");
}
Použití ServerCallContext.CancellationToken ve službě gRPC:
public override async Task<HelloReply> SayHello(HelloRequest request,
ServerCallContext context)
{
var user = await _databaseContext.GetUserAsync(request.Name,
context.CancellationToken);
return new HelloReply { Message = "Hello " + user.DisplayName };
}
Šíření konečných termínů
Při volání gRPC z spuštěné služby gRPC by se měl termín rozšířit. Například:
- Klientská aplikace volá
FrontendService.GetUsers konečným termínem. FrontendServicevoláUserService.GetUser. Termín určený klientem by měl být zadán pomocí nového volání gRPC.UserService.GetUserobdrží termín. Pokud dojde k překročení konečného termínu klientské aplikace, dojde ke správnému časového limitu.
Kontext volání poskytuje termín s ServerCallContext.Deadline :
public override async Task<UserResponse> GetUser(UserRequest request,
ServerCallContext context)
{
var client = new User.UserServiceClient(_channel);
var response = await client.GetUserAsync(
new UserRequest { Id = request.Id },
deadline: context.Deadline);
return response;
}
Ruční šíření konečných termínů může být obtížné. Konečný termín je potřeba předat každému hovoru a je snadné ho omylem zmeškat. V klientské továrně gRPC je k dispozici automatické řešení. Zadání: EnableCallContextPropagation
- Automaticky rozšíří token konečného termínu a zrušení do podřízených volání.
- Je vynikající způsob, jak zajistit, aby složité vnořené scénáře gRPC vždy šířely termín a zrušení.
services
.AddGrpcClient<User.UserServiceClient>(o =>
{
o.Address = new Uri("https://localhost:5001");
})
.EnableCallContextPropagation();
Další informace naleznete v tématu integrace klientské továrny gRPC v .NET.
Zrušení
Zrušení umožňuje klientovi gRPC zrušit dlouhotrvací volání, která už nepotřebujete. Například volání gRPC, které streamuje aktualizace v reálném čase, je zahájeno, když uživatel navštíví stránku na webu. Datový proud by měl být zrušen, když uživatel přejde ze stránky.
Volání gRPC lze v klientovi zrušit předáním tokenu zrušení s callOptions.CancellationToken nebo Dispose voláním volání.
private AsyncServerStreamingCall<HelloReply> _call;
public void StartStream()
{
_call = client.SayHellos(new HelloRequest { Name = "World" });
// Read response in background task.
_ = Task.Run(async () =>
{
await foreach (var response in _call.ResponseStream.ReadAllAsync())
{
Console.WriteLine("Greeting: " + response.Message);
}
});
}
public void StopStream()
{
_call.Dispose();
}
Služby gRPC, které je možné zrušit, by měly:
- Předejte
ServerCallContext.CancellationTokenasynchronním metodám. Zrušení asynchronních metod umožňuje rychlé dokončení volání na serveru. - Rozšíří token zrušení do podřízených volání. Rozšířením tokenu zrušení zajistíte zrušení podřízených volání s nadřazeným objektem . Objekt pro vytváření klienta gRPC
EnableCallContextPropagation()a automaticky rozšíří token zrušení.