微服务,通常都是用复杂的、大规模分布式集群来实现的。微服务构建在不同的软件模块上,这些软件模块,有可能是由不同的团队开发、可能使用不同的编程语言来实现、有可能布在了几千台服务器,横跨多个不同的数据中心。因此,就需要一些可以帮助理解系统行为、用于分析性能问题的工具。

API网关Ocelot 作为微服务的一个重要组件,出现在系统边界上的一个面向API的、串行集中式的强管控服务,这里的边界是企业IT系统的边界,主要起到隔离外部访问与内部系统的作用。通过API网关对外发布的通常是OpenAPI,在它的后面有众多的分布式应用,如微服务、消息收发、分布式数据库、分布式缓存、分布式对象存储、跨域调用,这些组件共同构成了繁杂的分布式网络。

当应用A发出某个请求时,其背后可能有数十个甚至更多的服务被调用,可谓是“牵一发而动全身”。 如果将分布式系统比作高速公路网,每个前端的请求就相当于高速上行驶的车辆,而处理请求的应用就是高速上的收费站,在收费站上将车辆通行信息记录成日志,包括时间、车牌、站点、公路、价格等,如果将所有收费站上的日志整合在一起,便可以通过唯一的车牌号确定该车的完整通行记录;分布式调用系统跟踪和监控就是类比这种思想,对每一次请求进行跟踪,进而明确每个请求所经过的应用、耗时等信息。

Butterfly被设计为分布式追踪和APM的Server端,它将包含Collector,Storage,独立的Web UI,并使用Open Tracing规范来设计追踪数据。目前仅根据规范实现了Open Tracing API,后续还会兼容google的opencensus。这里顺便提下为什么我们不用zipkin 或是Jaeger,他们只做了tracing,Butterfly比他们多一点就是同时要做metrics和预警,就是要做立体化监控系统。目前Butterfly也是在起步阶段,还有非常多的功能需要开发,目前有两个事情的优先级比较高一个应用程序进程级别的metrics,一个是后端collector和es的性能优化,欢迎各位同学加入一起开发,我们相信通过不断的建设,我们.NET社区一样可以达到Java的高度。回想Ocelot 的发展历程,2016年才是到现在已经开发了2年时间,完成了3.0版本的开发,现在已经是一个日趋成熟的API网关,通过API网关连接后面的服务,像今天和大家分享的最近我业余时间在开发的分布式跟踪的支持,这项任务在一年前提出来,https://github.com/TomPallister/Ocelot/issues/19 这里有我们的讨论,现在集成Butterfly 来实现这个功能,让我们的微服务能够可运维。

Butterfly.Client.AspNetCore 为我们提供了在ASP.NET Core项目集成Butterfly的组件,使用很简单,只需要在ConfigureServices 注册Butterfly services

public void ConfigureServices(IServiceCollection services)
{
//your other code
services.AddButterfly(option =>
{
option.CollectorUrl = "http://localhost:9618";
option.Service = "my service";
});
}

其中http://localhost:9618 是Butterfly的服务端,提供了UI,我们在浏览器通过http://localhost:9618 就可以访问到。

那么在API网关Ocelot 中集成Butterfly 有什么不一样呢? 我们在Ocelot项目中加入上述代码后,我们已经可以在Butterfly UI上看到我们的追踪数据,只是数据没有连成一条链。那么我们做集成的工作主要就是以下2点:

一、将追踪数据串起来,让我们可以在Butterfly UI上直观的看到各个节点的数据

二、Ocelot 本身需要加入到系统跟踪的数据定义

Ocelot 集成Butterfly 实现分布式跟踪的代码目前还没有加入主干,可以在我的代码库的分支https://github.com/geffzhang/Ocelot/tree/Monitoring 下看到,我们首先在Ocelot的路由配置中加入一个配置项,表示是否启用分布式追踪:

{
   "ReRoutes": [
     {
       "DownstreamPathTemplate": "/api/values",
       "DownstreamScheme": "http",
       "UpstreamPathTemplate": "/api/values",
       "UpstreamHttpMethod": [ "Get" ],
       "DownstreamHostAndPorts": [
         {
           "Host": "localhost",
           "Port": 5002
         }
       ],
       "HttpHandlerOptions": {
         "AllowAutoRedirect": true,
         "UseCookieContainer": true,
         "UseTracing": true
       }
     },

UseTracing 表示是否启用分布式追踪,默认为false,也就是不启用。 然后在Ocelot.DependencyInjection.IOcelotBuilder 加个接口方法:

方法的实现也非常简单:

主要就是加入Ocelot 本身需要加入到系统跟踪的数据定义,实现上主要使用DiagnosticSource, 官方的文档:https://github.com/dotnet/corefx/blob/master/src/System.Diagnostics.DiagnosticSource/src/DiagnosticSourceUsersGuide.md 。类似于asp.net core 有个 Diagnostics中间件https://github.com/aspnet/Diagnostics,主要功能是用于报告和处理ASP.NET Core中的异常和错误信息,以及诊断Entity Framework核心迁移错误。其中还有其他几项功能,欢迎页,错误代码页、如404 页等。以及一个还算不错的日志查看功能,这个功能也是很多人需要的功能,直接在线查看日志。

实现了Butterfly 的接口ITracingDiagnosticListener ,通过DI 注入后Butterfly 会帮我们注册好。

下面我们要把我们的分布式追踪数据串起来,OpenTracing(链接:opentracing.io)通过提供平台无关、厂商无关的API,使得开发人员能够方便的添加(或更换)追踪系统的实现。OpenTracing正在为全球的分布式追踪,提供统一的概念和数据标准。标准的中文版是我们的MVP吴晟翻译的,同时他也是OpenTracing的主要成员 : https://wu-sheng.gitbooks.io/opentracing-io/content/

在广义上,一个trace代表了一个事务或者流程在(分布式)系统中的执行过程。在OpenTracing标准中,trace是多个span组成的一个有向无环图(DAG),每一个span代表trace中被命名并计时的连续性的执行片段。

分布式追踪中的每个组件都包含自己的一个或者多个span。例如,在一个常规的RPC调用过程中,OpenTracing推荐在RPC的客户端和服务端,至少各有一个span,用于记录RPC调用的客户端和服务端信息。

一个父级的span会显示的并行或者串行启动多个子span。在OpenTracing标准中,甚至允许一个子span有个多父span(例如:并行写入的缓存,可能通过一次刷新操作写入动作)。

所以集成的关键点就在tracerId和spanId的关联关系的Id 处理上。

tracerid 代表是全局的id,类似于Ocelot的RequestId http://ocelot.readthedocs.io/en/latest/features/requestid.html,存放在http header 里,它的key是ot-traceid,所以在Ocelot里面可以把全局的RequestId设置为ot-traceid 。

同时还需要处理spanid,使得下游的的组件的spanid是它上一级的spanid,也是存放在http header 里,它的key是ot-spanId,我们在OcelotRequestTracer 以及OcelotHttpTracingHandler 需要处理spanid

上面我们说完了代码集成工作,我们来看看效果吧,我搭了一个Demo环境,服务前端—>Ocelot –>服务后端。Butterfly为每个请求生成全局唯一的ID(Traceld),通过它将不同系统的“孤立的”调用信息关联在一起,还原出更多有价值的数据。

上图是一条API调用请求的调用链,在Span列可以看到请求中间过程所经过的一系列应用组件,可以看到最先经过请求端的HttpClient组件,后续调用Ocelot、HttpClient、backend等,形成调用树(树上的缩进表示嵌套关系),从调用树上很容易看到前端请求的完整处理过程。在上图所示的页面中也清晰地展示了每块应用处理请求得具体耗时,非常直观地进行定位;此外,点击具体的组件,可以看到这个组件中的日志记录

对于分布式调用跟踪系统而言,它并不仅仅提供了调用链这一功能,因为它对所有中间件的调用做埋点,所以中间件上的所有情况都可以监控的到。因此,在形成调用链的过程中也会形成一份详细的调用监控报表,它与其他监控的不同之处在于:该监控报表是带有上下钻取功能的报表。因为调用链是详细的底层统计,对上可以形成的报表维度是非常丰富的,在上图所示的调用报表里,不仅可以看到服务的情况,还可以下钻到它所调用服务的情况;另外从监控报表上还可以进行调用链的下钻,查看清晰的调用链信息。目前Butterfly这块功能也是需要继续开发的功能,欢迎各位同学一起加入开发。

还有链路分析,链路与调用链不同,链路是一个统计学的概念,而调用链是单体调用的过程。分析链路的拓扑形态分析:分析来源、去向,识别不合理来源;

上图是全局调用拓扑图,可以明显的看到不同的服务之间存在复杂的调用关系,也可以查看某个服务和其他服务之间的调用关系以及调用的频次; 通过该拓扑图,架构师可以清楚地观察到系统上的调用情况。

Ocelot 集成Butterfly 实现分布式跟踪的更多相关文章

  1. .NET Core微服务之基于Ocelot+Butterfly实现分布式追踪

    Tip: 此篇已加入.NET Core微服务基础系列文章索引 一.什么是Tracing? 微服务的特点决定了功能模块的部署是分布式的,以往在单应用环境下,所有的业务都在同一个服务器上,如果服务器出现错 ...

  2. SpringBoot集成Zipkin实现分布式全链路监控

    目录 Zipkin 简介 Springboot 集成 Zipkin 安装启动 zipkin 版本说明 项目结构 工程端口分配 引入 Maven 依赖 配置文件.收集器的设置 编写 Controller ...

  3. 基于SkyWalking的分布式跟踪系统 - 微服务监控

    上一篇文章我们搭建了基于SkyWalking分布式跟踪环境,今天聊聊使用SkyWalking监控我们的微服务(DUBBO) 服务案例 假设你有个订单微服务,包含以下组件 MySQL数据库分表分库(2台 ...

  4. springCloud学习6(Spring Cloud Sleuth 分布式跟踪)

    springcloud 总集:https://www.tapme.top/blog/detail/2019-02-28-11-33 前言   在第四篇和第五篇中提到一个叫关联 id的东西,用这个东西来 ...

  5. 云原生 - Istio可观察性之分布式跟踪(三)

    作者:justmine 头条号:大数据与云原生 微信公众号:大数据与云原生 创作不易,在满足创作共用版权协议的基础上可以转载,但请以超链接形式注明出处. 为了方便阅读,微信公众号已按分类排版,后续的文 ...

  6. 手动造轮子——为Ocelot集成Nacos注册中心

    前言     近期在看博客的时候或者在群里看聊天的时候,发现很多都提到了Ocelot网关的问题.我之前也研究过一点,网关本身是一种通用的解决方案,主要的工作就是拦截请求统一处理,比如认证.授权.熔断. ...

  7. 使用 Spring Cloud Jaeger 进行分布式跟踪

    在本文中,学习如何实现 Jaeger(基于 OpenTracing 和 Spring Boot 应用程序)以及如何使用 Jaeger UI 可视化跟踪. 介绍 在本文中,我们将探讨如何使用 Jaege ...

  8. Spring Cloud Sleuth 和 Zipkin 进行分布式跟踪使用指南

    分布式跟踪允许您跟踪分布式系统中的请求.本文通过了解如何使用 Spring Cloud Sleuth 和 Zipkin 来做到这一点. 对于一个做所有事情的大型应用程序(我们通常将其称为单体应用程序) ...

  9. Zipkin分布式跟踪系统介绍

    Zipkin是什么Zipkin分布式跟踪系统:它可以帮助收集时间数据,解决在microservice架构下的延迟问题:它管理这些数据的收集和查找:Zipkin的设计是基于谷歌的Google Dappe ...

随机推荐

  1. 180114 用装饰器实现在不改变函数调用者的代码基础上,实现在函数执行前后分别打印"before" 和 "after"

    def bef_aft(func): #定义一个名为bef_aft的函数名 ,()里的是函数的参数,设置为func, 函数的参数分为实参和形参,有个参数传递的概念 ,下面有很多的解释 def PRin ...

  2. MYSQL的REPLACE和ON DUPLICATE KEY UPDATE使用

    REPLACE 我们在使用数据库时可能会经常遇到这种情况.如果一个表在一个字段上建立了唯一索引,当我们再向这个表中使用已经存在的键值插入一条记录,那将会抛出一个主键冲突的错误.当然,我们可能想用新记录 ...

  3. backbone 要点知识整理

    1.backbone 是个mvc的库,官方文档说它是个库,而不是个框架.库和框架的区别就是,库只是个工具,方便你的项目应用,不会改变你的项目结构,而框架会有一套自己的机制,项目需要遵循框架的设计来实现 ...

  4. python os 模块

    os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径os.chdir("dirname") 改变当前脚本工作目录:相当于shell下cdos.curdir ...

  5. UVAlive 3708 Graveyard(最优化问题)

    题目描述: 在周长10000的圆上,初始等距的放置着n个雕塑,现在新加入m个雕塑,要使得这n+m个雕塑仍然等距,问原来n个雕塑要移动的距离总和的最小值. 原题地址: http://acm.hust.e ...

  6. Codechef:Path Triples On Tree

    Path Triples On Tree 题意是求树上都不相交或者都相交的路径三元组数量. 发现blog里没什么树形dp题,也没有cc题,所以来丢一道cc上的树形dp题. 比较暴力,比较恶心 #inc ...

  7. HDU 4010 Query on The Trees

    Problem Description We have met so many problems on the tree, so today we will have a query problem ...

  8. STOI补番队互测#2

    Round2轮到我出了>_<(目测总共10人参加 实际共七人) 具体情况: #1: KPM,360 #2:ccz181078,160 #3:child,150 可惜KPM没看到第一题样例里 ...

  9. BZOJ1786: [Ahoi2008]Pair 配对/1831: [AHOI2008]逆序对

    这两道题是一样的. 可以发现,-1变成的数是单调不降. 记录下原有的逆序对个数. 预处理出每个点取每个值所产生的逆序对个数,然后dp转移. #include<cstring> #inclu ...

  10. Effective Java 第三版——23. 优先使用类层次而不是标签类

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...