gRPC istemci tarafı yük dengeleme
Uyarı
ASP.NET Core'un bu sürümü artık desteklenmiyor. Daha fazla bilgi için bkz . .NET ve .NET Core Destek İlkesi. Geçerli sürüm için bu makalenin .NET 9 sürümüne bakın.
Yayınlayan James Newton-King
İstemci tarafı yük dengeleme, gRPC istemcilerinin yükü kullanılabilir sunucular arasında en iyi şekilde dağıtmasını sağlayan bir özelliktir. Bu makalede, .NET'te ölçeklenebilir, yüksek performanslı gRPC uygulamaları oluşturmak için istemci tarafı yük dengelemenin nasıl yapılandırılacağı açıklanır.
İstemci tarafı yük dengeleme şunları gerektirir:
- .NET 5 veya üzeri.
Grpc.Net.Client
sürüm 2.45.0 veya üzeri.
gRPC istemci tarafı yük dengelemeyi yapılandırma
bir kanal oluşturulduğunda istemci tarafı yük dengeleme yapılandırılır. Yük dengeleme kullanılırken göz önünde bulundurulması gereken iki bileşen:
- Kanalın adreslerini çözümleyen çözümleyici. Çözümleyiciler, dış kaynaktan adres almayı destekler. Bu, hizmet bulma olarak da bilinir.
- Bağlantıları oluşturan ve gRPC çağrısının kullanacağı adresi seçen yük dengeleyici.
Çözümleyicilerin ve yük dengeleyicilerin yerleşik uygulamaları içinde Grpc.Net.Client
yer alır. Yük dengeleme, özel çözümleyiciler ve yük dengeleyiciler yazılarak da uzatılabilir.
Adresler, bağlantılar ve diğer yük dengeleme durumu bir GrpcChannel
örnekte depolanır. Yük dengelemenin düzgün çalışması için gRPC çağrıları yapılırken bir kanalın yeniden kullanılması gerekir.
Not
Bazı yük dengeleme yapılandırmaları bağımlılık ekleme (DI) kullanır. DI kullanmayan uygulamalar örnek ServiceCollection oluşturabilir.
Bir uygulamada ASP.NET Core web sitesi gibi DI kurulumu zaten varsa, türlerin mevcut DI örneğine kaydedilmesi gerekir. GrpcChannelOptions.ServiceProvider
, DI'den bir IServiceProvider alarak yapılandırılır.
Çözümleyiciyi yapılandırma
Çözümleyici, kanalın oluşturulduğu adres kullanılarak yapılandırılır. Adresin URI düzeni çözümleyiciyi belirtir.
Düzen | Type | Açıklama |
---|---|---|
dns |
DnsResolverFactory |
DNS adresi kayıtları için ana bilgisayar adını sorgulayarak adresleri çözümler. |
static |
StaticResolverFactory |
Uygulamanın belirttiği adresleri çözümler. Bir uygulama, çağırılan adresleri zaten biliyorsa önerilir. |
Kanal, çözümleyiciyle eşleşen bir URI'ye doğrudan çağrı yapmaz. Bunun yerine, eşleşen bir çözümleyici oluşturulur ve adresleri çözümlemek için kullanılır.
Örneğin, kullanarak GrpcChannel.ForAddress("dns:///my-example-host", new GrpcChannelOptions { Credentials = ChannelCredentials.Insecure })
:
- Şema
dns
ileDnsResolverFactory
eşler. Kanal için yeni bir DNS çözümleyici örneği oluşturulur. - Çözümleyici için
my-example-host
bir DNS sorgusu yapar ve iki sonuç alır:127.0.0.100
ve127.0.0.101
. - Yük dengeleyici, bağlantıları oluşturmak ve gRPC çağrıları yapmak için ve
127.0.0.101:80
kullanır127.0.0.100:80
.
DnsResolverFactory
, DnsResolverFactory
dış kaynaktan adresleri almak için tasarlanmış bir çözümleyici oluşturur. DNS çözümlemesi genellikle Kubernetes başsız hizmetleri olan pod örnekleri üzerinde yük dengelemesi yapmak için kullanılır.
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" });
Yukarıdaki kod:
- Oluşturulan kanalı adresiyle
dns:///my-example-host
yapılandırılır.- Şema
dns
ileDnsResolverFactory
eşler. my-example-host
çözümlenmesi gereken ana bilgisayar adıdır.- Adreste bağlantı noktası belirtilmediğinden gRPC çağrıları 80 numaralı bağlantı noktasına gönderilir. Bu, güvenli olmayan kanallar için varsayılan bağlantı noktasıdır. konak adından sonra isteğe bağlı olarak bir bağlantı noktası belirtilebilir. Örneğin,
dns:///my-example-host:8080
8080 numaralı bağlantı noktasına gönderilecek gRPC çağrılarını yapılandırıyor.
- Şema
- Yük dengeleyici belirtmez. Kanal varsayılan olarak ilk yük dengeleyiciyi seçer.
- gRPC çağrısını
SayHello
başlatır:- DNS çözümleyicisi ana bilgisayar adı
my-example-host
için adresleri alır. - Çözümlenen adreslerden birine bağlanmaya yönelik ilk yük dengeleyici girişimlerini seçin.
- Arama, kanalın başarıyla bağlandığınız ilk adrese gönderilir.
- DNS çözümleyicisi ana bilgisayar adı
DNS adresi önbelleğe alma
Yük dengeleme sırasında performans önemlidir. Adresleri çözümleme gecikmesi, adresleri önbelleğe alarak gRPC çağrılarından ortadan kalkar. İlk gRPC çağrısı yapılırken bir çözümleyici çağrılır ve sonraki çağrılar önbelleği kullanır.
Bağlantı kesilirse adresler otomatik olarak yenilenir. Adreslerin çalışma zamanında değiştiği senaryolarda yenileme önemlidir. Örneğin Kubernetes'te yeniden başlatılan bir pod , DNS çözümleyicisini tetikler ve pod'un yeni adresini alır.
Varsayılan olarak, bir bağlantı kesilirse DNS çözümleyicisi yenilenir. DNS çözümleyicisi, isteğe bağlı olarak düzenli aralıklarla kendini yenileyebilir. Bu, yeni pod örneklerini hızla algılamak için yararlı olabilir.
services.AddSingleton<ResolverFactory>(
sp => new DnsResolverFactory(refreshInterval: TimeSpan.FromSeconds(30)));
Yukarıdaki kod yenileme aralığına sahip bir DnsResolverFactory
oluşturur ve bağımlılık ekleme ile kaydeder. Özel olarak yapılandırılmış çözümleyici kullanma hakkında daha fazla bilgi için bkz . Özel çözümleyicileri ve yük dengeleyicileri yapılandırma.
StaticResolverFactory
Statik çözümleyici tarafından StaticResolverFactory
sağlanır. Bu çözümleyici:
- Dış kaynağı çağırmaz. Bunun yerine, istemci uygulaması adresleri yapılandırıyor.
- Bir uygulamanın çağırdığı adresleri zaten bildiği durumlar için tasarlanmıştır.
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);
Yukarıdaki kod:
- oluşturur
StaticResolverFactory
. Bu fabrika iki adres biliyor:localhost:80
velocalhost:81
. - Fabrikayı bağımlılık ekleme (DI) ile kaydeder.
- Oluşturulan kanalı şu şekilde yapılandırılır:
- adresi
static:///my-example-host
. Düzenstatic
, statik bir çözümleyiciye eşler. - DI hizmet sağlayıcısı ile ayarlar
GrpcChannelOptions.ServiceProvider
.
- adresi
Bu örnek, DI için yeni ServiceCollection bir oluşturur. Bir uygulamanın ASP.NET Core web sitesi gibi zaten DI kurulumu olduğunu varsayalım. Bu durumda, türlerin mevcut DI örneğine kaydedilmesi gerekir. GrpcChannelOptions.ServiceProvider
, DI'den bir IServiceProvider alarak yapılandırılır.
Yük dengeleyiciyi yapılandırma
Bir yük dengeleyici içinde koleksiyonu kullanılarak ServiceConfig.LoadBalancingConfigs
belirtilirservice config
. İki yük dengeleyici yerleşik olarak bulunur ve yük dengeleyici yapılandırma adlarına eşlenir:
Adı | Tür | Açıklama |
---|---|---|
pick_first |
PickFirstLoadBalancerFactory |
Bağlantı başarıyla yapılana kadar adreslere bağlanmayı dener. gRPC çağrılarının tümü ilk başarılı bağlantıya yapılır. |
round_robin |
RoundRobinLoadBalancerFactory |
Tüm adreslere bağlanmayı dener. gRPC çağrıları hepsini bir kez deneme mantığı kullanılarak tüm başarılı bağlantılar arasında dağıtılır. |
service config
, hizmet yapılandırmasının kısaltmasıdır ve türüyle ServiceConfig
temsil edilir. Bir kanalın yük dengeleyici yapılandırılmış bir şekilde elde service config
etmenin birkaç yolu vardır:
- Bir uygulama kullanılarak
GrpcChannelOptions.ServiceConfig
bir kanalın ne zaman oluşturulduğunu belirtebilirservice config
. - Alternatif olarak, çözümleyici bir kanal için çözümleyebilir
service config
. Bu özellik, dış kaynağın çağıranların yük dengelemeyi nasıl gerçekleştirmesi gerektiğini belirtmesine olanak tanır. Çözümleyicinin çözümü destekleyipservice config
desteklemediği çözümleyici uygulamasına bağlıdır. bu özelliği ileGrpcChannelOptions.DisableResolverServiceConfig
devre dışı bırakın. - Hayır
service config
sağlanmışsa veyaservice config
yük dengeleyici yapılandırılmamışsa, kanal varsayılan olarak olarakPickFirstLoadBalancerFactory
kullanılır.
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" });
Yukarıdaki kod:
- içinde
service config
birRoundRobinLoadBalancerFactory
belirtir. - gRPC çağrısını
SayHello
başlatır:DnsResolverFactory
ana bilgisayar adımy-example-host
için adresleri alan bir çözümleyici oluşturur.- Hepsini bir kez deneme yük dengeleyici, tüm çözümlenen adreslere bağlanmayı dener.
- gRPC çağrıları hepsini bir kez deneme mantığı kullanılarak eşit olarak dağıtılır.
Kanal kimlik bilgilerini yapılandırma
Kanalın gRPC çağrılarının aktarım güvenliği kullanılarak gönderilip gönderilmediğini bilmesi gerekir. http
ve https
artık adresin bir parçası değildir, şema artık bir çözümleyici belirtir, bu nedenle Credentials
yük dengeleme kullanılırken kanal seçeneklerinde yapılandırılmalıdır.
ChannelCredentials.SecureSsl
- gRPC çağrılarının güvenliği Aktarım Katmanı Güvenliği (TLS) ile sağlanır. Birhttps
adrese eşdeğerdir.ChannelCredentials.Insecure
- gRPC çağrıları aktarım güvenliğini kullanmaz. Birhttp
adrese eşdeğerdir.
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" });
gRPC istemci fabrikası ile yük dengelemeyi kullanma
gRPC istemci fabrikası yük dengelemeyi kullanacak şekilde yapılandırılabilir:
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();
Yukarıdaki kod:
- İstemciyi bir yük dengeleme adresiyle yapılandırıyor.
- Kanal kimlik bilgilerini belirtir.
- DI türlerini uygulamanın IServiceCollectionöğesine kaydeder.
Özel çözümleyiciler ve yük dengeleyiciler yazma
İstemci tarafı yük dengeleme genişletilebilir:
- Özel çözümleyici oluşturmak ve yeni bir veri kaynağından adresleri çözümlemek için uygulayın
Resolver
. - Yeni yük dengeleme davranışıyla özel bir yük dengeleyici oluşturmak için uygulayın
LoadBalancer
.
Önemli
İstemci tarafı yük dengelemeyi genişletmek için kullanılan API'ler deneyseldir. Bildirimde bulunmadan değişebilirler.
Özel çözümleyici oluşturma
Çözümleyici:
Resolver
uygular ve tarafındanResolverFactory
oluşturulur. Bu türleri uygulayarak özel bir çözümleyici oluşturun.- Yük dengeleyicinin kullandığı adresleri çözümlemek sorumludur.
- İsteğe bağlı olarak bir hizmet yapılandırması sağlayabilir.
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);
}
}
Önceki kodda:
FileResolverFactory
uygularResolverFactory
. Şemaya eşlerfile
ve örnekler oluştururFileResolver
.FileResolver
uygularPollingResolver
.PollingResolver
, geçersiz kılarakResolveAsync
zaman uyumsuz mantıkla çözümleyici uygulamayı kolaylaştıran soyut bir temel türüdür.- içinde
ResolveAsync
:- Dosya URI'si yerel yola dönüştürülür. Örneğin
file:///c:/addresses.json
,c:\addresses.json
olur. - JSON diskten yüklenir ve bir adres koleksiyonuna dönüştürülür.
- Dinleyici, kanala adreslerin kullanılabilir olduğunu bildirmek için sonuçlarla birlikte çağrılır.
- Dosya URI'si yerel yola dönüştürülür. Örneğin
Özel yük dengeleyici oluşturma
Yük dengeleyici:
LoadBalancer
uygular ve tarafındanLoadBalancerFactory
oluşturulur. Bu türleri uygulayarak özel bir yük dengeleyici ve fabrika oluşturun.- Bir çözümleyiciden adresler verilir ve örnekler oluşturulur
Subchannel
. - Bağlantıyla ilgili durumu izler ve bir
SubchannelPicker
oluşturur. Kanal, gRPC çağrıları yaparken adresleri seçmek için seçiciyi dahili olarak kullanır.
Şu SubchannelsLoadBalancer
şekildedir:
- uygulayan
LoadBalancer
soyut bir temel sınıf. - Adreslerden örnek oluşturmayı
Subchannel
yönetir. - Bir alt kanal koleksiyonu üzerinde özel bir malzeme çekme ilkesi uygulamayı kolaylaştırır.
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);
}
}
Önceki kodda:
RandomBalancerFactory
uygularLoadBalancerFactory
. İlke adıylarandom
eşler ve örnekler oluştururRandomBalancer
.RandomBalancer
uygularSubchannelsLoadBalancer
. Rastgele birRandomPicker
alt kanal seçen bir oluşturur.
Özel çözümleyicileri ve yük dengeleyicileri yapılandırma
Özel çözümleyicilerin ve yük dengeleyicilerin kullanıldıklarında bağımlılık ekleme (DI) ile kaydedilmesi gerekir. Birkaç seçenek vardır:
- Bir uygulama ASP.NET Core web uygulaması gibi zaten DI kullanıyorsa, mevcut DI yapılandırmasına kaydedilebilir. , IServiceProvider DI'den çözümlenebilir ve kullanılarak
GrpcChannelOptions.ServiceProvider
kanala geçirilebilir. - Bir uygulama DI kullanmıyorsa aşağıdakini oluşturun:
- Kendisiyle kaydedilmiş türleri olan A ServiceCollection .
- kullanan BuildServiceProviderbir hizmet sağlayıcısı.
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);
Yukarıdaki kod:
- Bir
ServiceCollection
oluşturur ve yeni çözümleyici ve yük dengeleyici uygulamalarını kaydeder. - Yeni uygulamaları kullanmak üzere yapılandırılmış bir kanal oluşturur:
ServiceCollection
yerleşikIServiceProvider
olarak bulunur ve olarakGrpcChannelOptions.ServiceProvider
ayarlanır.- Kanal adresi şeklindedir
file:///c:/data/addresses.json
. Şemafile
ileFileResolverFactory
eşler. service config
yük dengeleyici adıdırrandom
.RandomLoadBalancerFactory
ile eşler.
Yük dengeleme neden önemlidir?
HTTP/2, tek bir TCP bağlantısında birden çok çağrıyı katlar. gRPC ve HTTP/2 bir ağ yük dengeleyici (NLB) ile kullanılıyorsa, bağlantı bir sunucuya iletilir ve tüm gRPC çağrıları bu sunucuya gönderilir. NLB'de diğer sunucu örnekleri boşta.
Ağ yük dengeleyicileri, hızlı ve hafif olduklarından yük dengeleme için yaygın bir çözümdir. Örneğin Kubernetes, pod örnekleri arasındaki bağlantıları dengelemek için varsayılan olarak bir ağ yük dengeleyici kullanır. Ancak ağ yük dengeleyicileri, gRPC ve HTTP/2 ile kullanıldığında yükü dağıtmada etkili değildir.
Ara sunucu veya istemci tarafı yük dengelemesi mi?
gRPC ve HTTP/2, uygulama yük dengeleyici ara sunucusu veya istemci tarafı yük dengelemesi kullanılarak etkili bir şekilde yük dengelenebilir. Bu seçeneklerin her ikisi de tek tek gRPC çağrılarının kullanılabilir sunucular arasında dağıtılabilmesini sağlar. Ara sunucu ile istemci tarafı yük dengeleme arasında karar vermek mimari bir seçimdir. Her birinin artıları ve dezavantajları vardır.
Ara sunucu: gRPC çağrıları ara sunucuya gönderilir, ara sunucu bir yük dengeleme kararı alır ve gRPC çağrısı son uç noktaya gönderilir. Proxy, uç noktaları bilmekten sorumludur. Ara sunucu kullanıldığında şu ekler:
- gRPC çağrılarına ek bir ağ atlama.
- Gecikme süresi ve ek kaynaklar kullanır.
- Proxy sunucusu doğru şekilde ayarlanmalıdır ve yapılandırılmalıdır.
İstemci tarafı yük dengeleme: gRPC istemcisi bir gRPC çağrısı başlatıldığında yük dengeleme kararı verir. gRPC çağrısı doğrudan son uç noktaya gönderilir. İstemci tarafı yük dengeleme kullanılırken:
- İstemci, kullanılabilir uç noktaları bilmek ve yük dengeleme kararları vermekle sorumludur.
- Ek istemci yapılandırması gereklidir.
- Yüksek performanslı, yük dengeli gRPC çağrıları ara sunucu gereksinimini ortadan kaldırır.
Ek kaynaklar
ASP.NET Core