Treinamento
Módulo
Balancear carga de tráfego não HTTP(S) no Azure - Training
Saberá as diferentes opções do balanceador de carga no Azure e a escolher e implementar a solução correta do Azure para tráfego não HTTP(S).
Não há mais suporte para esse navegador.
Atualize o Microsoft Edge para aproveitar os recursos, o suporte técnico e as atualizações de segurança mais recentes.
Observação
Esta não é a versão mais recente deste artigo. Para a versão atual, consulte a versão .NET 9 deste artigo.
Aviso
Esta versão do ASP.NET Core não tem mais suporte. Para obter mais informações, consulte a Política de Suporte do .NET e do .NET Core. Para a versão atual, consulte a versão .NET 9 deste artigo.
Importante
Essas informações relacionam-se ao produto de pré-lançamento, que poderá ser substancialmente modificado antes do lançamento comercial. A Microsoft não oferece nenhuma garantia, explícita ou implícita, quanto às informações fornecidas aqui.
Para a versão atual, consulte a versão .NET 9 deste artigo.
O balanceamento de carga do lado do cliente é um recurso que permite que os clientes do gRPC distribuam a carga de forma ideal entre os servidores disponíveis. Esse artigo discute como configurar o balanceamento de carga do lado do cliente para criar aplicativos do gRPC escalonáveis e de alto desempenho no .NET.
O balanceamento de carga do lado do cliente exige:
Grpc.Net.Client
versão 2.45.0 ou posterior.O balanceamento de carga do lado do cliente é configurado quando um canal é criado. Os dois componentes a serem considerados ao usar o balanceamento de carga:
Implementações internas de resolvedores e balanceadores de carga estão incluídas no Grpc.Net.Client
. O balanceamento de carga também pode ser estendido gravando resolvedores personalizados e balanceadores de carga.
Endereços, conexões e outro estado de balanceamento de carga são armazenados em uma instância de GrpcChannel
. Um canal deve ser reutilizado ao fazer chamadas do gRPC para que o balanceamento de carga funcione corretamente.
Observação
Algumas configurações de balanceamento de carga usam injeção de dependência (DI). Aplicativos que não usam DI podem criar uma instância ServiceCollection.
Se um aplicativo já tiver configuração de DI, como um site ASP.NET Core, os tipos deverão ser registrados com a instância de DI existente. GrpcChannelOptions.ServiceProvider
é configurado obtendo um IServiceProvider da ID.
O resolvedor é configurado usando o endereço com o qual um canal é criado. O esquema de URI do endereço especifica o resolvedor.
Esquema | Tipo | Descrição |
---|---|---|
dns |
DnsResolverFactory |
Resolve endereços consultando o nome do host para registros de endereço do DNS. |
static |
StaticResolverFactory |
Resolve os endereços especificados pelo aplicativo. Recomendado se um aplicativo já souber os endereços que ele chama. |
Um canal não chama diretamente um URI que corresponde a um resolvedor. Em vez disso, um resolvedor correspondente é criado e usado para resolve os endereços.
Por exemplo, usando GrpcChannel.ForAddress("dns:///my-example-host", new GrpcChannelOptions { Credentials = ChannelCredentials.Insecure })
:
dns
é mapeado para DnsResolverFactory
. Uma nova instância de um resolvedor do DNS é criada para o canal.my-example-host
e obtém dois resultados: 127.0.0.100
e 127.0.0.101
.127.0.0.100:80
e 127.0.0.101:80
para criar conexões e fazer chamadas do gRPC.O DnsResolverFactory
cria um resolvedor projetado para obter endereços de uma fonte externa. A resolução do DNS é comumente usada para balancear a carga em instâncias de pod que têm serviços sem cabeça do 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" });
O código anterior:
dns:///my-example-host
.
dns
é mapeado para DnsResolverFactory
.my-example-host
é o nome do host a ser resolvido.dns:///my-example-host:8080
configura chamadas gRPC a serem enviadas para a porta 8080.SayHello
do gRPC: my-example-host
.O desempenho é importante durante o balanceamento de carga. A latência da resolução de endereços é eliminada das chamadas do gRPC armazenando em cache os endereços. Um resolvedor será invocado ao fazer a primeira chamada do gRPC e chamadas subsequentes usam o cache.
Os endereços serão atualizados automaticamente se uma conexão for interrompida. A atualização é importante em cenários em que os endereços mudam em runtime. Por exemplo, no Kubernetes, um pod reiniciado dispara o resolvedor do DNS para atualizar e obter o novo endereço do pod.
Por padrão, um resolvedor do DNS será atualizado se uma conexão for interrompida. O resolvedor do DNS também pode, opcionalmente, atualizar-se em um intervalo periódico. Isso pode ser útil para detectar rapidamente novas instâncias de pod.
services.AddSingleton<ResolverFactory>(
sp => new DnsResolverFactory(refreshInterval: TimeSpan.FromSeconds(30)));
O código anterior cria um DnsResolverFactory
com um intervalo de atualização e o registra com injeção de dependência. Para obter mais informações sobre como usar um resolvedor configurado personalizado, consulte Configurar resolvedores personalizados e balanceadores de carga.
Um resolvedor estático é fornecido por StaticResolverFactory
. Esse resolvedor:
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);
O código anterior:
StaticResolverFactory
. Esta fábrica sabe sobre dois endereços: localhost:80
e localhost:81
.static:///my-example-host
. O esquema static
é mapeado para um resolvedor estático.GrpcChannelOptions.ServiceProvider
com o provedor de serviços de ID.Esse exemplo cria um novo ServiceCollection para ID. Suponha que um aplicativo já tenha configuração de ID, como um site do ASP.NET Core. Nesse caso, os tipos devem ser registrados com a instância ID existente. GrpcChannelOptions.ServiceProvider
é configurado obtendo um IServiceProvider da ID.
Um balanceador de carga é especificado em um service config
usando a coleção ServiceConfig.LoadBalancingConfigs
. Dois balanceadores de carga são internos e são mapeados para nomes de configuração do balanceador de carga:
Nome | Tipo | Descrição |
---|---|---|
pick_first |
PickFirstLoadBalancerFactory |
Tenta se conectar a endereços até que uma conexão seja feita com êxito. As chamadas do gRPC são todas feitas para a primeira conexão bem-sucedida. |
round_robin |
RoundRobinLoadBalancerFactory |
Tenta se conectar a todos os endereços. As chamadas do gRPC são distribuídas entre todas as conexões com êxito usando a lógica round robin. |
service config
é uma abreviação da configuração de serviço e é representada pelo tipo ServiceConfig
. Há algumas maneiras pelas quais um canal pode obter um service config
com um balanceador de carga configurado:
service config
quando um canal é criado usando GrpcChannelOptions.ServiceConfig
.service config
para um canal. Esse recurso permite que uma fonte externa especifique como seus chamadores devem executar o balanceamento de carga. Se um resolvedor dá suporte à resolução de um service config
for depende da implementação do resolvedor. Desabilite esse recurso com GrpcChannelOptions.DisableResolverServiceConfig
.service config
for fornecido, ou o service config
não tiver um balanceador de carga configurado, o canal usará como padrão 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" });
O código anterior:
RoundRobinLoadBalancerFactory
no service config
.SayHello
do gRPC: DnsResolverFactory
cria um resolvedor que obtém endereços para o nome do host my-example-host
.Um canal deve saber se as chamadas do gRPC são enviadas usando segurança de transporte. http
e https
não fazem mais parte do endereço; o esquema agora especifica um resolvedor, portanto Credentials
deve ser configurado nas opções de canal ao usar o balanceamento de carga.
ChannelCredentials.SecureSsl
- As chamadas do gRPC são protegidas com armazenamento local de thread (TLS, na sigla em inglês). Equivalente a um endereço https
.ChannelCredentials.Insecure
- As chamadas do gRPC não usam segurança do transporte. Equivalente a um endereço http
.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" });
A fábrica de clientes gRPC pode ser configurada para usar o balanceamento de carga:
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();
O código anterior:
O balanceamento de carga do lado do cliente é extensível:
Resolver
para criar um resolvedor personalizado e resolva endereços de uma nova fonte de dados.LoadBalancer
para criar um balanceador de carga personalizado com novo comportamento de balanceamento de carga.Importante
As APIs usadas para estender o balanceamento de carga do lado do cliente são experimentais. Elas podem ser alteradas sem aviso prévio.
Um resolvedor:
Resolver
e é criado por um ResolverFactory
. Crie um resolvedor personalizado implementando esses tipos.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);
}
}
No código anterior:
FileResolverFactory
implementa ResolverFactory
. Ele mapeia para o esquema file
e cria instâncias de FileResolver
.FileResolver
implementa PollingResolver
. PollingResolver
é um tipo base abstrato que facilita a implementação de um resolvedor com lógica assíncrona substituindo ResolveAsync
.ResolveAsync
file:///c:/addresses.json
torna-se c:\addresses.json
.Um balanceador de carga:
LoadBalancer
e é criado por um LoadBalancerFactory
. Crie um balanceador de carga personalizado e uma fábrica implementando esses tipos.Subchannel
.SubchannelPicker
. O canal usa internamente o seletor para escolher endereços ao fazer chamadas do gRPC.O SubchannelsLoadBalancer
é:
LoadBalancer
.Subchannel
dos endereços.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);
}
}
No código anterior:
RandomBalancerFactory
implementa LoadBalancerFactory
. Mapeia para o nome da política random
e cria instâncias de RandomBalancer
.RandomBalancer
implementa SubchannelsLoadBalancer
. Cria um RandomPicker
que escolhe aleatoriamente um subcanal.Resolvedores personalizados e balanceadores de carga precisam ser registrados com injeção de dependência (ID) quando são usados. Há duas opções:
GrpcChannelOptions.ServiceProvider
.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);
O código anterior:
ServiceCollection
e registra novas implementações de resolvedor e balanceador de carga.ServiceCollection
é integrado a um IServiceProvider
e definido como GrpcChannelOptions.ServiceProvider
.file:///c:/data/addresses.json
. O esquema file
é mapeado para FileResolverFactory
.service config
é random
. Mapeia para RandomLoadBalancerFactory
.O HTTP/2 multiplexa várias chamadas em uma única conexão TCP. Se gRPC e HTTP/2 forem usados com um balanceador de carga de rede (NLB, na sigla em inglês), a conexão será encaminhada para um servidor e todas as chamadas do gRPC serão enviadas para esse servidor. As outras instâncias de servidor no NLB ficam ociosas.
Os balanceadores de carga de rede são uma solução comum para balanceamento de carga porque são rápidos e leves. Por exemplo, o Kubernetes, por padrão, usa um balanceador de carga de rede para equilibrar conexões entre instâncias de pod. No entanto, os balanceadores de carga de rede não são eficazes na distribuição de carga quando usados com gRPC e HTTP/2.
gRPC e HTTP/2 podem ser efetivamente balanceados por carga usando um proxy do balanceador de carga do aplicativo ou um balanceamento de carga do lado do cliente. Ambas as opções permitem que chamadas do gRPC individuais sejam distribuídas entre servidores disponíveis. Decidir entre o balanceamento de carga de proxy e o balanceamento de carga do lado do cliente é uma opção arquitetônica. Há prós e contras para cada um.
Proxy: as chamadas do gRPC são enviadas para o proxy; o proxy toma uma decisão de balanceamento de carga e a chamada do gRPC é enviada para o ponto de extremidade final. O proxy é responsável por saber sobre pontos de extremidade. O uso de um proxy adiciona:
Balanceamento de carga do lado do cliente: o cliente gRPC toma uma decisão de balanceamento de carga quando uma chamada do gRPC é iniciada. A chamada do gRPC é enviada diretamente para o ponto de extremidade final. Quando usar o balanceamento de carga do lado do cliente:
Comentários do ASP.NET Core
O ASP.NET Core é um projeto código aberto. Selecione um link para fornecer comentários:
Treinamento
Módulo
Balancear carga de tráfego não HTTP(S) no Azure - Training
Saberá as diferentes opções do balanceador de carga no Azure e a escolher e implementar a solução correta do Azure para tráfego não HTTP(S).