ไม่มี AppDomains ใน. NET Core! ทำไม?


88

มีเหตุผลที่ชัดเจนว่าทำไม Microsoft จึงเลือกที่จะไม่สนับสนุน AppDomains ใน. NET Core?

AppDomains มีประโยชน์อย่างยิ่งเมื่อสร้างแอปเซิร์ฟเวอร์ที่ใช้งานมานานซึ่งเราอาจต้องการอัปเดตแอสเซมบลีที่เซิร์ฟเวอร์โหลดเป็นวิธีที่ดีโดยไม่ต้องปิดเซิร์ฟเวอร์

หากไม่มี AppDomains เราจะเปลี่ยนแอสเซมบลีของเราในกระบวนการเซิร์ฟเวอร์ที่ใช้งานยาวนานได้อย่างไร

AppDomains ยังให้เราแยกส่วนต่างๆของรหัสเซิร์ฟเวอร์ เช่นเดียวกับเซิร์ฟเวอร์ websocket ที่กำหนดเองสามารถมีรหัสซ็อกเก็ตใน appdomain หลักในขณะที่บริการของเราทำงานใน appdomain รอง

หากไม่มี AppDomains สถานการณ์ข้างต้นจะเป็นไปไม่ได้

ฉันเห็นข้อโต้แย้งที่อาจพูดถึงการใช้แนวคิด VMs ของ Cloud สำหรับจัดการการเปลี่ยนแปลงแอสเซมบลีและไม่ต้องเสียค่าใช้จ่ายของ AppDomains แต่นี่คือสิ่งที่ Microsoft คิดหรือพูด? หรือมีเหตุผลและทางเลือกเฉพาะสำหรับสถานการณ์ข้างต้น?


9
แต่. NET Core 5 ไม่ใช่ . NET Framework ไม่ใช่. NET CLR 4.6 เวอร์ชันที่กำลังจะมาถึงแต่มีอีกสิ่งหนึ่งที่แยกจากกันไม่ต้องกังวล AppDomain อยู่ที่นี่
Adriano Repetti

2
ฉันเห็นว่า แต่ถ้า Microsoft อ้างว่า. NET Core 5 จะเป็นหลายแพลตฟอร์ม (Windows / Linux / Unix) ฉันก็สงสัยว่าทำไมพวกเขาถึงต้องการลบคุณสมบัติหลักอย่าง AppDomain
Aditya Pasumarthi

3
ฉันเดาว่า (แต่เป็นเพียงความคิดเห็นของฉัน) พวกมันยากที่จะนำไปใช้ในรูปแบบหลายแพลตฟอร์มทำให้หลาย ๆ อย่างช้าลงและเพิ่มความซับซ้อน ไม่ค่อยมีคนใช้ (อย่างน้อยคนส่วนใหญ่ก็ไม่ได้ทำโดยตรง) หากคุณไม่ต้องการคุณสามารถใช้. NET Core หากคุณต้องการ ... อย่าใช้มัน (คิดว่า ReFS กับ NTFS) เพียงแค่. NET Core ไม่ใช่. NET ในอนาคต (จนถึงปัจจุบัน) แต่เป็นโครงการที่แยกต่างหาก อาจจะเป็นโต๊ะทำงาน แต่แน่นอนว่าไม่ใช่เส้นทางการโยกย้ายหรือทางเลือก 1: 1 (อย่างน้อยก็ตอนนี้)
Adriano Repetti

@AdrianoRepetti: ลองเพิ่มสิ่งนี้เป็นคำตอบเพราะฉันคิดว่ามันมีประโยชน์เช่นนี้
Patrick Hofman

@PatrickHofman เป็นเพียงความคิดเห็นของฉัน (ความคิดเห็นที่ 2) ฉันสามารถตอบได้ในฐานะวิกิชุมชน แต่ฉันทิ้งหน้าที่นี้ให้กับคนที่มีภาษาอังกฤษคล่องกว่า
Adriano Repetti

คำตอบ:


49

จุดย่อย .NETCore คือการเก็บ .NET ติดตั้งขนาดเล็ก และง่ายต่อการพอร์ต นั่นคือเหตุผลที่คุณสามารถพูดเรียกใช้แอป Silverlight ทั้งบน Windows และ OSX และไม่ต้องรอนานมากเมื่อคุณเยี่ยมชมหน้าเว็บ การดาวน์โหลดและติดตั้งรันไทม์และเฟรมเวิร์กที่สมบูรณ์ใช้เวลาไม่กี่วินาทีให้หรือใช้เวลา

การทำให้เล็กต้องตัดคุณสมบัติอย่างหลีกเลี่ยงไม่ได้ ระยะไกลสูงมากในรายการนั้นค่อนข้างแพง มิฉะนั้นจะถูกซ่อนไว้อย่างดี แต่ตัวอย่างเช่นคุณจะเห็นว่าผู้รับมอบสิทธิ์ไม่มีเมธอด BeginInvoke () ที่ใช้งานได้อีกต่อไป ซึ่งทำให้ AppDomain อยู่ในรายการที่ถูกตัดเช่นกันคุณไม่สามารถเรียกใช้รหัสในโดเมนของแอปโดยไม่ได้รับการสนับสนุนจากระยะไกล นี่คือการออกแบบทั้งหมด


13
IMHO ไม่มีส่วนเกี่ยวข้องกับขนาด แต่ด้วยความจริงที่ว่า CoreCLR ไม่มีการตั้งชื่อที่ชัดเจนจึงมีระบบฟิวชั่นใหม่และวิธีใหม่ในการดูว่าแอสเซมบลีคืออะไรอัตลักษณ์และตำแหน่งที่โหลดเข้าไป หมายถึง appdomain เป็นคอนเทนเนอร์ไม่มีประโยชน์อีกต่อไป
Frans Bouma

7
อืมไม่ การรักษาขนาดการดาวน์โหลดให้เป็น 6.6 MB แน่นอนว่าจำเป็นต้องลบคุณลักษณะมากกว่าหนึ่งรายการ
Hans Passant

8
AppDomains จะมีประโยชน์ใน. NET เต็มรูปแบบแม้ว่าคุณจะไม่ได้ใช้การตั้งชื่อที่รัดกุมก็ตาม (เช่นความสามารถของ AppDomains ในการแยกข้อผิดพลาดไม่ได้ขึ้นอยู่กับการตั้งชื่อที่ชัดเจน) ดังนั้นการลบการตั้งชื่อที่รุนแรงจะไม่เป็นเหตุผลในการลบ AppDomains
Ian Griffiths

5
ฉันสับสน. ความสัมพันธ์ระหว่าง. Net Core และ Silverlight คืออะไร?
svick

10
โปรแกรมเมอร์มักจะคิดว่า. NETCore เป็นสิ่งใหม่ ไมโครซอฟท์ดำเนินการเพียงเล็กน้อยเพื่อขจัดความคิดนี้ไม่ใช่อย่างน้อยโดยการเปลี่ยนหมายเลขเวอร์ชัน 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 มีคำอธิบายนี้ :

AppDomain เป็นส่วนหนึ่งของ. NET Standard หรือไม่

ประเภท AppDomain เป็นส่วนหนึ่งของ. NET Standard ไม่ใช่ทุกแพลตฟอร์มที่จะรองรับการสร้างโดเมนแอปใหม่เช่น. NET Core จะไม่ดังนั้นวิธีการ AppDomain.CreateDomain ในขณะที่มีอยู่ใน. NET Standard อาจทำให้ PlatformNotSupportedException

เหตุผลหลักที่เราเปิดเผยประเภทนี้ใน. NET Standard เนื่องจากการใช้งานค่อนข้างสูงและโดยปกติแล้วจะไม่เกี่ยวข้องกับการสร้างโดเมนแอปใหม่ แต่สำหรับการโต้ตอบกับโดเมนแอปปัจจุบันเช่นการลงทะเบียนตัวจัดการข้อยกเว้นที่ไม่ได้จัดการหรือขอไดเรกทอรีฐานของแอปพลิเคชัน .

นอกเหนือจากนั้นคำตอบยอดนิยมและคำตอบอื่น ๆ ยังอธิบายได้เป็นอย่างดีว่าเหตุใด AppDomain จำนวนมากจึงยังคงถูกตัดออก (เช่นโยนข้อยกเว้นที่ไม่รองรับ)


21

App Domains

ทำไมถึงถูกยกเลิก? AppDomains ต้องการการสนับสนุนรันไทม์และโดยทั่วไปมีราคาค่อนข้างแพง แม้ว่าจะยังคงใช้งานโดย CoreCLR แต่ก็ไม่สามารถใช้ได้ใน. NET Native และเราไม่ได้วางแผนที่จะเพิ่มความสามารถนี้ที่นั่น

ฉันควรใช้อะไรแทน? AppDomains ถูกใช้เพื่อวัตถุประสงค์ที่แตกต่างกัน สำหรับการแยกรหัสเราขอแนะนำกระบวนการและ / หรือคอนเทนเนอร์ สำหรับการโหลดแอสเซมบลีแบบไดนามิกเราขอแนะนำคลาส AssemblyLoadContext ใหม่

ที่มาจาก MSDN Blog


คำถามเดียวคุณหมายถึงอะไรFor code isolation, we recommend processes and/or containers... มี container api ใน. net core หรือไม่?
Ivandro Jao

@IvandroIsmael พวกเขาหมายถึง "แยกแอป / โมดูลเดียวของคุณออกเป็นแอป / โมดูล / กระบวนการ / คอนเทนเนอร์ที่โต้ตอบกัน" (ส่วนใหญ่อาจเป็นไมโครเซอร์วิส) กล่าวคือปรับแอปของคุณไม่ให้ใช้ AppDomains ในการแยกโค้ด
Burst

10

จนถึงจุดหนึ่งฉันได้ยินมาว่าการยกเลิกการโหลดแอสเซมบลีจะเปิดใช้งานโดยไม่ต้องใช้โดเมน ฉันคิดว่าSystem.Runtime.Loader.AssemblyLoadContextประเภทใน System.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 ของคลาสนามธรรมคุณสามารถใช้โดยใช้ถ้าคุณต้องการ

หมายเหตุ:
ถือว่าคลาสนามธรรมคงที่ในแอสเซมบลีทั่วไป

public abstract class MyAbstractClass 
{

     public virtual void foo()
     {}
}

และคลาสที่สร้างรันไทม์แบบไดนามิก (โดยใช้ Roslyn) โดยอ้างถึงคลาสนามธรรมในแอสเซมบลีทั่วไปซึ่งดำเนินการเช่น:

public class RsEval: MyAbstractClass 
{

     public override void foo()
     {}
}

5

ฉันเคยได้ยินในชุมชน standup หรือบางคนพูดถึง Microsoft ว่าคุณลักษณะการแยกของ AppDomains ได้รับการจัดการที่ดีกว่าโดยกระบวนการ (และเป็นรูปแบบทั่วไปในแพลตฟอร์มอื่น ๆ ) และการยกเลิกการโหลดนั้นมีการวางแผนไว้เป็นคุณลักษณะปกติที่ไม่เกี่ยวข้องกับ AppDomains

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.