Brak domen aplikacji w .NET Core! Czemu?

88

Czy istnieje ważny powód, dla którego firma Microsoft zdecydowała się nie obsługiwać AppDomains w .NET Core?

AppDomains są szczególnie przydatne podczas tworzenia długo działających aplikacji serwerowych, w których możemy chcieć zaktualizować zestawy ładowane przez serwer w sposób łagodny, bez wyłączania serwera.

Bez AppDomains, jak zamierzamy zastąpić nasze zestawy w długotrwałym procesie serwera?

AppDomains zapewniają nam również sposób na izolowanie różnych części kodu serwera. Tak jak niestandardowy serwer WebSocket może mieć kod gniazda w podstawowej domenie aplikacji, podczas gdy nasze usługi działają w dodatkowej domenie aplikacji.

Bez AppDomains powyższy scenariusz nie jest możliwy.

Widzę argument, który może mówić o używaniu koncepcji maszyn wirtualnych w chmurze do obsługi zmian w montażu i bez konieczności ponoszenia narzutu AppDomains. Ale czy tak myśli lub mówi Microsoft? czy mają konkretny powód i alternatywy dla powyższych scenariuszy?

Aditya Pasumarthi
źródło
9
Ale .NET Core 5 to nie .NET Framework. To nie jest nadchodząca wersja .NET CLR 4.6, ale kolejna osobna rzecz, więc nie martw się, AppDomain jest tutaj.
Adriano Repetti,
2
Widzę to, ale jeśli Microsoft twierdzi, że .NET Core 5 będzie wieloplatformowy (Windows / Linux / Unix), to jestem ciekawy, dlaczego chcą usunąć podstawową funkcję, taką jak AppDomain.
Aditya Pasumarthi
3
Myślę (ale to tylko moja opinia) są trudniejsze do zaimplementowania w sposób wieloplatformowy, spowalniają wiele rzeczy i dodają złożoności. Niewiele osób z nich korzysta (przynajmniej większość ludzi nie robi tego bezpośrednio). Jeśli ich nie potrzebujesz, możesz użyć .NET Core. Jeśli ich potrzebujesz ... nie używaj ich (pomyśl ReFS vs NTFS). Po prostu .NET Core to nie .NET future (na razie), ale oddzielny projekt. Może warsztat, ale na pewno nie ścieżka migracji ani alternatywa 1: 1 (przynajmniej teraz).
Adriano Repetti,
@AdrianoRepetti: Rozważ dodanie tego jako odpowiedzi, ponieważ uważam, że jest to przydatne jako takie.
Patrick Hofman,
@PatrickHofman to tylko moja opinia (drugi komentarz), mogę odpowiedzieć jako wiki społeczności, ale zostawiam ten obowiązek komuś, kto mówi płynniej po angielsku!
Adriano Repetti,

Odpowiedzi:

49

Celem podzbioru .NETCore było utrzymanie małej instalacji .NET . I łatwe do przenoszenia. Dlatego możesz, powiedzmy, uruchomić aplikację Silverlight zarówno w systemie Windows, jak i OSX i nie czekać zbyt długo, kiedy odwiedzasz stronę internetową. Pobranie i zainstalowanie pełnego środowiska uruchomieniowego i frameworka zajmuje kilka sekund.

Utrzymanie jej małego rozmiaru nieuchronnie wymaga wycięcia cech. Zdalny dostęp był bardzo wysoko na tej liście, jest dość drogi. W przeciwnym razie dobrze ukryty, ale można na przykład zobaczyć, że delegaci nie mają już funkcjonalnej metody BeginInvoke (). Dzięki temu AppDomain również znalazł się na liście elementów ciętych, nie możesz uruchamiać kodu w domenie aplikacji bez obsługi zdalnej. Jest to więc całkowicie zgodne z projektem.

Hans Passant
źródło
13
IMHO nie ma to nic wspólnego z rozmiarem, ale z faktem, że CoreCLR nie ma silnego nazewnictwa, a tym samym ma nowy system fusion i nowy sposób patrzenia na to, czym jest zestaw, jego tożsamość i gdzie jest ładowany, co oznacza, że ​​domena aplikacji jako kontener nie jest już przydatna.
Frans Bouma,
7
Hmm, nie. Utrzymanie rozmiaru pobierania do 6,6 MB wymagało oczywiście usunięcia więcej niż jednej funkcji.
Hans Passant
8
AppDomains mogą być przydatne w pełnej wersji .NET, nawet jeśli nie używasz silnego nazewnictwa. (Np. Zdolność AppDomains do zapewniania izolacji błędów nie zależy od silnego nazewnictwa). Zatem samo usunięcie silnego nazewnictwa nie byłoby powodem do usunięcia AppDomains.
Ian Griffiths
5
Jestem zmieszany. Jaki jest związek między .Net Core i Silverlight?
Svick
10
Programiści zwykle zakładają, że .NETCore jest nowy. Microsoft robi bardzo niewiele, aby rozwiać ten pogląd, w najmniejszym stopniu zmieniając numer wersji 5.0 na 1.0. CoreCLR istnieje od bardzo dawna, rozpoczął życie jako środowisko wykonawcze .NET Compact. Silverlight i środowisko uruchomieniowe WinRT / UWP są godnymi uwagi zastosowaniami, zanim je otworzą. Najlepsza do wyboru wersja środowiska uruchomieniowego, wcześniej przeportowana na OSX i różne procesory mobilne WinCE.
Hans Passant
47

Aktualizacja dla .NET Standard 2 i .NET Core 2

W .NET Standard 2 AppDomainklasa jest tam. Jednak wiele części tego interfejsu API spowoduje zgłoszenie PlatformNotSupportedExceptiondla platformy .NET Core.

Głównym powodem, dla którego wciąż tam jest, są podstawowe rzeczy, takie jak rejestracja nieobsługiwanego programu obsługi wyjątków, który będzie działał.

NET Standard FAQ zawiera następujące wyjaśnienie :

Czy AppDomain jest częścią .NET Standard?

Typ AppDomain jest częścią .NET Standard. Nie wszystkie platformy będą obsługiwać tworzenie nowych domen aplikacji, na przykład .NET Core nie będzie, więc metoda AppDomain.CreateDomain, będąc dostępna w .NET Standard, może zgłosić PlatformNotSupportedException.

Głównym powodem, dla którego ujawniamy ten typ w .NET Standard, jest to, że użycie jest dość wysokie i zwykle nie jest związane z tworzeniem nowych domen aplikacji, ale z interakcją z bieżącą domeną aplikacji, taką jak rejestracja nieobsługiwanego programu obsługi wyjątków lub pytanie o katalog podstawowy aplikacji .

Poza tym górna odpowiedź i inne odpowiedzi również ładnie wyjaśniają, dlaczego większość AppDomain była nadal ograniczona (np. Zgłasza nieobsługiwany wyjątek).

Jeroen
źródło
21

Domeny aplikacji

Dlaczego zostało przerwane? AppDomains wymagają obsługi w czasie wykonywania i generalnie są dość drogie. Chociaż nadal jest implementowany przez CoreCLR, nie jest dostępny w .NET Native i nie planujemy dodawania tam tej funkcji.

Czego powinienem użyć zamiast tego? AppDomains były używane do różnych celów. Do izolacji kodu zalecamy procesy i / lub kontenery. W przypadku dynamicznego ładowania zestawów zalecamy nową klasę AssemblyLoadContext.

Źródło z blogu MSDN

cwishva
źródło
Jedno pytanie, co rozumiesz przez For code isolation, we recommend processes and/or containers... Czy w .net core jest dostępny interfejs API kontenera?
Ivandro Jao
@IvandroIsmael, mają na myśli „podziel swoją pojedynczą aplikację / moduł na oddzielne, wchodzące w interakcję aplikacje / moduły / procesy / kontenery” (najprawdopodobniej - na mikrousługi), tj. Refaktoryzację aplikacji tak, aby nie używała AppDomains do izolacji kodu
Burst
10

W pewnym momencie usłyszałem, że rozładowywanie zestawów byłoby możliwe bez korzystania z domen. Wydaje mi się, że System.Runtime.Loader.AssemblyLoadContexttyp w System.Runtime.Loader.dll jest związany z tą pracą, ale nie widzę tam jeszcze niczego, co umożliwiałoby wyładowanie.

bricelam
źródło
6

Nie potrzebujesz już AppDomains, masz teraz LoadContexts:

public class CollectibleAssemblyLoadContext 
    : AssemblyLoadContext
{
    public CollectibleAssemblyLoadContext() : base(isCollectible: true)
    { }
 
    protected override Assembly Load(AssemblyName assemblyName)
    {
        return null;
    }
}

byte[] result = null; // Assembly Emit-result from roslyn
System.Runtime.Loader.AssemblyLoadContext context = new CollectibleAssemblyLoadContext();
System.IO.Stream ms = new System.IO.MemoryStream(result);
System.Reflection.Assembly assembly = context.LoadFromStream(ms);


System.Type programType = assembly.GetType("RsEval");
MyAbstractClass eval = (MyAbstractClass )System.Activator.CreateInstance(programType);
eval.LoadContext = context;
eval.Stream = ms;
// do something here with the dynamically created class "eval"

a potem możesz powiedzieć

eval.LoadContext.Unload();
eval.Stream.Dispose();

Bonus, jeśli umieścisz to w interfejsie IDisposable klasy abstrakcyjnej, możesz po prostu użyć using, jeśli chcesz.

Uwaga:
Zakłada to stałą klasę abstrakcyjną we wspólnym zestawie

public abstract class MyAbstractClass 
{

     public virtual void foo()
     {}
}

oraz klasę generowaną dynamicznie (przy użyciu Roslyn), odwołującą się do klasy abstrakcyjnej we wspólnym zestawie, która implementuje np .:

public class RsEval: MyAbstractClass 
{

     public override void foo()
     {}
}
Stefan Steiger
źródło
5

Słyszałem w opinii społeczności lub rozmowach o firmie Microsoft, że funkcja izolacji AppDomains jest lepiej obsługiwana przez procesy (a właściwie wspólny wzorzec na innych platformach), a wyładowanie jest rzeczywiście planowane jako normalna funkcja niezwiązana z AppDomains.

Tomasz
źródło