ASP.NET Core აპლიკაცია GitHub-იდან ოთხ ნაბიჯად ეშვება: სერვერი repository-ს იწერს, dotnet publish პროექტს კომპილირებული შედეგის საქაღალდედ აქცევს, dotnet YourApp.dll Kestrel-ს უშვებს, ხოლო Kestrel უსმენს იმ პორტს, რომელიც ჰოსტმა მოგცა, ყველა ინტერფეისზე. თითქმის ყველა წარუმატებელი პირველი deploy ამ ოთხიდან ერთ-ერთია, ოდნავ არასწორად გაკეთებული - publish, რომელიც არასწორ პროექტს იღებს, start ბრძანება, რომელიც ბრუნდება ნაცვლად იმისა, რომ წინა პლანზე დარჩეს, ან Kestrel, რომელიც localhost:5000-ს უსმენს, რადგან სხვა არავინ უთხრა. ეს პოსტი თითოეულ ნაბიჯს იმ რიგით გადის, რომლითაც ისინი სრულდება, იმ პარამეტრებით, რომლებსაც მნიშვნელობა მხოლოდ მაშინ აქვს, როცა აპლიკაცია შენს ლეპტოპზე აღარ არის.
აქედან არაფერია ერთი ჰოსტისთვის სპეციფიკური. მაგალითებში გამოყენებულია პანელი Git deploy-ით და წინ მდგომი reverse proxy-ით, რადგან უმეტესი პატარა .NET აპლიკაცია სწორედ ასე მუშაობს, მაგრამ იგივე ბრძანებები VDS-ზეც მუშაობს systemd-ით.
როგორ უშვებს Git deploy .NET აპლიკაციას#
Git deploy არც მაგიაა და არც build pipeline. ეს არის clone (ან pull, შემდგომ deploy-ებზე) სერვერის ფაილურ სისტემაში, რასაც start ბრძანება მოსდევს. .NET პროექტისთვის ეს start ბრძანება ორ საქმეს აკეთებს: კოდს აგებს და შემდეგ უშვებს.
ამის მოწყობის ორი პატიოსანი გზა არსებობს და არჩევანი წყვეტს, რამდენ ხანს გაგრძელდება restart.
- აგება სერვერზე. start ბრძანება უშვებს
dotnet publish-ს და შემდეგ შედეგს. Git-ში კომპილირებული არაფერი ხვდება. ფასი ის არის, რომ ყოველი გაშვება - და არა მხოლოდ ყოველი deploy - restore-სა და კომპილაციას იხდის, რაც სწრაფ მანქანაზე 20 წამია, ხოლო ნახევარ ბირთვზე წუთი ან მეტი. - აგება CI-ში, გაშვება სერვერზე. GitHub Actions workflow აპლიკაციას publish-ს უკეთებს და შედეგს ცალკე ბრენჩში commit-ავს (დავარქვათ
deploy), ხოლო სერვერი ამ ბრენჩს მიჰყვება. start ბრძანება მხოლოდdotnet App.dll-ია. გაშვებები სწრაფია და სერვერს SDK-ის მეხსიერება არასოდეს სჭირდება, ფასად კი workflow ფაილის მოვლა გიჯდება.
ადამიანების უმეტესობამ პირველით უნდა დაიწყოს და მეორეზე გადავიდეს, როცა restart-ის დრო შეაწუხებს. ორივე ქვემოთაა აღწერილი.
რა სჭირდება repository-ს, სანამ deploy-ს შეძლებს#
.NET repository, რომელიც შენს მანქანაზე სუფთად იგება, სერვერზე მაინც შეიძლება ჩავარდეს, ჩვეულებრივ ერთ-ერთი ამ მიზეზით.
ერთზე მეტი პროექტია. dotnet publish არგუმენტის გარეშე მიმდინარე დირექტორიაში პროექტის ან solution ფაილს ეძებს. თუ root-ში არის .sln ვებ პროექტით, class library-ით და ტესტების პროექტით, solution-ის publish ყველა მათგანს ერთსა და იმავე საქაღალდეში აქვეყნებს და მიიღებ არეულობას ან შეცდომას იმაზე, რომ რამდენიმე პროექტი ერთსა და იმავე ფაილს წერს. დაასახელე ის პროექტი, რომელსაც გულისხმობ: dotnet publish src/Shop.Web/Shop.Web.csproj.
`bin` და `obj` commit-შია. ისინი იქ არ უნდა იყოს. commit-ში მოხვედრილი obj საქაღალდე შენი მანქანის restore მდგომარეობას ატარებს (შენი NuGet cache-ის აბსოლუტური გზების ჩათვლით), და სერვერზე build შემდეგ ისე ვარდება, რომ პაკეტების დაზიანებას ჰგავს. სტანდარტული dotnet new gitignore ორივეს გამორიცხავს.
SDK-ის ვერსია არ არის დაფიქსირებული. root-ში მდებარე global.json dotnet ბრძანებას ეუბნება, რომელი SDK გამოიყენოს:
{ "sdk": { "version": "10.0.100", "rollForward": "latestFeature" }}rollForward: latestFeature იღებს იმავე მთავარი ვერსიის ნებისმიერ უფრო ახალ feature band-ს, ამიტომ 10.0.100 ემთხვევა 10.0.2xx-საც. global.json-ის გარეშე შენს კოდს ყველაზე ახალი დაყენებული SDK აგებს, რაც ჩვეულებრივ კარგია. global.json-ით, რომელიც ასახელებს SDK-ს, რომელიც სერვერს არ აქვს, build ჩერდება შეტყობინებით "A compatible .NET SDK was not found" - ამიტომ დააფიქსირე ის მთავარი ვერსია, რომელსაც მიზნად ისახავ, და არა ზუსტი patch შენი ლეპტოპიდან. .NET-ის ვერსიები და LTS მხარდაჭერა განიხილავს, რომელ მთავარ ვერსიას უნდა დაუმიზნო.
პაკეტების ვერსიები ცურავს. თუ გინდა, რომ სერვერმა ზუსტად ის აღადგინოს, რაც გატესტე, ჩართე lock ფაილი. დაამატე პროექტში <RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>, commit გაუკეთე მის მიერ შექმნილ packages.lock.json-ს და სერვერზე restore გააკეთე --locked-mode-ით, რომელიც ჩავარდება და არა ჩუმად გადაწყვეტს რაღაც ახალს.
start ბრძანება#
start ბრძანება კონტეინერის ყოველ გაშვებაზე სრულდება და არა მხოლოდ push-ის შემდეგ. სერვერზე აგების მიდგომისთვის ის ასე გამოიყურება:
dotnet publish src/Shop.Web/Shop.Web.csproj -c Release -o out \ --disable-build-servers && exec dotnet out/Shop.Web.dllრას აკეთებს თითოეული ნაწილი:
-c Releaseაგებს ოპტიმიზაციებით. .NET 8-იდანdotnet publishნაგულისხმევად Release-ს იყენებს პროექტებისთვის, რომლებიც .NET 8-ს ან უფრო ახალს მიზნად ისახავს, მაგრამ მისი აშკარად დაწერა არაფერი ღირს და ძველ პროექტებს იცავს.-o outგამოქვეყნებულ ფაილებს ცნობილ საქაღალდეში ათავსებს. მის გარეშე ისინი ხვდებაbin/Release/net10.0/publish/-ში, გზაში, რომელიც target framework-ის შეცვლისას იცვლება.--disable-build-servers(SDK 7 და უფრო ახალი) აჩერებს MSBuild-სა და Roslyn-ის კომპილატორის სერვერს, რომ build-ის შემდეგ მეხსიერებაში არ დარჩნენ. დესკტოპზე ეს ფონური პროცესები შემდეგ build-ს აჩქარებს. 1 GB სერვერზე ისინი შენი აპლიკაციის გვერდით სხედან და რამდენიმე ასეულ მეგაბაიტ მეხსიერებას იკავებენ build-ისთვის, რომელიც შემდეგ restart-მდე აღარ მოხდება.execshell-ს .NET პროცესით ცვლის, ამიტომ პანელიდან გაჩერების სიგნალი პირდაპირ შენს აპლიკაციას აღწევს და მას სუფთად გამორთვა შეუძლია.
ბრძანება წინა პლანზე უნდა დარჩეს. სკრიპტი, რომელიც პროცესს ფონზე გადაიტანს, ან start ბრძანება, რომელიც მხოლოდ აგებს, დასრულებულ აპლიკაციას ჰგავს და ის ციკლში გადაიტვირთება.
CI-ში აგების მიდგომისთვის workflow GitHub runner-ზე აკეთებს publish-ს და შედეგის საქაღალდეს deploy ბრენჩში push-ავს, ხოლო start ბრძანება მცირდება exec dotnet Shop.Web.dll-მდე. restart-ებს მაშინ ერთი-ორი წამი სჭირდება. გაცვლა ის არის, რომ ბრენჩში გამოქვეყნებული შედეგი სერვერზე runtime-ს უნდა ემთხვეოდეს: .NET 10-ისთვის framework-dependent build-ს იქ .NET 10 runtime სჭირდება. dotnet publish და მისი runtime-ის პარამეტრები ხსნის framework-dependent და self-contained შედეგის განსხვავებას, რაც ამ დამოკიდებულებას აქრობს.
Kestrel, პორტი და ASPNETCORE_URLS#
Kestrel არის ASP.NET Core-ში ჩაშენებული ვებ სერვერი. ის სწრაფია, production-ისთვის ვარგისია და კონფიგურაციის გარეშე უსმენს http://localhost:5000-ს - რაც კონტეინერის შიგნით ნიშნავს, რომ კონტეინერის გარედან ვერავინ მიაღწევს. launchSettings.json ფაილს, რომელიც შენს ლოკალურ პორტებს ადგენს, მხოლოდ dotnet run და Visual Studio კითხულობს; dotnet App.dll-ით გაშვებული გამოქვეყნებული აპლიკაცია მას სრულად უგულებელყოფს.
შენს გეგმას აქვს პორტის allocation, რომელიც პანელში ჩანს, და აპლიკაციამ ამ პორტს ყველა ინტერფეისზე უნდა მოუსმინოს. Kestrel თავის მისამართებს რამდენიმე ადგილიდან კითხულობს, ამ პრიორიტეტის რიგით (გვიანდელი იმარჯვებს ადრინდელზე):
| წყარო | მაგალითი | შენიშვნა |
|---|---|---|
ASPNETCORE_HTTP_PORTS | 8080 | .NET 8 და უფრო ახალი. მხოლოდ პორტები, ყველა ინტერფეისი |
ASPNETCORE_URLS | http://0.0.0.0:8080 | სრული URL-ები; გადაფარავს პორტების ცვლადს |
--urls არგუმენტი | --urls http://0.0.0.0:8080 | გადაფარავს გარემოს |
Kestrel:Endpoints კონფიგურაციაში | appsettings.json | ცვლის ზემოთ მოცემულ URL პარამეტრებს |
Listen გამოძახებები კოდში | ListenAnyIP(port) | ასევე ცვლის URL პარამეტრებს |
პანელზე განთავსებული აპლიკაციისთვის ყველაზე მარტივი სწორი მოწყობა არის გარემოს ცვლადი Startup ჩანართზე:
ASPNETCORE_URLS=http://0.0.0.0:25571გამოიყენე პორტის ის ნომერი, რომელსაც შენი გეგმა რეალურად აჩვენებს. თუ არ გინდა პორტის ორ ადგილას კოპირება, წაიკითხე ის კოდში. პანელები გამოყოფილ პორტს პროცესს გარემოს ცვლადად გადასცემენ (Pterodactyl-ზე დაფუძნებულ პანელებზე ეს არის SERVER_PORT), და შეგიძლია მას აშკარად მიება:
var builder = WebApplication.CreateBuilder(args);var port = Environment.GetEnvironmentVariable("PORT") ?? Environment.GetEnvironmentVariable("SERVER_PORT");if (port is not null){ builder.WebHost.ConfigureKestrel(k => k.ListenAnyIP(int.Parse(port)));}var app = builder.Build();app.MapGet("/healthz", () => Results.Ok(new { ok = true }));app.Run();ListenAnyIP ამ პორტზე IPv4-საც და IPv6-საც ებმება. http://+:8080 და http://*:8080 ASPNETCORE_URLS-ში იგივეს ნიშნავს, რასაც 0.0.0.0; სამივე მუშაობს.
მოუსმინე უბრალო HTTP-ს. TLS-ს აპლიკაციის წინ მდგომი proxy ასრულებს, ამიტომ Kestrel-ს სერტიფიკატი არ სჭირდება, ხოლო კონტეინერის შიგნით HTTPS endpoint-ის კონფიგურაცია სერტიფიკატის პრობლემას გაძლევს ყოველგვარი სარგებლის გარეშე. ASP.NET Core-ის შაბლონის development სერტიფიკატი სერვერზე არ არსებობს; თუ შენს კონფიგურაციაში ჯერ კიდევ არის https:// URL, გაშვება ვარდება შეტყობინებით "Unable to configure HTTPS endpoint. No server certificate was specified".
გარემო, appsettings და connection string-ები#
ASP.NET Core თავის გარემოს ASPNETCORE_ENVIRONMENT-იდან (ან DOTNET_ENVIRONMENT-იდან) იღებს, და როცა არცერთი არ არის დაყენებული, გარემო არის Production. ეს ნაგულისხმევი სერვერისთვის სწორია და ცვლის ქცევას, რასაც შეამჩნევ: developer exception page გამორთულია, appsettings.Development.json არ იტვირთება და user secrets არ იკითხება.
ეს უკანასკნელი პირველი deploy-ის კლასიკური ჩავარდნაა. ლოკალურად ყველაფერი მუშაობდა, რადგან მონაცემთა ბაზის პაროლი user secrets-ში იყო; სერვერზე ის უბრალოდ არ არის და აპლიკაცია პირველივე query-ზე ვარდება ცარიელი connection string-ით. სერვერზე კონფიგურაცია მოდის appsettings.json-იდან, შემდეგ appsettings.Production.json-იდან, შემდეგ გარემოს ცვლადებიდან, და გარემო იმარჯვებს.
საიდუმლოებები ჩაწერე გარემოს ცვლადებში Startup ჩანართზე. ჩადგმული გასაღებები ორმაგ ქვედა ტირეს იყენებს:
ConnectionStrings__Default=Host=203.0.113.10;Port=5432;Database=shop;Username=shop;Password=...Stripe__SecretKey=sk_live_...builder.Configuration.GetConnectionString("Default") შემდეგ პირველს კითხულობს, ხოლო builder.Configuration["Stripe:SecretKey"] - მეორეს. სრული ფენები, options pattern და გაშვებისას პარამეტრების ვალიდაცია აღწერილია პოსტში ASP.NET Core-ის კონფიგურაცია და საიდუმლოებები. RE:NODE-ზე აპლიკაციის გეგმაში შედის ორი database slot, რომლებიც პანელში იქმნება გენერირებული ჰოსტით, მომხმარებლით და პაროლით, ამიტომ connection string არის ის, რასაც Startup ჩანართზე აკოპირებ და არა იგონებ. თუ SQL Server, MySQL ან PostgreSQL ცალკე სერვერად გჭირდება, ეს არის მონაცემთა ბაზის ჰოსტინგი; .NET PostgreSQL-ით, MySQL-ით თუ SQL Server-ით თითოეულის provider პაკეტებს განიხილავს.
კიდევ ერთი ფაილი, რომელიც deploy-ებს უნდა გადაურჩეს: Data Protection-ის key ring. ASP.NET Core მას ავთენტიკაციის cookie-ებისა და antiforgery ტოკენების დასაშიფრად იყენებს და ნაგულისხმევად ის მომხმარებლის home დირექტორიაში ცხოვრობს. თუ ეს ადგილი მუდმივი არ არის, ან გასაღებები ხელახლა გენერირდება, restart-ზე ყველა მომხმარებელი გამოდის სისტემიდან. შეინახე ისინი სადმე, სადაც დარწმუნებული ხარ, რომ redeploy-ს გადაურჩება და ტრეკინგ repository-ის გარეთაა:
builder.Services.AddDataProtection() .PersistKeysToFileSystem(new DirectoryInfo("/home/container/keys"));გზა შეცვალე იქით, სადაც შენი სერვერის მუდმივი ფაილები ცხოვრობს. ASP.NET Core-ის ავთენტიკაციის საფუძვლები ხსნის, რა ტყდება, როცა გასაღებები მოულოდნელად იცვლება.
დომენი, HTTPS და გადაგზავნილი header-ები#
როცა Kestrel უბრალო HTTP-ზეა, დომენი და სერტიფიკატი proxy-ს ეკუთვნის. RE:NODE-ზე ყველა აპლიკაციის გეგმაში proxy slot შედის: მიუთითე A ჩანაწერი ნაჩვენებ მისამართზე და სერტიფიკატი ავტომატურად გაიცემა და განახლდება 21-დღიან ფანჯარაში. კლიენტის რეალური მისამართი X-Forwarded-For-ში მოდის.
შენს აპლიკაციას უნდა უთხრა, რომ ამ header-ს დაუჯეროს, თორემ ყველა მოთხოვნას დაინახავს, როგორც proxy-დან უბრალო HTTP-ით მოსულს. როცა არ უჯერებს, ორი რამ ტყდება:
HttpContext.Connection.RemoteIpAddressproxy-ის მისამართია, ამიტომ ლოგები და rate limit-ები ყველა ვიზიტორს ერთ ადამიანად თვლის.Request.Schemeარისhttp, ამიტომUseHttpsRedirectionგადაამისამართებს მოთხოვნას, რომელიც უკვე HTTPS-ით მოვიდა, და ბრაუზერი ციკლში ტრიალებს, სანამ "too many redirects"-ით არ დანებდება.
გამოსავალია forwarded headers middleware, რომელიც პირველი რეგისტრირდება:
builder.Services.Configure<ForwardedHeadersOptions>(o =>{ o.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;});var app = builder.Build();app.UseForwardedHeaders();ნაგულისხმევად middleware მხოლოდ loopback-ზე მდგომ proxy-ებს ენდობა, ამიტომ სხვა მისამართზე მდგომი proxy იგნორირებულია, სანამ მას KnownProxies-ში არ დაამატებ. ამის სწორად გაკეთება ისე, რომ ვინმემ თავისი IP ვერ გააყალბოს, არის პოსტის ASP.NET Core reverse proxy-ს უკან მთავარი თემა, HSTS-თან და WebSocket-ებთან ერთად. თუ ეს იდეა შენთვის ახალია, ფონისთვის წაიკითხე რას აკეთებს reverse proxy სინამდვილეში.
პირველი deploy, ნაბიჯ-ნაბიჯ#
- Push გაუკეთე repository-ს
global.json-ით,bin-ისა დაobj-ის გარეშე, და health endpoint-ით, მაგალითად/healthz, რომელიც 200-ს აბრუნებს მონაცემთა ბაზასთან შეხების გარეშე. - დააკავშირე repository პანელში. RE:NODE-ზე ეს მხოლოდ GitHub-ია, GitHub App-ის გავლით ხანმოკლე ტოკენებით, ამიტომ კერძო repository-ებიც მუშაობს.
- დააყენე start ბრძანება: publish
out-ში, შემდეგexec dotnet out/YourApp.dll. - Startup ჩანართზე დააყენე
ASPNETCORE_URLSმნიშვნელობაზეhttp://0.0.0.0:პლუს შენი გამოყოფილი პორტი და დაამატე connection string-ები და საიდუმლოებები. - გაუშვი სერვერი და უყურე კონსოლს. ჯანსაღი გაშვება მთავრდება ხაზებით
Now listening on: http://0.0.0.0:25571დაApplication started.თუ ნაცვლად ამისა ხედავhttp://localhost:5000-ს, მე-4 ნაბიჯმა არ იმუშავა. - მოითხოვე health endpoint IP-ითა და პორტით. შემდეგ დააყენე proxy slot და მოითხოვე ის დომენით.
- ჩართე deploy-ის ორი გადამრთველი, თუ გინდა: pull ყოველ გაშვებაზე და deploy on push, რომელიც მხოლოდ უკვე გაშვებულ სერვერს გადატვირთავს - ამიტომ სერვერი, რომელიც განზრახ გააჩერე, გაჩერებული რჩება. ყოველი deploy ჩაიწერება, რაც გეუბნება, რომელი commit არის ცოცხალი.
ამის პანელის მხარე screenshot-ებით აღწერილია deploy-ების სახელმძღვანელოში. პროცესი იგივეა, რაც Node-ისთვის; Node.js აპლიკაციის გაშვება GitHub-იდან უფრო მეტს გიყვება იმაზე, როგორ ურთიერთქმედებს pull-on-start და deploy-on-push.
პირველი deploy-ის პრობლემების მოგვარება#
"Now listening on: http://localhost:5000" და არაფერი უკავშირდება. Kestrel-მა შენი მისამართი არასოდეს მიიღო. შეამოწმე ASPNETCORE_URLS-ის მართლწერა და რომ მნიშვნელობა http://-ით იწყება. გარემოს ცვლადის სახელში შეცდომა საერთოდ არანაირ შეცდომას არ იწვევს.
"A compatible .NET SDK was not found". global.json ასახელებს SDK-ს, რომელიც დაყენებული არ არის. შეარბილე ის მთავარ ვერსიამდე rollForward-ით, ან წაშალე.
"You must install or update .NET to run this application". framework-dependent შედეგი მიზნად ისახავს runtime-ს, რომელიც სერვერს არ აქვს - მაგალითად net10.0 აპლიკაცია მანქანაზე, სადაც მხოლოდ .NET 8 runtime-ია. დაუმიზნე დაყენებულ ვერსიას ან გააკეთე self-contained publish.
"Failed to bind to address ... address already in use". სხვა პროცესი (ხშირად შენივე წინა ინსტანცია, ან დავიწყებული build server) პორტს იკავებს, ან კონფიგურაციაში ორი endpoint ერთსა და იმავე პორტს ასახელებს.
build შუა გზაზე კვდება შეცდომის გარეშე. მეხსიერება. კომპილატორი ლიმიტზე გაჩერდა; იხილე ზემოთ მოცემული გაფრთხილება.
აპლიკაცია ყოველ რამდენიმე წუთში გადაიტვირთება. წაიკითხე ბოლო ხაზები ყოველი restart-ის წინ. გაშვებისას დაუმუშავებელი გამონაკლისი, მაგალითად მონაცემთა ბაზასთან წარუმატებელი კავშირი Program.cs-ში, პროცესს ასრულებს, პლატფორმა მას თავიდან უშვებს და ციკლი მეორდება. ჩავარდი გასაგები შეტყობინებით და არა stack trace-ით, და ნახე რატომ გადაიტვირთება შენი სერვერი გამუდმებით, რომ გაიგო, როგორ ვლინდება restart-ის ციკლები.
deploy-ის შემდეგ ყველა მომხმარებელი გამოდის სისტემიდან. Data Protection-ის გასაღებები არ იყო შენახული. იხილე ზემოთ.
სტატიკური ფაილები production-ში 404-ს აბრუნებს. wwwroot-ს dotnet publish მხოლოდ მაშინ აკოპირებს, თუ ფაილები პროექტის ნაწილია. ფაილები, რომლებიც publish-ის შემდეგ გაშვებულმა front-end build-მა დაამატა, ან .csproj-ში გამორიცხულია, out-მდე ვერასოდეს აღწევს. ჯერ front-end ააგე, შემდეგ გააკეთე publish.
FAQ#
მჭირდება IIS ან nginx Kestrel-ის წინ?
არა. Kestrel უკვე წლებია მხარდაჭერილი edge სერვერია. რაც გჭირდება, არის TLS-ის დასრულება და დომენი, რასაც proxy slot უზრუნველყოფს; კონტეინერის შიგნით nginx-ის დამატება მას ორმაგებს და დასარეგულირებელ timeout-ების მეორე ნაკრებს გაძლევს.
უნდა გავუკეთო commit გამოქვეყნებულ შედეგს main ბრენჩში?
არა იმ ბრენჩში, რომელზეც დეველოპმენტს აკეთებ. კომპილირებული შედეგი წყაროს კოდთან ერთ ბრენჩში უზარმაზარ diff-ებსა და merge კონფლიქტებს წარმოშობს. თუ სწრაფი restart-ები გინდა, CI-ს ცალკე ბრენჩში გააკეთებინე publish და სერვერი ამ ბრენჩზე მიუთითე.
რატომ გრძელდება ყოველი restart ასე დიდხანს?
იმიტომ, რომ start ბრძანება ყოველ ჯერზე restore-სა და კომპილაციას აკეთებს. ეს სერვერზე აგების ფასია. CI-ში წინასწარ აგება ან solution-ის პატარად შენარჩუნება მას წამებამდე ამცირებს.
შემიძლია მონაცემთა ბაზის მიგრაციები deploy-ის ნაწილად გავუშვა?
შეგიძლია, მაგრამ დაფიქრდი, რა ხდება, როცა მიგრაცია შუა გზაზე ვარდება. EF Core-ის მიგრაციები production-ში ადარებს მათ გაშვებისას გამოყენებას migration bundle-ებსა და idempotent სკრიპტებს.
.NET-ის რომელ ვერსიას უნდა დაუმიზნოს ახალმა აპლიკაციამ?
მიმდინარე long-term support რელიზს, რომელიც 2026 წლის ოქტომბრის მდგომარეობით არის .NET 10. ის მხარდაჭერილია 2028 წლის ნოემბრამდე, ამიტომ წლის განმავლობაში განახლებას არ გაიძულებს.
რამდენი მეხსიერება სჭირდება პატარა ASP.NET Core API-ს?
მინიმალური API უქმ მდგომარეობაში 100 MB-ზე გაცილებით ნაკლებს იყენებს; ტიპური აპლიკაცია EF Core-ით და რამდენიმე ათეული endpoint-ით მსუბუქი დატვირთვისას 100-დან 300 MB-მდე იკავებს. სერვერზე build-ს აპლიკაციაზე მეტი სჭირდება. .NET-ის მეხსიერება და garbage collection ხსნის, რატომ არის დამოკიდებული ის რიცხვი, რომელსაც ხედავ, GC-ის რეჟიმზე.




კომენტარები
სრულიად ანონიმურად: ანგარიშის, ელფოსტის და cookie-ის გარეშე. ინახება მხოლოდ სახელი, ტექსტი და დრო - სხვა არაფერი. ბმულების რაოდენობა ლიმიტირებულია.