NetCore實踐篇:分散式監控客戶端ZipkinTracer從入門到放棄之路
上面三篇文章普及了一些依賴注入的知識。sorry,這塊我研究的很淺。。。這次順帶了解了不少,以後要抽空專門研究一下。
Single:單例是一個將持續應用程式整個生命週期的例項。在Web術語中,這意味著在服務的初始請求之後,每個後續請求將使用相同的例項。這也意味著它跨越Web請求(因此,如果兩個不同的使用者訪問您的網站,程式碼仍然使用相同的例項)。考慮單例的最簡單方法是,如果類中有靜態變數,則它是跨多個例項的單個值。
Scoped:範圍內的生命週期物件通常會簡化為“每個Web請求一個例項”,但實際上它比實際上更加微妙。無可否認,在大多數情況下,您可以將每個Web請求視為範圍物件。您可能會看到的常見問題是每個Web請求建立一次DBContext,或者建立一次NHibernate上下文,以便您可以將整個請求包含在事務中。作用域生存期物件的另一個非常常見的用途是當您要建立每個請求快取時。 Scoped生命週期實際上意味著在建立的“範圍”物件中將是同一個例項。它恰好發生在.net核心中,它在“範圍”內包裝請求,但您實際上可以手動建立範圍
Transient:每次請求服務時,都會建立一個新例項。
這是一個基本的設計約束。你不能讓單身人士(Single)依賴於瞬態(Scoped)或範圍內(Transient)的物品。這不是容器的錯,這些生命週期是不相容的。如果您需要相容的生命週期,請選擇不同的生命週期。
Singleton < - Singleton 良好
Singleton < - Scoped 糟糕
Singleton < - Transient 糟糕
Scoped < - Singleton 良好
Scoped < - Scoped 良好
Scoped < - Transient 良好
TRANSIENT < - Singleton 良好
Transient < - Scoped 良好在範圍內,糟糕在範圍外 TRANSIENT< - TRANSIENT 良好
所以真的只有兩種情況“總是糟糕”,一種情況“有時候很糟糕”。 ASP.NET Core DI使這個非常明確,甚至將工廠方法傳遞給上下文物件,例如過濾器。過濾器是Singleton,因此您不能擁有建構函式依賴項。相反,您使用傳遞給過濾器方法的各種XyzContext物件來解析依賴項。
上述是十分有價值的評價,先收藏,以後細細品味。
有了這些基礎知識和良好建議,我們再來回顧下程式碼。看到前面都是AddSingleton,後面是AddScoped,在上面的建議中是屬於糟糕的。雖然不清楚作者的意圖,但我們可以先把程式跑起來,以後用熟悉了再來仔細修復。
public static class ServiceCollectionExtensions
{
public static void AddZipkinTracer(this IServiceCollection services, ZipkinConfig config)
{
if (config == null) throw new ArgumentNullException(nameof(config));
var maxSize = config.MaxQueueSize <= 0 ? 100 : config.MaxQueueSize;
services.AddSingleton(config);
services.AddSingleton(new BlockingCollection<Span>(maxSize));
services.AddSingleton<IServiceEndpoint, ServiceEndpoint>();
services.AddSingleton<ISpanProcessorTask, SpanProcessorTask>();
services.AddSingleton<ISpanProcessor, SpanProcessor>();
services.AddSingleton<ITraceInfoAccessor, TraceInfoAccessor>();
services.AddScoped<ISpanCollector, SpanCollector>();
services.AddScoped<IZipkinTracer, ZipkinClient>();
services.AddScoped<ISpanTracer, SpanTracer>();
}
}
好吧,臨時將三個AddScoped 改為 AddSingleton(); 執行專案。又開始報錯了。。。。說IZipkinTracer需要一個無參的建構函式。
InvalidOperationException: Could not create an instance of type 'ZipkinTracer.IZipkinTracer'. Model bound complex types must not be abstract or value types and must have a parameterless constructor. Alternatively, give the 'tracer' parameter a non-null default value.
繼續搜尋新的這個錯誤。