微服务, 通常都是用复杂的大规模分布式集群来实现的微服务构建在不同的软件模块上, 这些软件模块, 有可能是由不同的团队开发可能使用不同的编程语言来实现有可能布在了几千台服务器, 横跨多个不同的数据中心因此, 就需要一些可以帮助理解系统行为用于分析性能问题的工具
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 组件, 后续调用 OcelotHttpClientbackend 等, 形成调用树(树上的缩进表示嵌套关系), 从调用树上很容易看到前端请求的完整处理过程在上图所示的页面中也清晰地展示了每块应用处理请求得具体耗时, 非常直观地进行定位; 此外, 点击具体的组件, 可以看到这个组件中的日志记录
对于分布式调用跟踪系统而言, 它并不仅仅提供了调用链这一功能, 因为它对所有中间件的调用做埋点, 所以中间件上的所有情况都可以监控的到因此, 在形成调用链的过程中也会形成一份详细的调用监控报表, 它与其他监控的不同之处在于: 该监控报表是带有上下钻取功能的报表因为调用链是详细的底层统计, 对上可以形成的报表维度是非常丰富的, 在上图所示的调用报表里, 不仅可以看到服务的情况, 还可以下钻到它所调用服务的情况; 另外从监控报表上还可以进行调用链的下钻, 查看清晰的调用链信息目前 Butterfly 这块功能也是需要继续开发的功能, 欢迎各位同学一起加入开发
还有链路分析, 链路与调用链不同, 链路是一个统计学的概念, 而调用链是单体调用的过程分析链路的拓扑形态分析: 分析来源去向, 识别不合理来源;
上图是全局调用拓扑图, 可以明显的看到不同的服务之间存在复杂的调用关系, 也可以查看某个服务和其他服务之间的调用关系以及调用的频次; 通过该拓扑图, 架构师可以清楚地观察到系统上的调用情况
来源: https://www.cnblogs.com/shanyou/p/8413506.html