本文紧接上篇.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的全链路追踪
本篇到此结束,感谢观看。