GoSuda

Próbálja ki a Go szerver futtatását bővíthető módon a dotnet aspire-ben

By snowmerak
views ...

dotnet aspire?

A dotnet aspire egy olyan eszköz, amelyet a felhőnatív környezetek terjedésével hoztak létre, hogy segítse a fejlesztőket a felhőnatív fejlesztésben és konfigurációban. Ez az eszköz lehetővé teszi a .NET fejlesztők számára, hogy könnyen telepíthessenek .NET projekteket, különféle felhőnatív infrastruktúrákat, valamint más nyelven írt szolgáltatásokat vagy konténereket.

Természetesen a docker-től a k8s-ig terjedően kiadható és üzemeltethető, a meglévő on-premise környezetekből pedig meglehetősen sok terület, iparág és fejlesztő tér át a felhőnatív környezetbe, vagy már át is tért. Ez már egy érett terület. Ezért azt gondolom, hogy nem szükséges elmagyarázni a hosztnevek, portkonfigurációk, tűzfalak és metrikák kezelésének korábbi kényelmetlenségeit.

Ezért a fenti leírások alapján azonnal nem fogja megérteni, hogy mi is a dotnet aspire. Ugyanis a Microsoft sem határozta meg pontosan. Ezért én sem fogok különösebb definíciót adni. Azonban ebben a bejegyzésben a dotnet aspire általam értelmezett alapvető funkcióit fogom használni, ezért kérem, ezt figyelembe véve alakítsa ki saját álláspontját.

Projekt konfiguráció

dotnet aspire projekt létrehozása

Ha nincs dotnet aspire sablon, akkor először a sablont kell telepítenie. Telepítse a sablont a következő paranccsal. Ha nincs .net, akkor azt saját maga telepítse.

1dotnet new install Aspire.ProjectTemplates

Majd hozzon létre egy új megoldást egy megfelelő mappában.

1dotnet new sln

Ezután a megoldás mappájában futtassa a következő parancsot az aspire-apphost sablon projektjének létrehozásához.

1dotnet new aspire-apphost -o AppHost

Ezzel létrejön egy aspire-apphost projekt, amely csak egy egyszerű kódot tartalmaz a beállításhoz.

Valkey hozzáadása

Akkor egyszerűen adjunk hozzá egy Valkey-t.

Mielőtt hozzáadnánk, a dotnet aspire community hostingon keresztül különféle harmadik féltől származó megoldásokat kínál.
Természetesen a valkey is részesülhet a közösségi hosting támogatásában, és a következő nuget csomaggal könnyen használható.

1dotnet add package Aspire.Hosting.Valkey

Emellett különféle integrált hostingot is kínál, melyeket itt tekinthet meg.
Visszatérve a valkeyhez, nyissa meg a Program.cs fájlt az AppHost projektben, és módosítsa a következőképpen.

1var builder = DistributedApplication.CreateBuilder(args);
2
3var cache = builder.AddValkey("cache")
4    .WithDataVolume(isReadOnly: false)
5    .WithPersistence(interval: TimeSpan.FromMinutes(5),
6        keysChangedThreshold: 100);
7
8builder.Build().Run();

A cache egy IResourceBuilder interfész implementációja, amely információkat tartalmaz a valkey szolgáltatás létrehozásához.
A WithDataVolume egy olyan kötetet hoz létre, amelyben a gyorsítótár adatai tárolódnak, a WithPersistence pedig lehetővé teszi a gyorsítótár adatainak folyamatos tárolását.
Eddig úgy tűnik, hogy a docker-compose volumes funkciójához hasonlót látunk.
Természetesen ezt Önök is könnyen létrehozhatják.
Azonban ez a bejegyzés hatókörén kívül esik, ezért most nem fogok erről beszélni.

Go nyelvű echo szerver létrehozása

Akkor adjunk hozzá egy egyszerű Go nyelvű szervert.
Először is hozzon létre egy munkaterületet a go work init paranccsal a megoldás mappájában.
A .NET fejlesztők számára a Go munkaterület hasonló a megoldáshoz.

Ezután hozzon létre egy EchoServer nevű mappát, lépjen be oda, majd futtassa a go mod init EchoServer parancsot.
Ezzel a paranccsal egy Go modult hoz létre. A modul a .NET fejlesztők számára a projekthez hasonlóként értelmezhető.
Ezután hozza létre a main.go fájlt, és írja bele a következőket.

 1package main
 2
 3import (
 4	"log"
 5	"net/http"
 6	"os"
 7)
 8
 9func main() {
10	addr := os.Getenv("PORT")
11	log.Printf("Server started on %s", addr)
12
13	http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
14		name := request.URL.Query().Get("name")
15		writer.Write([]byte("Hello, " + name))
16	})
17
18	http.ListenAndServe(":"+addr, nil)
19}

Ez a szerver az Aspire AppHost futtatásakor, a PORT környezeti változót, amelyen hallgatnia kell, átadja, majd beolvassa ezt a portot és elindítja a szervert.
Egyszerűen megkapja a name lekérdezést, és visszaadja a Hello, {name}-t.

Most adjuk hozzá ezt a szervert a dotnet aspire-hoz.

Echo szerver hozzáadása az aspire-hoz

Menjen vissza az Aspire AppHost projekthez, ahova a Valkey-t is hozzáadta, és adja hozzá a Go nyelvű közösségi hostingot.

1dotnet add package CommunityToolkit.Aspire.Hosting.Golang

Ezután nyissa meg a Program.cs fájlt, és adja hozzá a következő kódot.

 1var builder = DistributedApplication.CreateBuilder(args);
 2
 3var cache = builder.AddValkey("cache")
 4    .WithDataVolume(isReadOnly: false)
 5    .WithPersistence(interval: TimeSpan.FromMinutes(5),
 6        keysChangedThreshold: 100);
 7
 8var echoServer = builder.AddGolangApp("echo-server", "../EchoServer")
 9    .WithHttpEndpoint(port: 3000, env: "PORT")
10    .WithExternalHttpEndpoints();
11
12builder.Build().Run();

Itt az echoServer egy IResourceBuilder interfész implementációja, amely információkat tartalmaz a Go nyelvű szerver létrehozásához.
Az imént hozzáadott AddGolangApp metódus egy egyéni gazdagép bővítő metódusa a Go nyelvű szerver hozzáadásához.
Fixen a 3000-es portot használja, és a PORT környezeti változót adja át, amint látható.
Végül a WithExternalHttpEndpoints teszi lehetővé a külső hozzáférést.

A teszteléshez, ha a http://localhost:3000/?name=world-re navigál, akkor a Hello, world kell, hogy megjelenjen.

Azonban a dotnet aspire-ban jelenleg egy komoly büntetés sújtja a nem .NET projekteket.
Ez pedig...

Projekt kiterjesztése

Akkor hogyan történik a horizontális skálázás?

A dotnet aspire jelenleg csak az AddProject metódussal hozzáadott .NET projektek builder-eihez biztosítja a WithReplica opciót.
Azonban a Go nyelvű gazdagépek vagy az AddContainer típusú külső projektek esetében nem kínálja ezt az opciót.

Ezért külön terheléselosztót vagy fordított proxyt kell használnia a közvetlen megvalósításhoz.
De mivel ez a fordított proxy egyetlen hibaforrássá válhat, a fordított proxy számára is jó lenne a WithReplica opció.
Akkor elkerülhetetlen, hogy a fordított proxy .NET projekt legyen.

Eddig az nginx, trafik, direkt implementáció és más módszerekkel kezeltük a problémát, de mivel a .NET projekt korlátozás bejött, hirtelen nem volt megoldás a kezemben.
Ezért kerestem egy .NET-tel megvalósított fordított proxyt, és szerencsére ott volt a YARP választási lehetőség.
A YARP egy .NET-tel megvalósított fordított proxy, amely képes terheléselosztóként is működni, és számos funkciót kínált, ezért jó választásnak ítéltem.

Akkor most adjuk hozzá a YARP-t.

Fordított proxy konfigurálása a YARP-pel

Először hozzon létre egy projektet a YARP használatához.

1dotnet new web -n ReverseProxy

Ezután lépjen be a projektbe, és telepítse a YARP-ot.

1dotnet add package Yarp.ReverseProxy --version 2.2.0

A telepítés befejezése után nyissa meg a Program.cs fájlt, és írja bele a következőket.

 1using Yarp.ReverseProxy.Configuration;
 2
 3var builder = WebApplication.CreateBuilder(args);
 4
 5var routes = new List<RouteConfig>();
 6var clusters = new List<ClusterConfig>();
 7
 8builder.Services.AddReverseProxy()
 9    .LoadFromMemory(routes, clusters);
10
11var app = builder.Build();
12
13app.MapReverseProxy();
14app.Run(url: $"http://0.0.0.0:{Environment.GetEnvironmentVariable("PORT") ?? "5000"}");

Ez a kód a YARP használatának alapvető kódja.
A routes a fordított proxy által használt útvonalinformációkat, a clusters pedig a fordított proxy által használt klaszterinformációkat tartalmazza.
Ezek az információk a LoadFromMemory metódussal kerülnek betöltésre a fordított proxyba.
Végül a MapReverseProxy metódussal leképezi és elindítja a fordított proxyt.

A tényleges használathoz adjon hozzá egy hivatkozást a fordított proxy projektre az aspire apphost projektben, majd adja hozzá és módosítsa a következő kódot a Program.cs fájlban.

1dotnet add reference ../ReverseProxy
1var echoServer = builder.AddGolangApp("echo-server", "../EchoServer")
2    .WithHttpEndpoint(env: "PORT");
3
4var reverseProxy = builder.AddProject<Projects.ReverseProxy>("gateway")
5    .WithReference(echoServer)
6    .WithHttpEndpoint(port: 3000, env: "PORT", isProxied: true)
7    .WithExternalHttpEndpoints();

Most a fordított proxy hivatkozhat az echo szerverre.
A kívülről érkező kéréseket a fordított proxy fogadja, és továbbítja az echo szervernek.

Fordított proxy módosítása

Először is módosítania kell a fordított proxyhoz rendelt projekt figyelési címét.
Távolítsa el az applicationUrl-t a Properties/launchSettings.json fájlon belül.
Ezután nyissa meg a Program.cs fájlt, és módosítsa alapvetően az alábbiak szerint.

 1using Yarp.ReverseProxy.Configuration;
 2
 3var builder = WebApplication.CreateBuilder(args);
 4
 5var routes = new List<RouteConfig>
 6{
 7    new RouteConfig
 8    {
 9        ClusterId = "cluster-echo",
10        RouteId = "route-echo",
11        Match = new RouteMatch
12        {
13            Path = "/"
14        }
15    }
16};
17
18var echoServerAddr = Environment.GetEnvironmentVariable("services__echo-server__http__0") ?? "http://localhost:8080";
19
20var clusters = new List<ClusterConfig>
21{
22    new ClusterConfig
23    {
24        ClusterId = "cluster-echo",
25        Destinations = new Dictionary<string, DestinationConfig>
26        {
27            { "destination-echo", new DestinationConfig { Address = echoServerAddr } }
28        }
29    }
30};
31
32builder.Services.AddReverseProxy()
33    .LoadFromMemory(routes, clusters);
34
35var app = builder.Build();
36
37app.MapReverseProxy();
38app.Run(url: $"http://0.0.0.0:{Environment.GetEnvironmentVariable("PORT") ?? "5000"}");

Először is módosítsa az routes és clusters információit.
Adjon hozzá egy echo-route-ot és egy echo-cluster-t, hogy a kéréseket az echo szerverre küldje.
Ezután módosítsa az echo szerver címét, hogy környezeti változóból olvassa be.

Ennek a címnek a szabálya: services__{service-name}__http__{index}.
Az echo szerver esetében a szolgáltatás neve echo-server, és mivel egyetlen példányról van szó, az indexhez a 0 -t használja.
Ha hozzáad egy asp .net core szervert, akkor több példány is létrehozható a WithReplica segítségével, így az index növelhető.
A http://localhost:8080 kivételkezelése egy értelmetlen szemét érték.

Most, hogy elindítja a projektet, és a http://localhost:3000/?name=world címre navigál, a Hello, world jelenik meg.

Bővítési ötlet

Most már ellenőriztük, hogy hozzáadtunk egy Go szervert a dotnet aspire-hoz, és a fordított proxy továbbítja a kéréseket.
Akkor most ezt a folyamatot programozható módon is ki tudjuk terjeszteni.
Például, ha egy számozást ad az echo szerver szolgáltatásneve után, több példányt hozhat létre, és automatikusan hozzáadhatja a fordított proxy konfigurációjához.

Módosítsa a fordított proxyt és az echo szervert használó kódot az aspire apphost projekt Program.cs fájljában az alábbiak szerint.

 1var reverseProxy = builder.AddProject<Projects.ReverseProxy>("gateway")
 2    .WithHttpEndpoint(port: 3000, env: "PORT", isProxied: true)
 3    .WithExternalHttpEndpoints();
 4
 5for (var i = 0; i < 8; i++)
 6{
 7    var echoServer = builder.AddGolangApp($"echo-server-{i}", "../EchoServer")
 8        .WithHttpEndpoint(env: "PORT");
 9    reverseProxy.WithReference(echoServer);
10}

Ezután módosítsa a fordított proxy projekt Program.cs fájlját az alábbiak szerint.

 1var echoServerDestinations = new Dictionary<string, DestinationConfig>();
 2for (var i = 0; i < 8; i++)
 3{
 4    echoServerDestinations[$"destination-{i}"] = new DestinationConfig
 5    {
 6        Address = Environment.GetEnvironmentVariable($"services__echo-server-{i}__http__0") ?? "http://localhost:8080"
 7    };
 8}
 9
10var clusters = new List<ClusterConfig>
11{
12    new ClusterConfig
13    {
14        ClusterId = "cluster-echo",
15        Destinations = echoServerDestinations
16    }
17};

Adjon hozzá egy célhely konfigurációt a 8-ra bővített echo szerver példányhoz.
Most a fordított proxy rendelkezik a megnövekedett számú echo szerver célhely információival, és továbbíthatja a kéréseket.
Ha most a http://localhost:3000/?name=world címre navigál, továbbra is a Hello, world jelenik meg.

Összegzés

Ebben a bejegyzésben elmagyaráztam, hogyan kell Go szervert hozzáadni a dotnet aspire-hoz, és hogyan kell a kéréseket a fordított proxy segítségével továbbítani.
A bővítés tekintetében azonban még nem írtam le teljesen, és egy külön repoban helyeztem el a környezeti változókon keresztül programozhatóbb megvalósítást bemutató példákat.
A részletes projektkonfigurációért és kódért tekintse meg a snowmerak/AspireStartPack oldalt.

Én személy szerint remélem, hogy a dotnet aspire a docker compose alternatívájaként, és felhőtelepítési eszközként is képes lesz betölteni a saját szerepét.
Mivel már létezik egy generátor, amely docker compose vagy k8s manifesztet generál, azt gondolom, hogy az átlagos fejlesztők számára a hozzáférés az infrastrukturális eszközökhöz könnyebbé vált.