GoSuda

Kokeillaan Go-palvelimen suorittamista skaalautuvasti dotnet aspire -ympäristössä

By snowmerak
views ...

dotnet aspire?

dotnet aspire on työkalu, joka on kehitetty auttamaan kehittäjiä pilvipohjaisessa kehityksessä ja konfiguroinnissa pilvipohjaisten ympäristöjen yleistyessä. Tämä työkalu mahdollistaa .NET-kehittäjille .NET-projektien ja erilaisten pilvipohjaisten infrastruktuurien sekä muiden kielten palveluiden ja konttien helpon käyttöönoton.

On itsestään selvää, että se julkaistaan ja toimii Dockerista k8s:ään, ja että merkittävä määrä aloja, teollisuudenaloja ja kehittäjiä on siirtymässä ja on jo siirtynyt pilvipohjaisiin ympäristöihin perinteisistä on-premise-ympäristöistä. Se on nyt kypsä ala. Siksi en usko, että on tarpeen selittää aiemmin esiintyneitä hankaluuksia liittyen isäntänimiin, porttien konfiguraatioihin, palomuurihin ja mittareiden hallintaan.

Siksi, pelkästään yllä olevien selitysten perusteella, on erittäin vaikea ymmärtää, mikä dotnet aspire on. Koska Microsoftkaan ei ole antanut sille täsmällistä määritelmää. Siksi en myöskään anna sille erillistä määritelmää. Kuitenkin, koska tässä artikkelissa käytän dotnet aspiren perustoimintoja sellaisina kuin olen ne ymmärtänyt, voit viitata niihin ja muodostaa oman näkemyksesi.

Projektin rakenne

dotnet aspire -projektin luominen

Jos dotnet aspire -mallia ei ole, sinun on ensin asennettava malli. Asenna malli seuraavalla komennolla. Jos .net ei ole asennettu, asenna se itse.

1dotnet new install Aspire.ProjectTemplates

Luo sitten uusi ratkaisu sopivaan kansioon.

1dotnet new sln

Sen jälkeen suorita seuraava komento ratkaisukansiossa luodaksesi projektin aspire-apphost-mallista.

1dotnet new aspire-apphost -o AppHost

Tällöin luodaan aspire-apphost-projekti, jossa on vain yksinkertainen koodi asetuksia varten.

Valkey-lisäys

Lisätään sitten yksinkertaisesti Valkey.

Ennen kuin lisätään se, dotnet aspire tarjoaa erilaisia kolmannen osapuolen ratkaisuja yhteisöhostingin kautta. Tietenkin valkey voi myös hyötyä tästä yhteisöhostingin tuesta, ja sitä on helppo käyttää seuraavan NuGet-paketin avulla.

1dotnet add package Aspire.Hosting.Valkey

Se tarjoaa myös erilaisia muita integroituja hosting-ratkaisuja, jotka voit tarkistaa täältä. Palataan takaisin valkeyn pariin ja avataan AppHost-projektin Program.cs-tiedosto ja muokataan sitä seuraavasti.

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();

cache on IResourceBuilder-rajapinnan toteutus, jolla on tiedot valkey-palvelun rakentamiseksi.WithDataVolume luo tallennusvolyymin välimuistidatan tallentamiseksi ja WithPersistence mahdollistaa välimuistidatan pysyvän tallentamisen. Tähän asti tämä näyttää suorittavan samanlaista roolia kuin docker-composen volumes. On itsestään selvää, että myös sinä voisit tehdä tämän helposti. Mutta koska tämä ylittää tämän artikkelin laajuuden, en käsittele sitä nyt.

Go-kielinen ekopalvelimen luominen

Lisätään sitten yksinkertainen Go-kielinen palvelin. Luo ensin työtila komennolla go work init ratkaisukansiossa. .NET-kehittäjille Go-työtila on samankaltainen kuin ratkaisu.

Luo sitten kansio nimeltä EchoServer, siirry sen sisään ja suorita komento go mod init EchoServer. Tämä komento luo Go-moduulin. Moduuli on .NET-kehittäjille samankaltainen kuin projekti. Luo sitten main.go-tiedosto ja kirjoita siihen seuraava koodi.

 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}

Tämä palvelin lukee PORT-ympäristömuuttujan, joka annetaan, kun Aspire AppHost käynnistetään, ja suorittaa palvelimen kyseisessä portissa. Se on yksinkertainen palvelin, joka vastaanottaa name-kyselyn ja palauttaa Hello, {name}.

Lisätään tämä palvelin nyt dotnet aspireen.

Ekopalvelimen lisääminen aspireen

Siirry takaisin Aspire AppHost -projektiin, johon lisäsit Valkeyn, ja lisää yhteisöhosting Go-kielelle.

1dotnet add package CommunityToolkit.Aspire.Hosting.Golang

Avaa sitten Program.cs-tiedosto ja lisää seuraava lauseke.

 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();

Tässä echoServer on IResourceBuilder-rajapinnan toteutus, jolla on tiedot Go-kielisen palvelimen rakentamiseksi. Juuri lisätty AddGolangApp-metodi on mukautetun isännän laajennusmetodi Go-kielisen palvelimen lisäämiseksi. Se käyttää oletuksena porttia 3000 ja antaa PORT-ympäristömuuttujan. Lopuksi WithExternalHttpEndpoints mahdollistaa ulkoisen pääsyn.

Jos testaat sitä käyttämällä osoitetta http://localhost:3000/?name=world, näet, että Hello, world tulostuu.

Tällä hetkellä dotnet aspirella on kuitenkin merkittävä haitta ei-.net-projekteille. Se on...

Projektin laajennus

Miten sitten horisontaalinen skaalaus tehdään?

Tällä hetkellä dotnet aspire tarjoaa WithReplica-vaihtoehdon vain AddProject-metodilla lisättyjen .NET-projektien rakentajille. Mutta se ei tarjoa tätä vaihtoehtoa Go-kielisille isännille tai ulkoisille projekteille, kuten AddContainer.

Siksi sinun on toteutettava se itse käyttämällä erillistä kuormituksen tasaajaa tai käänteisproxyä. Mutta jos näin tehdään, kyseinen käänteisproxy voi muodostaa SPOF:n, joten on suositeltavaa, että käänteisproxy tarjoaa WithReplica-vaihtoehdon. Silloin käänteisproxyn on välttämättä oltava .NET-projekti.

Olen tähän asti käyttänyt menetelmiä, kuten nginx, trafik ja oma toteutus, mutta kun .NET-projekti on rajoitettu, en löytänyt heti ratkaisua. Siksi etsin .NET:illä toteutettua käänteisproxyä ja onneksi löysin vaihtoehdon nimeltä YARP. YARP on .NET:illä toteutettu käänteisproxy, joka voi toimia myös kuormituksen tasaajana ja tarjosi monia ominaisuuksia, joten se oli hyvä valinta.

Lisätään nyt YARP.

Käänteisproxyn määrittäminen YARP:llä

Luo ensin projekti YARP:n käyttöä varten.

1dotnet new web -n ReverseProxy

Siirry sitten projektiin ja asenna YARP.

1dotnet add package Yarp.ReverseProxy --version 2.2.0

Kun asennus on valmis, avaa Program.cs-tiedosto ja kirjoita siihen seuraava koodi.

 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"}");

Tämä on peruskoodi YARP:n käyttöä varten.routes sisältää käänteisproxyn käyttämät reititystiedot ja clusters sisältää käänteisproxyn käyttämät klusteritiedot. Nämä tiedot ladataan käänteisproxyyn LoadFromMemory-metodilla. Lopuksi käänteisproxy kartoitetaan ja suoritetaan MapReverseProxy-metodilla.

Ja käytännön käyttöä varten lisää viittaus käänteisproxyprojektiin aspire-apphost-projektissa ja lisää ja muokkaa seuraavaa lauseketta Program.cs-tiedostossa.

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();

Nyt käänteisproxy voi viitata ekopalvelimeen. Ulkoapäin tulevat pyynnöt vastaanotetaan käänteisproksyssä ja ohjataan ekopalvelimelle.

Käänteisproxyn muokkaus

Ensinnäkin on muutettava käänteisproxylle allokoidun projektin kuunteluosoitetta. Poista applicationUrl tiedoston Properties/launchSettings.json sisältä. Avaa sitten Program.cs-tiedosto ja muokkaa sitä laajasti seuraavasti.

 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"}");

Muokkaa ensin routes- ja clusters-tiedot. Lisää echo-route ja echo-cluster, jotta pyynnöt lähetetään ekopalvelimelle. Muuta myös ekopalvelimen osoite luettavaksi ympäristömuuttujasta.

Tämän osoitteen sääntö on services__{palvelun-nimi}__http__{indeksi}. Ekopalvelimen tapauksessa palvelun nimi on echo-server ja koska se on yksittäinen instanssi, indeksinä käytetään 0:aa. Jos lisäät asp .net core -palvelimen, useita instansseja voidaan luoda WithReplica-vaihtoehdolla, joten indeksiä voidaan kasvattaa. Poikkeuksellinen http://localhost:8080 on hyödytön roska-arvo.

Kun olet suorittanut projektin ja siirryt osoitteeseen http://localhost:3000/?name=world, näet edelleen Hello, world tulostuvan.

Laajennusideoita

Nyt olemme vahvistaneet, että voimme lisätä Go-palvelimen dotnet aspireen ja välittää pyynnöt käänteisproxyn kautta. Voimme nyt laajentaa tämän prosessin ohjelmalliseksi. Voimme esimerkiksi luoda useita instansseja lisäämällä numeron ekopalvelimen palvelunimen perään ja lisätä automaattisesti asetukset käänteisproxyyn.

Muokkaa seuraavaa koodia aspire apphost -projektin Program.cs-tiedostossa, joka käyttää käänteisproxyä ja ekopalvelinta.

 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}

Muokkaa sitten käänteisproxyprojektin Program.cs-tiedostoa seuraavasti.

 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};

Lisää kohdeasetukset 8:lle ekopalvelininstanssille. Nyt käänteisproxyllä on kohdetiedot lisätyille ekopalvelimille, ja se voi välittää pyynnöt. Kun olet yhdistänyt osoitteeseen http://localhost:3000/?name=world, näet edelleen Hello, world tulostuvan.

Lopuksi

Tässä artikkelissa on selitetty, kuinka Go-palvelin lisätään dotnet aspireen ja kuinka pyynnöt välitetään käänteisproxyn kautta. Laajennuksen osalta en ole vielä kirjoittanut kaikkea, ja olen kirjoittanut esimerkin, jonka avulla ympäristömuuttujien avulla voidaan toteuttaa ohjelmallisemmin erillisessä repossa. Lisätietoja projektin rakenteesta ja koodista on snowmerak/AspireStartPack.

Henkilökohtaisesti odotan, että dotnet aspire pystyy suorittamaan oman roolinsa vaihtoehtona docker composelle ja pilvipalvelujen käyttöönoton työkaluna. Olemassa on jo generaattori, joka luo docker composen tai k8s manifestin, joten uskon, että tavallisen kehittäjän pääsy infrastruktuurityökaluihin on parantunut.