Aracılığıyla paylaş


gRPC istemci tarafı yük dengeleme

Not

Bu, bu makalenin en son sürümü değildir. Geçerli sürüm için bu makalenin .NET 9 sürümüne bakın.

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.

Önemli

Bu bilgiler, ticari olarak piyasaya sürülmeden önce önemli ölçüde değiştirilebilen bir yayın öncesi ürünle ilgilidir. Burada verilen bilgilerle ilgili olarak Microsoft açık veya zımni hiçbir garanti vermez.

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:

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.Clientyer 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 ile DnsResolverFactoryeş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 ve 127.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-hostyapılandırılır.
    • Şema dns ile DnsResolverFactoryeş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.
  • Yük dengeleyici belirtmez. Kanal varsayılan olarak ilk yük dengeleyiciyi seçer.
  • gRPC çağrısını SayHellobaşlatır:
    • DNS çözümleyicisi ana bilgisayar adı my-example-hostiç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 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 StaticResolverFactorysağ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 ve localhost: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üzen static , statik bir çözümleyiciye eşler.
    • DI hizmet sağlayıcısı ile ayarlar GrpcChannelOptions.ServiceProvider .

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.ServiceConfigbir 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ü destekleyip service config desteklemediği çözümleyici uygulamasına bağlıdır. bu özelliği ile GrpcChannelOptions.DisableResolverServiceConfigdevre dışı bırakın.
  • Hayır service config sağlanmışsa veya service config yük dengeleyici yapılandırılmamışsa, kanal varsayılan olarak olarak PickFirstLoadBalancerFactorykullanı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 configbir RoundRobinLoadBalancerFactory belirtir.
  • gRPC çağrısını SayHellobaşlatır:
    • DnsResolverFactory ana bilgisayar adı my-example-hostiç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. Bir https adrese eşdeğerdir.
  • ChannelCredentials.Insecure - gRPC çağrıları aktarım güvenliğini kullanmaz. Bir http 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ından ResolverFactoryoluş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 uygular ResolverFactory. Şemaya eşler file ve örnekler oluşturur FileResolver .
  • FileResolver uygular PollingResolver. PollingResolver , geçersiz kılarak ResolveAsynczaman 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.

Özel yük dengeleyici oluşturma

Yük dengeleyici:

  • LoadBalancer uygular ve tarafından LoadBalancerFactoryoluş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 SubchannelPickeroluşturur. Kanal, gRPC çağrıları yaparken adresleri seçmek için seçiciyi dahili olarak kullanır.

Şu SubchannelsLoadBalancer şekildedir:

  • uygulayan LoadBalancersoyut 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 uygular LoadBalancerFactory. İlke adıyla random eşler ve örnekler oluşturur RandomBalancer .
  • RandomBalancer uygular SubchannelsLoadBalancer. Rastgele bir RandomPicker 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.ServiceProviderkanala geçirilebilir.
  • Bir uygulama DI kullanmıyorsa aşağıdakini oluşturun:
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şik IServiceProvider olarak bulunur ve olarak GrpcChannelOptions.ServiceProviderayarlanır.
    • Kanal adresi şeklindedir file:///c:/data/addresses.json. Şema file ile FileResolverFactoryeşler.
    • service config yük dengeleyici adıdır random. RandomLoadBalancerFactoryile 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