Równoważenie obciążenia po stronie klienta gRPC
Uwaga
Nie jest to najnowsza wersja tego artykułu. Aby zapoznać się z bieżącą wersją, zobacz wersję tego artykułu platformy .NET 9.
Ważne
Te informacje odnoszą się do produktu w wersji wstępnej, który może zostać znacząco zmodyfikowany, zanim zostanie wydany komercyjnie. Firma Microsoft nie udziela żadnych gwarancji, jawnych lub domniemanych, w odniesieniu do informacji podanych w tym miejscu.
Aby zapoznać się z bieżącą wersją, zobacz wersję tego artykułu platformy .NET 9.
Autor: James Newton-King
Równoważenie obciążenia po stronie klienta to funkcja, która umożliwia klientom gRPC optymalną dystrybucję obciążenia na dostępnych serwerach. W tym artykule omówiono sposób konfigurowania równoważenia obciążenia po stronie klienta w celu tworzenia skalowalnych aplikacji gRPC o wysokiej wydajności na platformie .NET.
Równoważenie obciążenia po stronie klienta wymaga:
- .NET 5 lub nowszy.
Grpc.Net.Client
wersja 2.45.0 lub nowsza.
Konfigurowanie równoważenia obciążenia po stronie klienta usługi gRPC
Równoważenie obciążenia po stronie klienta jest konfigurowane podczas tworzenia kanału. Dwa składniki, które należy wziąć pod uwagę podczas korzystania z równoważenia obciążenia:
- Program rozpoznawania, który rozpoznaje adresy kanału. Narzędzia rozpoznawania nazw obsługują pobieranie adresów ze źródła zewnętrznego. Jest to również nazywane odnajdywaniem usług.
- Moduł równoważenia obciążenia, który tworzy połączenia i wybiera adres używany przez wywołanie gRPC.
Wbudowane implementacje rozwiązań rozpoznawania i modułów równoważenia obciążenia są uwzględniane w programie Grpc.Net.Client
. Równoważenie obciążenia można również rozszerzyć, pisząc niestandardowe moduły rozpoznawania i moduły równoważenia obciążenia.
Adresy, połączenia i inny stan równoważenia obciążenia są przechowywane w wystąpieniu GrpcChannel
. Kanał musi być ponownie używany podczas wykonywania wywołań gRPC w celu poprawnego działania równoważenia obciążenia.
Uwaga
Niektóre konfiguracje równoważenia obciążenia używają wstrzykiwania zależności (DI). Aplikacje, które nie używają di, mogą utworzyć ServiceCollection wystąpienie.
Jeśli aplikacja ma już konfigurację di, podobnie jak witryna internetowa ASP.NET Core, typy powinny być zarejestrowane w istniejącym wystąpieniu di. GrpcChannelOptions.ServiceProvider
program jest konfigurowany przez pobranie z IServiceProvider di.
Konfigurowanie narzędzia rozpoznawania nazw
Program rozpoznawania nazw jest konfigurowany przy użyciu adresu, za pomocą której jest tworzony kanał. Schemat identyfikatora URI adresu określa rozpoznawanie.
Schemat | Type | Opis |
---|---|---|
dns |
DnsResolverFactory |
Usuwa adresy, wysyłając zapytanie o nazwę hosta dla rekordów adresów DNS. |
static |
StaticResolverFactory |
Rozpoznaje adresy określone przez aplikację. Zalecane, jeśli aplikacja zna już adresy, które wywołuje. |
Kanał nie wywołuje bezpośrednio identyfikatora URI zgodnego z rozpoznawaniem nazw. Zamiast tego tworzony jest pasujący program rozpoznawania adresów i używany do rozpoznawania adresów.
Na przykład przy użyciu polecenia GrpcChannel.ForAddress("dns:///my-example-host", new GrpcChannelOptions { Credentials = ChannelCredentials.Insecure })
:
- Schemat
dns
jest mapowy naDnsResolverFactory
. Dla kanału jest tworzone nowe wystąpienie rozpoznawania nazw DNS. - Program rozpoznawania tworzy zapytanie DNS dla
my-example-host
i pobiera dwa wyniki:127.0.0.100
i127.0.0.101
. - Moduł równoważenia obciążenia używa
127.0.0.100:80
metod i127.0.0.101:80
do tworzenia połączeń i tworzenia wywołań gRPC.
DnsResolverFactory
Tworzy narzędzie rozpoznawania DnsResolverFactory
, które ma na celu pobieranie adresów ze źródła zewnętrznego. Rozpoznawanie nazw DNS jest często używane do równoważenia obciążenia w wystąpieniach zasobników, które mają usługi bezgłówne Kubernetes.
var channel = GrpcChannel.ForAddress(
"dns:///my-example-host",
new GrpcChannelOptions { Credentials = ChannelCredentials.Insecure });
var client = new Greet.GreeterClient(channel);
var response = await client.SayHelloAsync(new HelloRequest { Name = "world" });
Powyższy kod ma następujące działanie:
- Konfiguruje utworzony kanał przy użyciu adresu
dns:///my-example-host
.- Schemat
dns
jest mapowy naDnsResolverFactory
. my-example-host
jest nazwą hosta, która ma zostać rozpoznana.- Żaden port nie jest określony w adresie, dlatego wywołania gRPC są wysyłane do portu 80. Jest to domyślny port dla niezabezpieczonych kanałów. Port można opcjonalnie określić po nazwie hosta. Na przykład
dns:///my-example-host:8080
konfiguruje wywołania gRPC, które mają być wysyłane do portu 8080.
- Schemat
- Nie określa modułu równoważenia obciążenia. Kanał domyślnie wybiera pierwszy moduł równoważenia obciążenia.
- Uruchamia wywołanie
SayHello
gRPC:- Program rozpoznawania nazw DNS pobiera adresy dla nazwy
my-example-host
hosta . - Wybierz pierwszą próbę nawiązania połączenia z jednym z rozpoznanych adresów.
- Połączenie jest wysyłane do pierwszego adresu, z którymi kanał pomyślnie nawiązuje połączenie.
- Program rozpoznawania nazw DNS pobiera adresy dla nazwy
Buforowanie adresów DNS
Wydajność jest ważna podczas równoważenia obciążenia. Opóźnienie rozpoznawania adresów jest wyeliminowane z wywołań gRPC przez buforowanie adresów. Podczas pierwszego wywołania gRPC zostanie wywołany program rozpoznawania nazw, a kolejne wywołania używają pamięci podręcznej.
Adresy są automatycznie odświeżane, jeśli połączenie zostanie przerwane. Odświeżanie jest ważne w scenariuszach, w których adresy zmieniają się w czasie wykonywania. Na przykład na platformie Kubernetes ponownie uruchomiony zasobnik wyzwala program rozpoznawania nazw DNS w celu odświeżenia i pobrania nowego adresu zasobnika.
Domyślnie program rozpoznawania nazw DNS jest odświeżany, jeśli połączenie zostanie przerwane. Program rozpoznawania nazw DNS może również opcjonalnie odświeżyć się w okresowym interwale. Może to być przydatne w przypadku szybkiego wykrywania nowych wystąpień zasobników.
services.AddSingleton<ResolverFactory>(
sp => new DnsResolverFactory(refreshInterval: TimeSpan.FromSeconds(30)));
Powyższy kod tworzy element DnsResolverFactory
z interwałem odświeżania i rejestruje go za pomocą iniekcji zależności. Aby uzyskać więcej informacji na temat używania niestandardowego programu rozpoznawania nazw, zobacz Konfigurowanie niestandardowych rozpoznawania nazw i modułów równoważenia obciążenia.
StaticResolverFactory
Statyczny program rozpoznawania nazw jest dostarczany przez StaticResolverFactory
program . Ten program rozpoznawania:
- Nie wywołuje zewnętrznego źródła. Zamiast tego aplikacja kliencka konfiguruje adresy.
- Jest przeznaczony dla sytuacji, w których aplikacja zna już adresy, które wywołuje.
var factory = new StaticResolverFactory(addr => new[]
{
new BalancerAddress("localhost", 80),
new BalancerAddress("localhost", 81)
});
var services = new ServiceCollection();
services.AddSingleton<ResolverFactory>(factory);
var channel = GrpcChannel.ForAddress(
"static:///my-example-host",
new GrpcChannelOptions
{
Credentials = ChannelCredentials.Insecure,
ServiceProvider = services.BuildServiceProvider()
});
var client = new Greet.GreeterClient(channel);
Powyższy kod ma następujące działanie:
- Tworzy element
StaticResolverFactory
. Ta fabryka wie o dwóch adresach:localhost:80
ilocalhost:81
. - Rejestruje fabrykę przy użyciu wstrzykiwania zależności (DI).
- Konfiguruje utworzony kanał za pomocą:
- Adres
static:///my-example-host
. Schematstatic
jest mapowy na statyczny program rozpoznawania nazw. - Zestawy
GrpcChannelOptions.ServiceProvider
z dostawcą usług DI.
- Adres
W tym przykładzie zostanie utworzony nowy ServiceCollection element di. Załóżmy, że aplikacja ma już konfigurację di, na przykład witrynę internetową platformy ASP.NET Core. W takim przypadku typy powinny być zarejestrowane w istniejącym wystąpieniu di. GrpcChannelOptions.ServiceProvider
program jest konfigurowany przez pobranie z IServiceProvider di.
Konfigurowanie modułu równoważenia obciążenia
Moduł równoważenia obciążenia jest określony w obiekcie korzystającym service config
z kolekcji ServiceConfig.LoadBalancingConfigs
. Dwa moduły równoważenia obciążenia są wbudowane i mapowane na nazwy konfiguracji modułu równoważenia obciążenia:
Nazwisko | Pisz | Opis |
---|---|---|
pick_first |
PickFirstLoadBalancerFactory |
Próbuje nawiązać połączenie z adresami do momentu pomyślnego nawiązania połączenia. Wszystkie wywołania gRPC są wykonywane do pierwszego pomyślnego połączenia. |
round_robin |
RoundRobinLoadBalancerFactory |
Próbuje nawiązać połączenie ze wszystkimi adresami. Wywołania gRPC są dystrybuowane we wszystkich pomyślnych połączeniach przy użyciu logiki działania okrężnego. |
service config
jest skrótem konfiguracji usługi i jest reprezentowany przez ServiceConfig
typ. Istnieje kilka sposobów, na które kanał może uzyskać service config
skonfigurowany moduł równoważenia obciążenia:
- Aplikacja może określić
service config
, kiedy kanał zostanie utworzony przy użyciu poleceniaGrpcChannelOptions.ServiceConfig
. - Alternatywnie program rozpoznawania może rozpoznać
service config
element dla kanału. Ta funkcja umożliwia zewnętrznemu źródle określenie sposobu, w jaki jego osoby wywołujące powinny wykonywać równoważenie obciążenia. To, czy program rozpoznawania obsługuje rozpoznawanie elementuservice config
, zależy od implementacji narzędzia rozpoznawania nazw. Wyłącz tę funkcję za pomocąGrpcChannelOptions.DisableResolverServiceConfig
polecenia . - Jeśli parametr nie
service config
jest podany lubservice config
nie ma skonfigurowanego modułu równoważenia obciążenia, kanał domyślnie ma wartośćPickFirstLoadBalancerFactory
.
var channel = GrpcChannel.ForAddress(
"dns:///my-example-host",
new GrpcChannelOptions
{
Credentials = ChannelCredentials.Insecure,
ServiceConfig = new ServiceConfig { LoadBalancingConfigs = { new RoundRobinConfig() } }
});
var client = new Greet.GreeterClient(channel);
var response = await client.SayHelloAsync(new HelloRequest { Name = "world" });
Powyższy kod ma następujące działanie:
- Określa element
RoundRobinLoadBalancerFactory
w obiekcieservice config
. - Uruchamia wywołanie
SayHello
gRPC:DnsResolverFactory
Tworzy program rozpoznawania nazw, który pobiera adresy dla nazwymy-example-host
hosta .- Moduł równoważenia obciążenia z działaniem okrężnym próbuje nawiązać połączenie ze wszystkimi rozwiązanymi adresami.
- Wywołania gRPC są dystrybuowane równomiernie przy użyciu logiki działania okrężnego.
Konfigurowanie poświadczeń kanału
Kanał musi wiedzieć, czy wywołania gRPC są wysyłane przy użyciu zabezpieczeń transportu. http
i https
nie są już częścią adresu, schemat określa teraz rozpoznawanie, więc Credentials
należy skonfigurować opcje kanału podczas korzystania z równoważenia obciążenia.
ChannelCredentials.SecureSsl
- Wywołania gRPC są zabezpieczone za pomocą protokołu Transport Layer Security (TLS).https
Odpowiednik adresu.ChannelCredentials.Insecure
- Wywołania gRPC nie używają zabezpieczeń transportu.http
Odpowiednik adresu.
var channel = GrpcChannel.ForAddress(
"dns:///my-example-host",
new GrpcChannelOptions { Credentials = ChannelCredentials.Insecure });
var client = new Greet.GreeterClient(channel);
var response = await client.SayHelloAsync(new HelloRequest { Name = "world" });
Używanie równoważenia obciążenia z fabryką klienta gRPC
Fabrykę klienta gRPC można skonfigurować do używania równoważenia obciążenia:
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddGrpcClient<Greeter.GreeterClient>(o =>
{
o.Address = new Uri("dns:///my-example-host");
})
.ConfigureChannel(o => o.Credentials = ChannelCredentials.Insecure);
builder.Services.AddSingleton<ResolverFactory>(
sp => new DnsResolverFactory(refreshInterval: TimeSpan.FromSeconds(30)));
var app = builder.Build();
Powyższy kod ma następujące działanie:
- Konfiguruje klienta przy użyciu adresu równoważenia obciążenia.
- Określa poświadczenia kanału.
- Rejestruje typy DI w aplikacji IServiceCollection.
Pisanie niestandardowych rozwiązań rozpoznawania i modułów równoważenia obciążenia
Równoważenie obciążenia po stronie klienta jest rozszerzalne:
- Zaimplementuj
Resolver
, aby utworzyć niestandardowy program rozpoznawania nazw i rozpoznawać adresy z nowego źródła danych. - Zaimplementuj
LoadBalancer
tworzenie niestandardowego modułu równoważenia obciążenia przy użyciu nowego zachowania równoważenia obciążenia.
Ważne
Interfejsy API używane do rozszerzania równoważenia obciążenia po stronie klienta są eksperymentalne. Mogą się zmieniać bez powiadomienia.
Tworzenie niestandardowego rozpoznawania nazw
Program rozpoznawania:
- Implementuje
Resolver
element i jest tworzony przez elementResolverFactory
. Utwórz niestandardowy program rozpoznawania, implementując te typy. - Odpowiada za rozpoznawanie adresów używanych przez moduł równoważenia obciążenia.
- Opcjonalnie może zapewnić konfigurację usługi.
public class FileResolver : PollingResolver
{
private readonly Uri _address;
private readonly int _port;
public FileResolver(Uri address, int defaultPort, ILoggerFactory loggerFactory)
: base(loggerFactory)
{
_address = address;
_port = defaultPort;
}
public override async Task ResolveAsync(CancellationToken cancellationToken)
{
// Load JSON from a file on disk and deserialize into endpoints.
var jsonString = await File.ReadAllTextAsync(_address.LocalPath);
var results = JsonSerializer.Deserialize<string[]>(jsonString);
var addresses = results.Select(r => new BalancerAddress(r, _port)).ToArray();
// Pass the results back to the channel.
Listener(ResolverResult.ForResult(addresses));
}
}
public class FileResolverFactory : ResolverFactory
{
// Create a FileResolver when the URI has a 'file' scheme.
public override string Name => "file";
public override Resolver Create(ResolverOptions options)
{
return new FileResolver(options.Address, options.DefaultPort, options.LoggerFactory);
}
}
Powyższy kod:
FileResolverFactory
implementujeResolverFactory
. Mapuje on nafile
schemat i tworzyFileResolver
wystąpienia.FileResolver
implementujePollingResolver
.PollingResolver
jest abstrakcyjnym typem podstawowym, który ułatwia implementowanie rozpoznawania za pomocą logiki asynchronicznej przez zastąpienie elementuResolveAsync
.- W pliku
ResolveAsync
:- Identyfikator URI pliku jest konwertowany na ścieżkę lokalną. Na przykład,
file:///c:/addresses.json
staje sięc:\addresses.json
. - Kod JSON jest ładowany z dysku i konwertowany na kolekcję adresów.
- Odbiornik jest wywoływany z wynikami, aby poinformować kanał, że adresy są dostępne.
- Identyfikator URI pliku jest konwertowany na ścieżkę lokalną. Na przykład,
Tworzenie niestandardowego modułu równoważenia obciążenia
Moduł równoważenia obciążenia:
- Implementuje
LoadBalancer
element i jest tworzony przez elementLoadBalancerFactory
. Utwórz niestandardowy moduł równoważenia obciążenia i fabrykę, implementując te typy. - Otrzymuje adresy z narzędzia rozpoznawania nazw i tworzy
Subchannel
wystąpienia. - Śledzi stan połączenia i tworzy element
SubchannelPicker
. Kanał wewnętrznie używa selektora do wybierania adresów podczas wykonywania wywołań gRPC.
Element SubchannelsLoadBalancer
to:
- Abstrakcyjna klasa bazowa, która implementuje
LoadBalancer
element . - Zarządza tworzeniem
Subchannel
wystąpień na podstawie adresów. - Ułatwia implementowanie niestandardowych zasad wybierania w kolekcji podkanałów.
public class RandomBalancer : SubchannelsLoadBalancer
{
public RandomBalancer(IChannelControlHelper controller, ILoggerFactory loggerFactory)
: base(controller, loggerFactory)
{
}
protected override SubchannelPicker CreatePicker(List<Subchannel> readySubchannels)
{
return new RandomPicker(readySubchannels);
}
private class RandomPicker : SubchannelPicker
{
private readonly List<Subchannel> _subchannels;
public RandomPicker(List<Subchannel> subchannels)
{
_subchannels = subchannels;
}
public override PickResult Pick(PickContext context)
{
// Pick a random subchannel.
return PickResult.ForSubchannel(_subchannels[Random.Shared.Next(0, _subchannels.Count)]);
}
}
}
public class RandomBalancerFactory : LoadBalancerFactory
{
// Create a RandomBalancer when the name is 'random'.
public override string Name => "random";
public override LoadBalancer Create(LoadBalancerOptions options)
{
return new RandomBalancer(options.Controller, options.LoggerFactory);
}
}
Powyższy kod:
RandomBalancerFactory
implementujeLoadBalancerFactory
. Mapuje onarandom
nazwę zasad i tworzyRandomBalancer
wystąpienia.RandomBalancer
implementujeSubchannelsLoadBalancer
. Tworzy obiektRandomPicker
, który losowo wybiera podkanał.
Konfigurowanie niestandardowych modułów rozpoznawania i modułów równoważenia obciążenia
Niestandardowe moduły rozpoznawania i moduły równoważenia obciążenia muszą być zarejestrowane za pomocą wstrzykiwania zależności (DI), gdy są używane. Istnieje kilka opcji:
- Jeśli aplikacja korzysta już z di, na przykład aplikacji internetowej ASP.NET Core, można je zarejestrować przy użyciu istniejącej konfiguracji di. Element IServiceProvider można rozpoznać z di i przekazać do kanału przy użyciu polecenia
GrpcChannelOptions.ServiceProvider
. - Jeśli aplikacja nie korzysta z di, utwórz:
- Element ServiceCollection z zarejestrowanymi typami.
- Dostawca usług przy użyciu polecenia BuildServiceProvider.
var services = new ServiceCollection();
services.AddSingleton<ResolverFactory, FileResolverFactory>();
services.AddSingleton<LoadBalancerFactory, RandomLoadBalancerFactory>();
var channel = GrpcChannel.ForAddress(
"file:///c:/data/addresses.json",
new GrpcChannelOptions
{
Credentials = ChannelCredentials.Insecure,
ServiceConfig = new ServiceConfig { LoadBalancingConfigs = { new LoadBalancingConfig("random") } },
ServiceProvider = services.BuildServiceProvider()
});
var client = new Greet.GreeterClient(channel);
Powyższy kod ma następujące działanie:
- Tworzy element
ServiceCollection
i rejestruje nowe implementacje modułu rozpoznawania nazw i modułu równoważenia obciążenia. - Tworzy kanał skonfigurowany do używania nowych implementacji:
ServiceCollection
element jest wbudowany w elementIServiceProvider
i ustawiony naGrpcChannelOptions.ServiceProvider
wartość .- Adres kanału to
file:///c:/data/addresses.json
. Schematfile
jest mapowy naFileResolverFactory
. service config
Nazwa modułu równoważenia obciążenia torandom
. Mapuje naRandomLoadBalancerFactory
.
Dlaczego równoważenie obciążenia jest ważne
Multipleksy HTTP/2 w jednym połączeniu TCP. Jeśli gRPC i HTTP/2 są używane z modułem równoważenia obciążenia sieciowego (NLB), połączenie jest przekazywane do serwera, a wszystkie wywołania gRPC są wysyłane do tego jednego serwera. Inne wystąpienia serwera w równoważeniu obciążenia sieciowego są bezczynne.
Moduły równoważenia obciążenia sieciowego są typowym rozwiązaniem do równoważenia obciążenia, ponieważ są one szybkie i lekkie. Na przykład platforma Kubernetes domyślnie używa modułu równoważenia obciążenia sieciowego do równoważenia połączeń między wystąpieniami zasobników. Jednak moduły równoważenia obciążenia sieciowego nie są skuteczne podczas dystrybucji obciążenia w przypadku użycia z gRPC i HTTP/2.
Równoważenie obciążenia po stronie klienta lub serwera proxy?
Usługi gRPC i HTTP/2 można skutecznie zrównoważyć przy użyciu serwera proxy modułu równoważenia obciążenia aplikacji lub równoważenia obciążenia po stronie klienta. Obie te opcje umożliwiają dystrybucję poszczególnych wywołań gRPC na dostępnych serwerach. Wybór między serwerem proxy a równoważeniem obciążenia po stronie klienta jest wyborem architektury. Każda z nich ma zalety i wady.
Serwer proxy: wywołania gRPC są wysyłane do serwera proxy, serwer proxy podejmuje decyzję o równoważeniu obciążenia, a wywołanie gRPC jest wysyłane do końcowego punktu końcowego. Serwer proxy jest odpowiedzialny za poznanie punktów końcowych. Używanie serwera proxy dodaje:
- Dodatkowy przeskok sieciowy do wywołań gRPC.
- Opóźnienie i zużywa dodatkowe zasoby.
- Serwer proxy musi być poprawnie skonfigurowany i skonfigurowany.
Równoważenie obciążenia po stronie klienta: klient gRPC podejmuje decyzję o równoważeniu obciążenia po uruchomieniu wywołania gRPC. Wywołanie gRPC jest wysyłane bezpośrednio do końcowego punktu końcowego. W przypadku korzystania z równoważenia obciążenia po stronie klienta:
- Klient jest odpowiedzialny za poznanie dostępnych punktów końcowych i podejmowanie decyzji dotyczących równoważenia obciążenia.
- Wymagana jest dodatkowa konfiguracja klienta.
- Wywołania gRPC o wysokiej wydajności eliminują potrzebę korzystania z serwera proxy o wysokiej wydajności.