本文緊接上篇.Net架構篇:思考如何設計一款實用的分佈式監控系統?,上篇僅僅是個思考篇,跟本文沒有太大的關係。但有思考,結合現有的開源組件,實踐起來更易理解起來,因此看本文以前,應該先看下上篇博文。html
Zipkin是一種分佈式跟蹤系統。它有助於收集解決微服務架構中的延遲問題所需的時序數據。它管理這些數據的收集和查找。Zipkin的設計基於Google Dapper 論文。java
應用程序用於向Zipkin報告時序數據。Zipkin UI還提供了一個依賴關係圖,顯示了每一個應用程序經過的跟蹤請求數。若是要解決延遲問題或錯誤,能夠根據應用程序,跟蹤長度,註釋或時間戳對全部跟蹤進行篩選或排序。選擇跟蹤後,您能夠看到每一個跨度所需的總跟蹤時間百分比,從而能夠識別有問題的應用程序。git
啓動的三種方式程序員
docker run -d -p 9411:9411 openzipkin/zipkingithub
curl -sSL https://zipkin.io/quickstart.sh | bash -sweb
java -jar zipkin.jardocker
# get the latest source git clone https://github.com/openzipkin/zipkin cd zipkin # Build the server and also make its dependencies ./mvnw -DskipTests --also-make -pl zipkin-server clean install # Run the server java -jar ./zipkin-server/target/zipkin-server-*exec.jar
不管您以何種方式啓動zikpin,請訪問 http://your_host:9411以查詢跟蹤。api
應用程序中的監控器記錄有關發生的操做的時間和元數據,而且對用戶是透明的。如一個web監聽服務記錄了請求何時進來,何時離開。這個監控的數據叫作Span。緩存
將數據發送到Zipkin的檢測應用程序中的組件稱爲Reporter。bash
如圖所示
這是一個示例序列的http跟蹤,其中用戶代碼調用資源/ foo。這個結果是單個Span,在用戶代碼收到http響應後異步發送到Zipkin。
┌─────────────┐ ┌───────────────────────┐ ┌─────────────┐ ┌──────────────────┐
│ User Code │ │ Trace Instrumentation │ │ Http Client │ │ Zipkin Collector │
└─────────────┘ └───────────────────────┘ └─────────────┘ └──────────────────┘
│ │ │ │
┌─────────┐
│ ──┤GET /foo ├─▶ │ ────┐ │ │
└─────────┘ │ record tags
│ │ ◀───┘ │ │
────┐
│ │ │ add trace headers │ │
◀───┘
│ │ ────┐ │ │
│ record timestamp
│ │ ◀───┘ │ │
┌─────────────────┐
│ │ ──┤GET /foo ├─▶ │ │
│X-B3-TraceId: aa │ ────┐
│ │ │X-B3-SpanId: 6b │ │ │ │
└─────────────────┘ │ invoke
│ │ │ │ request │
│
│ │ │ │ │
┌────────┐ ◀───┘
│ │ ◀─────┤200 OK ├─────── │ │
────┐ └────────┘
│ │ │ record duration │ │
┌────────┐ ◀───┘
│ ◀──┤200 OK ├── │ │ │
└────────┘ ┌────────────────────────────────┐
│ │ ──┤ asynchronously report span ├────▶ │
│ │
│{ │
│ "traceId": "aa", │
│ "id": "6b", │
│ "name": "get", │
│ "timestamp": 1483945573944000,│
│ "duration": 386000, │
│ "annotations": [ │
│--snip-- │
└────────────────────────────────┘
跟蹤檢測報告以異步方式跨越,以防止與跟蹤系統相關的延遲或故障延遲或中斷用戶代碼。
由儀器庫發送的span必須從跟蹤到Zipkin收集器的服務傳輸。 主要支持三種傳輸: HTTP, Kafka 和 Scribe.
Zipkin有4個組件:
咱們建立了一個GUI,它爲查看跟蹤提供了一個很好的界面。Web UI提供了一種基於服務,時間和註釋查看跟蹤的方法。注意:UI中沒有內置身份驗證!
按照官方文檔說明。
using ZipkinTracer.DependencyInjection;
using ZipkinTracer.Owin;
public class Startup
{
public void Configuration(IApplicationBuilder app)
{
app.UseZipkinTracer();
}
public void ConfigureServices(IServiceCollection services)
{
var config = new ZipkinConfig(new Uri("http://XXX:9411"), request => new Uri("https://yourservice.com"))
{
Bypass = request => request.GetUri().AbsolutePath.StartsWith("/allowed"),
SpanProcessorBatchSize = 10,
SampleRate = 0.5
}
services.AddZipkinTracer(config);
}
}
//GetUri()方法報錯。
改爲以下方法:
public void Configuration(IApplicationBuilder app) { app.UseZipkinTracer(); } public void ConfigureServices(IServiceCollection services) { var config = new ZipkinConfig(new Uri("http://weixinhe.cn:9411")); services.AddZipkinTracer(config); services.AddZipkinTracer(config); }
客戶端調用
using ZipkinTracer.Http; public class HomeController : Controller { private readonly IZipkinTracer _tracer; public HomeController(IZipkinTracer tracer) { _tracer = tracer; } public async Task<ActionResult> Index() { using (var httpClient = new HttpClient(new ZipkinMessageHandler(_tracer)))) { var response = await httpClient.GetAsync("http://www.google.com"); if (response.IsSuccessStatusCode) { var content = await response.Content.ReadAsStringAsync(); } } return View(); } }
運行程序,報錯!
讓咱們去官網看看問題,issue 裏面有人提出了這個問題,
Registering zipkin tracer throws an error #10
下面有人回覆:意思是須要重寫中間件。
I have the same issue. According to the documentation, the dependencies in the middlewares should be moved into the Invoke method. In this case, the ZipkinMiddleware has to be changed in my opinion.
年久失修,做者未回覆。可是源碼都放在那裏了,難道任由其報錯而無能爲力麼?這我不能忍受。因此,下載源碼,引用源碼項目。開啓調試之路。
右鍵查看屬性,居然看不到目標框架。應該是版本過低了。
查看依賴版本是framework4.6和.netstandard 1.3
那好辦,咱們新建一個.netcore2.1版本的項目,而後將tracer的代碼都複製過去。 一些複製好並引用後,仍是剛纔那個錯。調試也沒有看到哪裏報錯,只是最終頁面報錯了。因此咱們繼續搜索。
Cannot consume scoped service 'XXXX' from singleton 'XXX'.
沒法從Singleton消耗Scoped服務 - ASP.net核心DI範圍的一課
此網站已收集在.NetCore外國一些高質量博客分享,長期保持更新。
上面三篇文章普及了一些依賴注入的知識。sorry,這塊我研究的很淺。。。此次順帶了解了很多,之後要抽空專門研究一下。
Single:單例是一個將持續應用程序整個生命週期的實例。在Web術語中,這意味着在服務的初始請求以後,每一個後續請求將使用相同的實例。這也意味着它跨越Web請求(所以,若是兩個不一樣的用戶訪問您的網站,代碼仍然使用相同的實例)。考慮單例的最簡單方法是,若是類中有靜態變量,則它是跨多個實例的單個值。
Scoped:範圍內的生命週期對象一般會簡化爲「每一個Web請求一個實例」,但實際上它比實際上更加微妙。無能否認,在大多數狀況下,您能夠將每一個Web請求視爲範圍對象。您可能會看到的常見問題是每一個Web請求建立一次DBContext,或者建立一次NHibernate上下文,以便您能夠將整個請求包含在事務中。做用域生存期對象的另外一個很是常見的用途是當您要建立每一個請求緩存時。 Scoped生命週期實際上意味着在建立的「範圍」對象中將是同一個實例。它剛好發生在.net核心中,它在「範圍」內包裝請求,但您實際上能夠手動建立範圍
Transient:每次請求服務時,都會建立一個新實例。
關於上述的相似錯誤沒法從單件服務 #2569中使用做用域服務'AutoMapper.IMapper',有用戶評論:
這是一個基本的設計約束。你不能讓單身人士(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.
繼續搜索新的這個錯誤。
Model bound complex types must not be abstract or value types and must have a parameterless constructor
asp.net mvc github的問題裏面討論的很激烈。我只能根據翻譯大概猜想意思了。
用於簡單模型 - 視圖模型 - 模型屬性映射的基本對象映射器
Asp.net Core中的自定義模型綁定,3:模型綁定接口
又get到一個網址:http://www.dotnet-programming.com,已更新到.NetCore外國一些高質量博客分享
您正在混淆依賴注入和模型綁定。有一個很大的不一樣。請考慮執行如下操做。 註冊IModelFactory爲服務:
public void ConfigureServices(IServiceCollection services) { services.AddSingleton<IModelFactory>(ModelFactory.Current); // Add framework services. services.AddMvc(); }
如今在您的控制器中,用於FromServices獲取實例,並使用如下內容獲取建立模型所需的值FromForm:
[HttpPost] public IActionResult CreateTemplate([FromForm] string name, [FromServices] IModelFactory factory) { var item = factory.CreateTechnicalTaskTemplate(name); repo.Templates.Add(item); return View(nameof(TemplatesList)); }
您的工廠應該被視爲一項服務。模型綁定須要POCO,而不是接口。
對不起,模型綁定這個錯,我沒看太懂,只能先放棄了。若是對着源碼都找不到解決辦法,我只能理解本身的知識太淺。。。時間也很晚了,程序員也是須要有業餘生活的。關於zipkintracer的試用到此爲止。下期使用官方推薦客戶端zipkin4net
。
看官們,大家也真的深刻了解依賴注入和模型綁定麼?
本篇旅程雖然失敗,但也瞭解了zipkin的相關介紹,原理,也在解決問題的過程當中加深了依賴注入的理解。模型綁定的概念還不是太清楚,抽空我再看看。真可謂:無意栽花花不成,無意插柳柳成蔭。來一句雞湯:努力向前走,總會有意想不到的收穫。
各大廠分佈式鏈路跟蹤系統架構對比 Net和Java基於zipkin的全鏈路追蹤
本篇到此結束,感謝觀看。