Megosztás a következőn keresztül:


Teljesítménnyel kapcsolatos ajánlott eljárások a gRPC-vel

Jegyzet

Ez nem a cikk legújabb verziója. A jelen cikk .NET 9-es verzióját lásd az aktuális kiadásért .

Figyelmeztetés

A ASP.NET Core ezen verziója már nem támogatott. További információ: .NET és .NET Core támogatási szabályzat. A jelen cikk .NET 9-es verzióját lásd az aktuális kiadásért .

Fontos

Ezek az információk egy olyan előzetes termékre vonatkoznak, amelyet a kereskedelmi forgalomba kerülés előtt jelentősen módosíthatnak. A Microsoft nem vállal kifejezett vagy hallgatólagos szavatosságot az itt megadott információkra vonatkozóan.

A jelen cikk .NET 9-es verzióját lásd az aktuális kiadásért .

Írta: James Newton-King

A gRPC nagy teljesítményű szolgáltatásokhoz készült. Ez a dokumentum bemutatja, hogyan lehet a lehető legjobb teljesítményt elérni a gRPC-ből.

GRPC-csatornák újrafelhasználása

A gRPC-csatornákat gRPC-hívások esetén újra fel kell használni. A csatornák újrafelhasználásával a hívások egy meglévő HTTP/2-kapcsolaton keresztül multiplexelhetők.

Ha minden gRPC-híváshoz új csatorna jön létre, akkor a befejezéshez szükséges idő jelentősen megnőhet. Minden híváshoz több hálózati körút szükséges az ügyfél és a kiszolgáló között egy új HTTP/2-kapcsolat létrehozásához:

  1. Csatlakozó megnyitása
  2. TCP-kapcsolat létrehozása
  3. TLS kapcsolat kialakítása
  4. HTTP/2 kapcsolat indítása
  5. GRPC-hívás indítása

A csatornák biztonságosan megoszthatók és újra felhasználhatók a gRPC-hívások között:

  • A gRPC klienseket csatornák segítségével hozzák létre. A gRPC-ügyfelek könnyű objektumok, nem szükséges őket gyorsítótárban tárolni vagy újra felhasználni.
  • Egy csatornáról több gRPC-ügyfél is létrehozható, beleértve a különböző típusú ügyfeleket is.
  • Több szál is biztonságosan használhatja a csatornát és az abból létrehozott klienseket.
  • A csatornáról létrehozott ügyfelek több egyidejű hívást is kezdeményezhetnek.

A gRPC-ügyfél-előállító központosított módot kínál a csatornák konfigurálására. Automatikusan újra felhasználja a mögöttes csatornákat. További információért lásd: gRPC-ügyfélgyár integrációja a .NET-ben.

Kapcsolat párhuzamossága

A HTTP/2-kapcsolatok általában korlátozzák a kapcsolaton egyszerre egyidejű streamek (aktív HTTP-kérések) maximális számát. Alapértelmezés szerint a legtöbb kiszolgáló ezt a korlátot 100 egyidejű streamre állítja be.

A gRPC-csatornák egyetlen HTTP/2 kapcsolatot használnak, és az egyidejű hívások multiplexáltak ezen a kapcsolaton. Amikor az aktív hívások száma eléri a kapcsolat streamkorlátját, a rendszer további hívásokat is várólistára állít az ügyfélben. A várakozó hívások megvárják, amíg az aktív hívások befejeződnek, mielőtt továbbítják őket. A nagy terhelésű vagy hosszú ideig futó streamelési gRPC-hívásokkal rendelkező alkalmazások teljesítményproblémákat tapasztalhatnak, amelyeket a hívások sorban állása okoz a korlát miatt.

A .NET 5 bemutatja a SocketsHttpHandler.EnableMultipleHttp2Connections tulajdonságot. Ha trueértékre van állítva, a csatorna további HTTP/2-kapcsolatokat hoz létre az egyidejű streamkorlát elérésekor. A GrpcChannel létrehozásakor a belső SocketsHttpHandler automatikusan további HTTP/2-kapcsolatok létrehozására van konfigurálva. Ha egy alkalmazás saját kezelőt konfigurál, fontolja meg a EnableMultipleHttp2Connectionstruebeállítását:

var channel = GrpcChannel.ForAddress("https://localhost", new GrpcChannelOptions
{
    HttpHandler = new SocketsHttpHandler
    {
        EnableMultipleHttp2Connections = true,

        // ...configure other handler settings
    }
});

A gRPC-hívásokat kezdeményező .NET-keretrendszeralkalmazásokat WinHttpHandlerhasználatára kell konfigurálni. A .NET-keretrendszeralkalmazások a WinHttpHandler.EnableMultipleHttp2Connections tulajdonságot true értékre állíthatják további kapcsolatok létrehozásához.

A .NET Core 3.1-alkalmazásokhoz számos áthidaló megoldás érhető el:

  • Hozzon létre külön gRPC-csatornákat az alkalmazás nagy terhelésű területeihez. Előfordulhat például, hogy a Logger gRPC szolgáltatás nagy terheléssel rendelkezik. Hozzon létre egy külön csatornát az alkalmazásban a LoggerClient számára.
  • Használjon gRPC-csatornák készletét, például hozzon létre egy listát a gRPC-csatornákról. Random minden alkalommal, amikor gRPC-csatornára van szükség, kiválaszt egy csatornát a listából. A Random véletlenszerűen osztja el a hívásokat több kapcsolaton keresztül.

Fontos

A probléma megoldásához egy másik módszer a kiszolgáló egyidejű streamkorlátjának növelése. A Kestrel ezzel van konfigurálva: MaxStreamsPerConnection.

Az egyidejű stream maximális korlátjának növelése nem ajánlott. Egy HTTP/2-kapcsolat túl sok streamje új teljesítményproblémákat vezet be:

  • A kapcsolatra írni próbáló streamek közötti ütközés.
  • A kapcsolati csomagvesztés miatt az összes hívás blokkolva lesz a TCP-rétegben.

ServerGarbageCollection ügyfélalkalmazásokban

A .NET szemétgyűjtőnek két módja van: a munkaállomás szemétgyűjtése (GC) és a kiszolgálói szemétgyűjtés. Mindegyik különböző számítási feladatokhoz van hangolva. ASP.NET Core-alkalmazások alapértelmezés szerint kiszolgálói GC-t használnak.

A magas egyidejűségű alkalmazások általában jobban teljesítenek a kiszolgálói GC-vel. Ha egy gRPC-ügyfélalkalmazás egyszerre nagy számú gRPC-hívást küld és fogad, akkor az alkalmazás kiszolgálói GC használatára való frissítésének teljesítménybeli előnye lehet.

A szerver Garbage Collector (GC) engedélyezéséhez állítsa be a <ServerGarbageCollection> az alkalmazás projektfájljában:

<PropertyGroup>
  <ServerGarbageCollection>true</ServerGarbageCollection>
</PropertyGroup>

További információ a szemétgyűjtésről: Munkaállomás és kiszolgáló szemétgyűjtési.

Jegyzet

ASP.NET Core-alkalmazások alapértelmezés szerint kiszolgálói GC-t használnak. A <ServerGarbageCollection> engedélyezése csak a nem kiszolgálói gRPC-ügyfélalkalmazásokban hasznos, például egy gRPC-ügyfélkonzol-alkalmazásban.

Aszinkron hívások az ügyfélalkalmazásokban

Inkább aszinkron programozást használjon aszinkronnal, és várja meg a gRPC-metódusok meghívásakor. Ha gRPC-hívásokat kezdeményez blokkolással, például Task.Result vagy Task.Wait()használatával, megakadályozza, hogy más feladatok használják a szálakat. Ez a szálkészlet éhezéséhez, teljesítményromláshoz vezethet, és az alkalmazás holtpontra juthat.

Minden gRPC-metódustípus aszinkron API-kat hoz létre a gRPC-ügyfeleken. A kivétel az unáris metódusok, amelyek aszinkron és blokkoló metódusokat generálnak.

Fontolja meg a következő gRPC szolgáltatást, amely egy .proto fájlban van definiálva:

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply);
}

A létrehozott GreeterClient típusa két .NET-metódussal rendelkezik a SayHellohívásához:

  • GreeterClient.SayHelloAsync – a Greeter.SayHello szolgáltatást aszinkron módon hívja meg. Lehet várni rá.
  • GreeterClient.SayHello – meghívja a Greeter.SayHello szolgáltatást, és blokkolja a folyamatot a befejezésig.

A blokkoló GreeterClient.SayHello metódus nem használható aszinkron kódban. Teljesítmény- és megbízhatósági problémákat okozhat.

Terheléselosztás

Egyes terheléselosztók nem működnek hatékonyan a gRPC-vel. Az L4 (átviteli) terheléselosztók kapcsolati szinten működnek a TCP-kapcsolatok végpontok közötti elosztásával. Ez a megközelítés jól működik a HTTP/1.1 használatával indított API-hívások terheléselosztásához. A HTTP/1.1 használatával egyidejűleg indított hívások különböző kapcsolatokon lesznek elküldve, így a hívások terhelése a végpontok között elosztható.

Mivel az L4 terheléselosztók kapcsolati szinten működnek, nem működnek jól a gRPC-vel. A gRPC HTTP/2-t használ, amely több hívást is multiplexel egyetlen TCP-kapcsolaton. A kapcsolaton keresztüli összes gRPC-hívás egy végpontra kerül.

A gRPC hatékony terheléselosztásának két lehetősége van:

  • Ügyféloldali terheléselosztás
  • L7 (alkalmazás) proxy terheléselosztása

Jegyzet

Csak a gRPC-hívások esetében lehet terheléselosztást végezni a végpontok között. Miután létrejött egy streamelési gRPC-hívás, a streamen keresztül küldött összes üzenet egy végpontra kerül.

Ügyféloldali terheléselosztás

Az ügyféloldali terheléselosztással az ügyfél ismeri a végpontokat. Minden gRPC-híváshoz kiválaszt egy másik végpontot a hívás elküldéséhez. Az ügyféloldali terheléselosztás akkor jó választás, ha fontos a késés. Az ügyfél és a szolgáltatás között nincs proxy, ezért a rendszer közvetlenül a szolgáltatásnak küldi a hívást. Az ügyféloldali terheléselosztás hátránya, hogy minden ügyfélnek nyomon kell követnie a használni kívánt elérhető végpontokat.

A Lookaside-ügyfél terheléselosztása egy olyan technika, amelyben a terheléselosztási állapot egy központi helyen van tárolva. Az ügyfelek rendszeres időközönként lekérdezik a központi helyet, hogy a terheléselosztási döntések meghozatalakor használandó információkat kereshessenek.

További információ: gRPC ügyféloldali terheléselosztási.

Proxy terhelés-kiegyenlítése

Az L7 (alkalmazás-) proxy magasabb szinten működik, mint egy L4 (átviteli) proxy. Az L7 proxyk megértik a HTTP/2-t. A proxy egy HTTP/2-kapcsolaton multiplexált gRPC-hívásokat fogad, és több háttérvégpont között osztja el őket. A proxy használata egyszerűbb, mint az ügyféloldali terheléselosztás, de további késést ad a gRPC-hívásokhoz.

Sok L7 proxy érhető el. Néhány lehetőség:

Folyamatközi kommunikáció

Az ügyfél és a szolgáltatás közötti gRPC-hívásokat általában TCP-szoftvercsatornákon keresztül küldik el. A TCP kiválóan alkalmas a hálózaton keresztüli kommunikációra, de folyamatközi kommunikáció (IPC) hatékonyabb, ha az ügyfél és a szolgáltatás ugyanazon a gépen van.

Fontolja meg egy olyan átvitel használatát, mint a Unix tartományi szoftvercsatornák vagy a nevesített csövek az ugyanazon a gépen lévő folyamatok közötti gRPC-hívásokhoz. További információ: GRPCfolyamatközi kommunikációja.

Életben tartó pingek

A http/2-kapcsolatok életben tartására szolgáló pingek az inaktivitás időszakában is használhatók. Ha egy meglévő HTTP/2-kapcsolat készen áll, amikor egy alkalmazás folytatja a tevékenységet, lehetővé teszi a kezdeti gRPC-hívások gyors indítását, a kapcsolat újbóli megnyitása által okozott késés nélkül.

Az életben tartás pingjei a SocketsHttpHandler-en vannak konfigurálva.

var handler = new SocketsHttpHandler
{
    PooledConnectionIdleTimeout = Timeout.InfiniteTimeSpan,
    KeepAlivePingDelay = TimeSpan.FromSeconds(60),
    KeepAlivePingTimeout = TimeSpan.FromSeconds(30),
    EnableMultipleHttp2Connections = true
};

var channel = GrpcChannel.ForAddress("https://localhost:5001", new GrpcChannelOptions
{
    HttpHandler = handler
});

Az előző kód konfigurál egy csatornát, amely 60 másodpercenként küld élő pinget a kiszolgálónak inaktivitási időszakokban. A pingelés biztosítja, hogy a kiszolgáló és a használatban lévő proxyk inaktivitás miatt ne zárják be a kapcsolatot.

Jegyzet

A pingelések csak a kapcsolat életben tartását segítik. Előfordulhat, hogy a kapcsolaton futó, hosszan futó gRPC-hívásokat a kiszolgáló vagy a közvetítő proxyk inaktivitás miatt továbbra is leálltathatják.

Áramlásvezérlés

A HTTP/2 folyamatvezérlés egy olyan funkció, amely megakadályozza, hogy az alkalmazások túlterheltek legyenek az adatokkal. Folyamatvezérlés használata esetén:

  • Minden HTTP/2 kapcsolat és kérés rendelkezik egy elérhető pufferablakkal. A pufferablak azt határozza meg, hogy az alkalmazás mennyi adatot fogadhat egyszerre.
  • A folyamatvezérlő aktiválódik, ha a pufferablak ki van töltve. Aktiváláskor a küldő alkalmazás szünetelteti a további adatok küldését.
  • Miután a fogadó alkalmazás feldolgozta az adatokat, a pufferablakban szabad hely áll rendelkezésre. A küldő alkalmazás folytatja az adatok küldését.

A folyamatvezérlés negatív hatással lehet a teljesítményre, ha nagy üzeneteket fogad. Ha a pufferablak kapacitása kisebb, mint a bejövő üzenetek hasznos adatainak mérete, vagy késés van az ügyfél és a kiszolgáló között, akkor az adatok szakaszos indítási és leállítási sorozatokban továbbíthatók.

A folyamatvezérlés teljesítményproblémái a pufferablak méretének növelésével javíthatók. Az alkalmazás indításakor a Kestrel-t InitialConnectionWindowSize és InitialStreamWindowSize segítségével konfigurálják.

builder.WebHost.ConfigureKestrel(options =>
{
    var http2 = options.Limits.Http2;
    http2.InitialConnectionWindowSize = 1024 * 1024 * 2; // 2 MB
    http2.InitialStreamWindowSize = 1024 * 1024; // 1 MB
});

Ajánlások:

  • Ha egy gRPC-szolgáltatás gyakran 768 KB-nál nagyobb üzeneteket fogad, Kestrela streamablak alapértelmezett méretét, akkor fontolja meg a kapcsolat és a streamablak méretének növelését.
  • A kapcsolati ablak méretének mindig egyenlőnek vagy nagyobbnak kell lennie, mint a streamablak mérete. A stream a kapcsolat része, és a feladót mindkettő korlátozza.

További információ a folyamatvezérlés működéséről: HTTP/2 folyamatvezérlés (blogbejegyzés).

Fontos

A Kestrelablakméretének növelése lehetővé teszi, hogy Kestrel több adatot puffereljen az alkalmazás nevében, ami esetleg növeli a memóriahasználatot. Ne konfiguráljon szükségtelenül nagy méretű ablakokat.

A streaming hívások zökkenőmentes befejezése

Próbálja meg elegánsan befejezni a streamelési hívásokat. A hívások kecses végrehajtása elkerüli a szükségtelen hibákat, és lehetővé teszi a kiszolgálók számára a belső adatstruktúrák kérések közötti újrafelhasználását.

A hívás akkor fejeződik be, ha az ügyfél és a kiszolgáló befejezte az üzenetek küldését, és a társ elolvasta az összes üzenetet.

Ügyfélkérés streamje:

  1. Az ügyfél befejezte az üzenetek írását a kérési folyamra, és a folyamatot lezárja call.RequestStream.CompleteAsync()-val.
  2. A kiszolgáló minden üzenetet beolvasott a kérelemstreamből. Az üzenetek olvasási módjától függően vagy a requestStream.MoveNext() visszatér false-ként, vagy a requestStream.ReadAllAsync() befejeződött.

Kiszolgáló válaszfolyama:

  1. A kiszolgáló befejezte az üzenetek írását a válaszfolyamba, és a kiszolgáló metódusa befejeződött.
  2. Az ügyfél elolvasta a válaszfolyam összes üzenetét. Az üzenetek olvasási módjától függően, vagy a call.ResponseStream.MoveNext() visszatér a false-hez, vagy a call.ResponseStream.ReadAllAsync() befejeződik.

A kétirányú streamelési hívások kecses végrehajtására példa: kétirányú streamelési hívás.

A kiszolgáló streamelési hívásai nem rendelkeznek kérések adatfolyamával. Ez azt jelenti, hogy az ügyfél csak úgy tud kommunikálni a kiszolgálóval, hogy a streamnek le kell állnia, ha megszakítja azt. Ha a megszakított hívások többletterhelése hatással van az alkalmazásra, fontolja meg, hogy a kiszolgáló streamelési hívását kétirányú streamelési hívásra módosítsa. Kétirányú streamelési hívás esetén a kérésfolyamot befejező ügyfél jelzés lehet a kiszolgálónak a hívás befejezéséhez.

Adatfolyam-hívások eltávolítása

Ha már nincs rájuk szükség, mindig dobja el a streamelési hívásokat. Az a típus, amelyet streamelési hívások indításakor adunk vissza, implementálja a IDisposable-t. Ha a hívásra már nincs szükség, akkor a rendszer leállítja, és az összes erőforrást megtisztítja.

Az alábbi példában a using deklaráció a AccumulateCount() hívás során gondoskodik arról, hogy mindig megfelelően megsemmisüljön, ha váratlan hiba történik.

var client = new Counter.CounterClient(channel);
using var call = client.AccumulateCount();

for (var i = 0; i < 3; i++)
{
    await call.RequestStream.WriteAsync(new CounterRequest { Count = 1 });
}
await call.RequestStream.CompleteAsync();

var response = await call;
Console.WriteLine($"Count: {response.Count}");
// Count: 3

Ideális esetben a streamelési hívásokat elegánsan kell befejezni. A hívás letiltása biztosítja, hogy az ügyfél és a kiszolgáló közötti HTTP-kérés váratlan hiba esetén megszakadjon. A véletlenül futó streamelési hívások nem csak a memóriát és az erőforrásokat szivárgják ki az ügyfélen, hanem a kiszolgálón is futnak. Sok kiszivárgott streamhívás befolyásolhatja az alkalmazás stabilitását.

Egy már sikeresen befejezett streamhívás törlése nem jár semmilyen negatív hatással.

Egyedi hívások cseréje streamelésre

A gRPC kétirányú streamelése használható az egyszeri gRPC-hívások helyett nagy teljesítményű helyzetekben. Ha egy kétirányú stream elindult, az üzenetek oda-vissza streamelése gyorsabb, mint az üzenetek küldése több egyirányú gRPC-hívással. A streamelt üzeneteket a rendszer egy meglévő HTTP/2-kérelem adataiként küldi el, és kiküszöböli az új HTTP/2-kérések létrehozásának többletterhelését minden egyes nem ütemezett híváshoz.

Példaszolgáltatás:

public override async Task SayHello(IAsyncStreamReader<HelloRequest> requestStream,
    IServerStreamWriter<HelloReply> responseStream, ServerCallContext context)
{
    await foreach (var request in requestStream.ReadAllAsync())
    {
        var helloReply = new HelloReply { Message = "Hello " + request.Name };

        await responseStream.WriteAsync(helloReply);
    }
}

Példaügyfél:

var client = new Greet.GreeterClient(channel);
using var call = client.SayHello();

Console.WriteLine("Type a name then press enter.");
while (true)
{
    var text = Console.ReadLine();

    // Send and receive messages over the stream
    await call.RequestStream.WriteAsync(new HelloRequest { Name = text });
    await call.ResponseStream.MoveNext();

    Console.WriteLine($"Greeting: {call.ResponseStream.Current.Message}");
}

A váratlan hívások kétirányú streamelésre való cseréje teljesítménybeli okokból speciális technika, és sok esetben nem megfelelő.

A streamelési hívások használata akkor jó választás, ha:

  1. Nagy átviteli sebességre vagy alacsony késésre van szükség.
  2. A gRPC és a HTTP/2 teljesítménybeli szűk keresztmetszetként van azonosítva.
  3. Az ügyfél egy munkatársa rendszeres üzeneteket küld vagy fogad egy gRPC-szolgáltatással.

Vegye figyelembe a folyamatos hívások használatával járó további összetettséget és korlátokat, szemben az unáris hívások egyszerűségével.

  1. A streameket szolgáltatás- vagy csatlakozási hiba szakíthatja meg. Hiba esetén logikára van szükség a stream újraindításához.
  2. RequestStream.WriteAsync nem biztonságos a többszálas használatra. Egyszerre csak egy üzenet írható streambe. Amikor üzeneteket küld több szálból egyetlen streamen keresztül, egy gyártói/fogyasztói üzenetsorra van szükség, például Channel<T> az üzenetek összeállításához.
  3. A gRPC-streamelési módszer egyetlen üzenettípus fogadására és egy üzenettípus küldésére korlátozódik. rpc StreamingCall(stream RequestMessage) returns (stream ResponseMessage) például RequestMessage kap, és ResponseMessageküld. A Protobuf által az ismeretlen vagy feltételes üzenetek Any és oneof használatával történő támogatása megkerülheti ezt a korlátozást.

Bináris terhek

A Protobuf támogatja a bináris adatterheléseket a bytes skaláris értéktípussal. A C#-ban létrehozott tulajdonság ByteString használ tulajdonságtípusként.

syntax = "proto3";

message PayloadResponse {
    bytes data = 1;
}  

A Protobuf egy bináris formátum, amely hatékonyan szerializálja a nagy bináris hasznos adatokat minimális többletterheléssel. A JSON-hoz hasonló szöveges formátumokban meg kell, hogy történjen a bájtok base64 kódolása, ami 33%-t ad hozzá az üzenet méretéhez.

Nagy ByteString terhelések kezelésénél az alábbiakban tárgyalt legjobb gyakorlatok segíthetnek elkerülni a felesleges másolatokat és memóriafoglalásokat.

Bináris adatcsomagok küldése

ByteString példányok általában ByteString.CopyFrom(byte[] data) használatával jönnek létre. Ez a módszer egy új ByteString és egy új byte[] foglal le. Az adatok át lesznek másolva az új bájttömbbe.

UnsafeByteOperations.UnsafeWrap(ReadOnlyMemory<byte> bytes) alkalmazásával elkerülhetők a plusz foglalatok és másolatok a ByteString példányok létrehozásakor.

var data = await File.ReadAllBytesAsync(path);

var payload = new PayloadResponse();
payload.Data = UnsafeByteOperations.UnsafeWrap(data);

A bájtok nem másolhatók UnsafeByteOperations.UnsafeWrap, ezért nem módosíthatók, amíg a ByteString használatban van.

UnsafeByteOperations.UnsafeWrap Google.Protobuf 3.15.0-s vagy újabb verzióját igényli.

Bináris adatfolyamok olvasása

Az adatok hatékonyan olvashatók ByteString példányokból ByteString.Memory és ByteString.Span tulajdonságok használatával.

var byteString = UnsafeByteOperations.UnsafeWrap(new byte[] { 0, 1, 2 });
var data = byteString.Span;

for (var i = 0; i < data.Length; i++)
{
    Console.WriteLine(data[i]);
}

Ezek a tulajdonságok lehetővé teszik, hogy a kód közvetlenül olvasson be adatokat egy ByteString-ból foglalások és másolatok nélkül.

A legtöbb .NET API ReadOnlyMemory<byte> és byte[] túlterhelt, ezért ByteString.Memory ajánlott a mögöttes adatok használata. Vannak azonban olyan körülmények, amikor egy alkalmazásnak bájttömbként kell lekérnie az adatokat. Ha bájttömbre van szüksége, akkor a MemoryMarshal.TryGetArray metódussal mind az adatok új másolatának kiosztása nélkül is kaphat egy tömböt egy ByteString-ból.

var byteString = GetByteString();

ByteArrayContent content;
if (MemoryMarshal.TryGetArray(byteString.Memory, out var segment))
{
    // Success. Use the ByteString's underlying array.
    content = new ByteArrayContent(segment.Array, segment.Offset, segment.Count);
}
else
{
    // TryGetArray didn't succeed. Fall back to creating a copy of the data with ToByteArray.
    content = new ByteArrayContent(byteString.ToByteArray());
}

var httpRequest = new HttpRequestMessage();
httpRequest.Content = content;

Az előző kód:

  • Kísérlet egy tömb lekérésére ByteString.Memory-ból a MemoryMarshal.TryGetArraysegítségével.
  • Használja az ArraySegment<byte>-t, ha az sikerült lekérni. A szegmens hivatkozik a tömbre, az eltolásra és a darabszámra.
  • Ellenkező esetben visszatér ahhoz, hogy egy új tömböt allokáljon ByteString.ToByteArray().

gRPC-szolgáltatások és nagy bináris terhelések

A gRPC és a Protobuf nagy bináris hasznos adatokat tud küldeni és fogadni. Bár a bináris Protobuf hatékonyabb, mint a szöveges JSON a bináris hasznos adatok szerializálásában, a nagy bináris hasznos adatok használatakor még mindig fontos teljesítményjellemzőket kell szem előtt tartani.

A gRPC egy üzenetalapú RPC-keretrendszer, amely a következőt jelenti:

  • A rendszer a teljes üzenetet betölti a memóriába, mielőtt a gRPC elküldené.
  • Az üzenet érkezésekor a rendszer a teljes üzenetet deszerializálja a memóriába.

A bináris terhelések bájttömbként vannak lefoglalva. Egy 10 MB-os bináris adat például 10 MB bájttömböt foglal le. A nagy bináris hasznos terhelésű üzenetek bájttömböket foglalhatnak el a nagy objektumhalmon. A nagy foglalások hatással vannak a kiszolgáló teljesítményére és méretezhetőségére.

Tanácsok nagy teljesítményű alkalmazások létrehozásához nagy mennyiségű bináris adattartalommal: