.NET Core에 AppDomain이 없습니다! 왜?


88

Microsoft가 .NET Core에서 AppDomains를 지원하지 않기로 선택한 강력한 이유가 있습니까?

AppDomains는 서버를 종료하지 않고 서버에서로드 한 어셈블리를 적절하게 업데이트하려는 장기 실행 서버 앱을 빌드 할 때 특히 유용합니다.

AppDomains가 없으면 장기 실행 서버 프로세스에서 어셈블리를 어떻게 교체할까요?

AppDomains는 또한 서버 코드의 다른 부분을 격리하는 방법을 제공합니다. 마찬가지로 사용자 지정 웹 소켓 서버는 기본 appdomain에 소켓 코드를 가질 수 있지만 서비스는 보조 appdomain에서 실행됩니다.

AppDomains가 없으면 위의 시나리오는 불가능합니다.

어셈블리 변경을 처리하고 AppDomain의 오버 헤드를 발생시키지 않아도되는 클라우드의 VM 개념을 사용하는 것에 대해 이야기 할 수있는 주장을 볼 수 있습니다. 그러나 이것이 Microsoft가 생각하거나 말하는 것입니까? 또는 위 시나리오에 대한 구체적인 이유와 대안이 있습니까?


9
그러나 .NET Core 5 는 .NET Framework 가 아닙니다 . 그렇지 않은 .NET CLR 4.6의 향후 버전 하지만 다른 별도의 일이 다음하지 걱정을, 응용 프로그램 도메인은 여기에 있습니다.
— 아드리아누 Repetti

2
하지만 Microsoft가 .NET Core 5가 다중 플랫폼 (Windows / Linux / Unix)이 될 것이라고 주장하는 경우 AppDomain과 같은 핵심 기능을 제거하려는 이유가 궁금합니다.
— Aditya Pasumarthi

3
나는 (그러나 그것은 단지 내 의견이다) 다중 플랫폼 방식으로 구현하기가 더 어렵고 많은 것을 느리게 만들고 복잡성을 추가합니다. 많은 사람들이 사용하지 않습니다 (적어도 대부분의 사람들은 직접 사용하지 않습니다). 필요하지 않은 경우 .NET Core를 사용할 수 있습니다. 필요한 경우 사용하지 마십시오 (ReFS ​​대 NTFS를 생각하십시오). 단순히 .NET Core는 .NET 미래 (지금까지)가 아니라 별도의 프로젝트입니다. 워크 벤치 일 수도 있지만 마이그레이션 경로 나 1 : 1 대안은 아닙니다 (적어도 지금).
— Adriano Repetti 2014

@AdrianoRepetti : 이것이 유용하다고 생각하기 때문에 이것을 대답으로 추가하는 것을 고려하십시오.
— Patrick Hofman 2014

@PatrickHofman 그것은, 내가 커뮤니티 위키로 대답 할 수 단지 내 의견 (2 코멘트)이다하지만이 떠나 의무를 더 유창하게 영어를 사람에게!
— Adriano Repetti 2014

답변:


49

.NETCore 하위 집합의 요점은 .NET 설치를 작게 유지하는 것이 었습니다 . 이식하기 쉽습니다. 그렇기 때문에 Windows와 OSX 모두에서 Silverlight 앱을 실행할 수 있고 웹 페이지를 방문 할 때 오래 기다리지 않아도됩니다. 완전한 런타임과 프레임 워크를 다운로드하고 설치하는 데는 몇 초 정도 걸립니다.

작게 유지하려면 불가피하게 기능을 잘라야합니다. Remoting은 그 목록에서 매우 높았으며 비용이 많이 듭니다. 그렇지 않으면 잘 숨겨져 있지만 예를 들어 대리자에 더 이상 기능적인 BeginInvoke () 메서드가 없음을 알 수 있습니다. AppDomain도 컷 목록에 포함되므로 원격 지원 없이는 앱 도메인에서 코드를 실행할 수 없습니다. 그래서 이것은 전적으로 의도적으로 설계된 것입니다.


13
IMHO는 크기와 관련이 없지만 CoreCLR에는 강력한 이름 지정이 없으므로 새로운 융합 시스템과 어셈블리가 무엇인지, 그 정체성과로드 위치를 보는 새로운 방식이 있다는 사실과 관련이 있습니다. 즉, 컨테이너로서의 appdomain은 더 이상 유용하지 않습니다.
— Frans Bouma 2014

7
흠, 아니. 물론 다운로드 크기를 6.6MB로 유지하려면 둘 이상의 기능을 제거해야했습니다.
— Hans Passant 2014

8
강력한 이름 지정을 사용하지 않는 경우에도 전체 .NET에서 AppDomains가 유용 할 수 있습니다. (예를 들어, 오류 격리를 제공하는 AppDomains의 기능은 강력한 이름 지정에 의존하지 않습니다.) 따라서 강력한 이름 지정의 제거 자체가 AppDomains를 제거하는 이유는 아닙니다.
— Ian Griffiths

5
혼란 스러워요. .Net Core와 Silverlight의 관계는 무엇입니까?
— svick

10
프로그래머는 .NETCore가 새로운 것이라고 생각하는 경향이 있습니다. Microsoft는 5.0 버전 번호를 1.0으로 변경하는 것이 아니라이 개념을 거의 없애지 않습니다. CoreCLR은 아주 오래 전부터 .NET Compact의 런타임으로 시작되었습니다. Silverlight 및 WinRT / UWP 런타임은 오픈 소스 화되기 전에 주목할만한 용도입니다. 이전에 이미 OSX 및 다양한 WinCE 모바일 프로세서로 포팅 된 적이있는 최고의 런타임 버전입니다.
— Hans Passant

47

.NET Standard 2 및 .NET Core 2 용 업데이트

.NET Standard 2에는 AppDomain클래스 가 있습니다. 그러나 해당 API의 많은 부분 PlatformNotSupportedException에서 .NET Core 용이 발생합니다.

그것이 여전히 존재하는 주된 이유 는 작동 할 처리되지 않은 예외 핸들러를 등록하는 것과 같은 기본적인 것들 때문입니다 .

.NET Standard FAQ에는 다음과 같은 설명이 있습니다 .

AppDomain은 .NET Standard의 일부입니까?

AppDomain 유형은 .NET Standard의 일부입니다. 모든 플랫폼이 새 앱 도메인 생성을 지원하는 것은 아닙니다. 예를 들어 .NET Core는 지원하지 않으므로 .NET Standard에서 사용 가능한 AppDomain.CreateDomain 메서드는 PlatformNotSupportedException을 throw 할 수 있습니다.

.NET Standard에서이 유형을 노출하는 주된 이유는 사용량이 상당히 높고 일반적으로 새 앱 도메인을 만드는 것과 관련이 없지만 처리되지 않은 예외 처리기를 등록하거나 애플리케이션의 기본 디렉터리를 요청하는 등 현재 앱 도메인과 상호 작용하기 때문입니다. .

그 외에도 상위 답변 및 기타 답변은 AppDomain의 대부분이 여전히 잘린 이유를 잘 설명합니다 (예 : 지원되지 않는 예외 발생).


21

앱 도메인

중단 된 이유는 무엇입니까? AppDomain은 런타임 지원이 필요하며 일반적으로 비용이 많이 듭니다. 여전히 CoreCLR에 의해 구현되지만 .NET Native에서는 사용할 수 없으며 여기에이 기능을 추가 할 계획이 없습니다.

대신 무엇을 사용해야합니까? AppDomain은 다른 목적으로 사용되었습니다. 코드 격리를 위해 프로세스 및 / 또는 컨테이너를 권장합니다. 어셈블리를 동적으로로드하려면 새 AssemblyLoadContext 클래스를 사용하는 것이 좋습니다.

MSDN 블로그 출처


한 가지 질문은 무엇을 의미 For code isolation, we recommend processes and/or containers합니까? .net 코어에서 사용할 수있는 컨테이너 API가 있습니까?
— Ivandro Jao

@IvandroIsmael, "단일 앱 / 모듈을 별도의 상호 작용하는 앱 / 모듈 / 프로세스 / 컨테이너로 분할"(대부분 마이크로 서비스로 분할), 즉 코드 격리를 위해 AppDomains를 사용하지 않도록 앱을 리팩터링하는 것을 의미합니다.
— Burst

10

언로드 어셈블리는 도메인을 사용하지 않고 활성화 될 것이라고 들었습니다. System.Runtime.Loader.AssemblyLoadContextSystem.Runtime.Loader.dll 의 형식이이 작업과 관련이 있다고 생각 하지만 아직 언로드 할 수있는 항목이 표시되지 않습니다.


6

더 이상 AppDomains가 필요하지 않습니다. 이제 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"

그리고 당신은 말할 수 있습니다

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

추상 클래스의 IDisposable 인터페이스에 추가하면 원하는 경우 using을 사용할 수 있습니다.

참고 :
이것은 공통 어셈블리에서 고정 된 추상 클래스를 가정합니다.

public abstract class MyAbstractClass 
{

     public virtual void foo()
     {}
}

다음을 구현하는 공통 어셈블리의 추상 클래스를 참조하는 동적 런타임 생성 클래스 (Roslyn 사용)가 있습니다.

public class RsEval: MyAbstractClass 
{

     public override void foo()
     {}
}

5

나는 커뮤니티 스탠드 업이나 마이크로 소프트에서 AppDomains의 격리 기능이 프로세스 (그리고 실제로는 다른 플랫폼의 일반적인 패턴)에서 더 잘 처리되며 언 로딩은 실제로 AppDomains와 관련이없는 정상적인 기능으로 계획되어 있다고 들었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.