微服务架构盛行,服务拆分边界更加细粒度,完成一次完整的业务逻辑,需要调用不同的微服务,
微服务有可能是由不同的团队开发、可能使用不同的编程语言来实现、有可能布在了几千台服务器,
横跨多个不同的数据中心,因此,就需要一些可以帮助理解系统行为、用于分析性能问题的工具,
以便发生故障的时候,能够快速定位和解决问题。
全链路监控理论模型基本都是依赖于Google Dapper论文
SkyWalking架构的基本设计原则包括易于维护、可控和流式处理。 为了实现这些目标,SkyWalking后端采用以下设计。
SkyWalking后端基于纯模块化设计。用户可以根据自己的需求切换或组装后端功能。
模块定义了一组特性,这些特性q可以包括技术库(如:gRPC/Jetty服务器管理)、跟踪分析(如:跟踪段或zipkin span解析器)或聚合特性。 这些完全由模块定义及其模块实现来决定。
每个模块都可以在Java接口中定义它们的服务,每个模块的提供者都必须为这些服务提供实现者。 提供者应该基于自己的实现定义依赖模块。这意味着,即使两个不同的模块实现者,也可以依赖不同的模块。
此外,后端模块化core还检查启动序列,如果没有发现周期依赖或依赖,后端应该被core终止。
后端启动所有模块,这些模块的配置在application.yml中是分离的。在这个yaml文件中:根级别是模块名称,例如cluster、naming等。 第二级别是模块的实现者的名称,例如zookeeper是cluster等模块。第三级是实现者的具体属性。例如hostPort和sessionTimeout是zookepper的必需属性。
首先,后端提供两种类型的连接,也即提供两种协议(HTTP和gRPC): HTTP中的命名服务,它返回后端群集中的所有可用collector地址。 在gRPC(SkyWalking原生探针的主要部分)和HTTP中使用上行链路服务,它将跟踪和度量数据上传到后端。 每个客户端将只向单个collector发送监视数据(跟踪和度量)。如果与连接的后端在某个时刻断开连接将会尝试连接其它的后端。比如在SkyWalking Java探针中collector.servers表示命名服务,将naming/jetty/ip:port映射为HTTP请求地址。collector.direct_servers表示直接设置上行服务,并使用gRPC发送监控数据。
当Collector以群集模式运行时,后端必须以某种方式相互发现。默认情况下,SkyWalking使用Zookeeper进行协调,并作为实例发现的注册中心。
通过以上部分(多个连接方式),客户端库将不会使用Zookeeper来查找集群。我们建议客户不要这么做。因为集群发现机制是可切换的,由模块化核心提供。依赖它会破坏可切换能力。 我们希望社区提供更多的实现者来进行集群发现,例如Eureka,Consul,Kubernate等。
流模式类似轻量级storm/spark的实现,它允许使用API构建流处理图(DAG)以及每个节点的输入/输出数据协定。
新模块可以查找和扩展现有的流程图。
处理中有三种情况
同步过程,传统方法调用。 异步过程,又叫做基于队列缓冲区的批处理。 远程过程,汇总后端的汇总。以这种方式,在节点中定义选择器以决定如何在集群中找到collector。(HashCode,Rolling,ForeverFirst是支持的三种方式) 通过具备的这些功能,collector集群像流式网络一样运行着去聚合、度量标准监控信息,并且不依赖于存储模块的实现来支持并发地编写相同的度量id。
由于流模式负责并发,因此存储模块的实现的职责是提供高速写入和组合查询。
目前,我们支持ElasticSearch作为主要实现模块,H2用于预览版本,以及由Sharding Shpere项目管理的MySQL关系数据库集群。
除了后端设计的原则,UI是SkyWalking的另一个核心组件。它基于React,Antd和Zuul代理实现,提供后端集群发现、查询调度和可视化的功能。
Web UI以多连接方式中的相似的流程机制作为客户端的1.naming、2.uplink。唯一的区别是,在ui/jetty/yaml定义下的主机和端口上(默认值:localhost:12800)用HTTP绑定中的GraphQL查询协议替换上行。
OAP(可观察性分析平台)是一个新概念,从SkyWalking 6.x开始。 OAP取代旧的SkyWalking整个后端。该平台的功能如下。
OAP功能 OAP接受来自更多来源的数据,这些来源属于两个组:跟踪和指标。
像往常一样,gRPC和HTTP协议提供的所有服务使得不受支持的生态系统更容易集成。
SkyWalking 5系列的传统方式。使用SkyWalking跟踪段和跨度格式格式化跟踪数据,甚至是Zipkin数据格式。 AOP分析段以获取度量,并将度量数据推送到流聚合中。 考虑仅跟踪某些类型的日志记录。只需为跟踪提供保存和可视化功能。 此外,SkyWalking接受来自其他项目的跟踪格式,例如Zipkin,Jeager,OpenCensus。这些格式也可以用两种方式处理。
度量数据在流模式下在AOP集群内聚合。请参阅Observability Analysis Language,它提供了以脚本样式进行聚合和分析的简便方法。
提供OAL(可观察性分析语言)以分析流模式下的传入数据。OAL侧重于服务,服务实例和端点中的度量。因此,语言易于学习和使用。考虑到性能,读取和调试,OAL被定义为编译语言。 OAL scrips将在包阶段编译为普通Java代码。
在SkyWalking中,探测意味着集成到目标系统中的代理或SDK库,负责收集包括跟踪和度量的遥测数据。基于目标系统技术堆栈,探针可以使用非常不同的方法来实现。但最终它们是相同的,只需收集并重新格式化数据,然后发送到后端。
在高级别中,所有SkyWalking探测器中都有三个典型组。
基于语言的本地代理。这种代理在目标服务用户空间中运行,就像用户代码的一部分一样。如SkyWalking Java代理,使用-javaagent命令行参数在运行时操作代码,操作意味着更改并注入用户代码。另一种代理使用目标库提供的一些钩子或拦截机制。所以你可以看到,这些基于语言和库的代理。
服务网格探测器。 ServiceMesh探针从服务网格或代理中的边车,控制面板收集数据。在过去,代理仅用作整个集群的入口,但是使用ServiceMesh和sidecar,现在我们可以基于此进行观察。
第三方探针库。 SkyWalking接受其他链路数据格式。它分析数据,将其转换为跟踪,度量或两者的SkyWalking格式。此功能从接受Zipkin跨度数据开始。有关其他示踪剂的信息,请参阅Receiver以了解更多信
您不需要同时使用基于语言的本机代理和ServiceMesh探针,因为它们都收集度量标准数据。因此,您的系统会遭受两倍的有效负载,并且分析数量会翻倍。
使用这些探针有几种推荐方法: 仅使用基于语言的本机代理。 仅使用第三方探针库,如Zipkin探针生态系统。 仅使用Service Mesh探针。 在跟踪状态中使用Service Mesh探针与基于语言的本机代理或第三方仪器库。 (高级用法) 另外,举个例子,跟踪状态是什么意思?
默认情况下,基于语言的本机代理和第三方探针库都会将分布式跟踪发送到后端,后端会对这些跟踪进行分析和聚合。在跟踪状态意味着,后端将这些跟踪视为日志,只保存它们,并构建跟踪和指标之间的链接,例如跟踪所属的端点和服务?
接下来是什么? 在Service auto instrument agent,Manual instrument SDK,Service Mesh probe和Zipkin receiver中学习SkyWalking支持的探针。 在了解了探针之后,请阅读后端概述以了解分析和持久性。
服务自动工具代理是基于语言的本机代理的子集。在这种代理中,它基于某些语言特定的功能,通常是基于VM的语言。
Auto Instrument是什么意思? 很多用户都知道这些代理人听到他们说不需要改变任何一行代码,SkyWalking过去常常把这些话放在我们的自述文件中。但实际上,这是对与错。对于最终用户,YES,他们不需要更改代码,至少在大多数情况下。但也是NO,代码仍然由代理更改,通常在运行时称为操作代码。基础上,它只是自动探针代理,包括有关如何通过VM接口更改代码的代码,例如通过javaagent premain在Java中更改类。
此外,我们说大多数自动探针代理都是基于VM的,但实际上,您可以在编译时构建工具,而不是运行时。
有什么限制?自动探针非常酷,您也可以在编译时创建它们,不依赖于VM功能,那么有没有限制?
答案肯定是肯定的。它们是: 在大多数情况下可以进行过程传播。在许多高级语言中,它们用于构建业务系统,例如Java和.NET。大多数业务逻辑代码在每个请求的同一个线程中运行,这使得传播可以基于线程Id和堆栈模块以确保上下文是安全的。
只是影响框架或库。由于代理更改代码,这也意味着代理插件开发人员已经知道代码。因此,这种探测器中始终存在受支持的列表。像SkyWalking Java代理支持的列表。
跨线程不能一直支持。就像我们在流程传播中所说的那样,大多数代码在每个请求的单个线程中运行,尤其是业务代码。但在其他一些场景中,他们在不同的线程中执行操作,例如作业分配,任务池或批处理。或者某些语言提供协同程序或类似的东西,如Goroutine,然后开发人员可以运行低负载的异步过程,甚至鼓励。在这些情况下,仪表大盘将面临问题。
因此,对于汽车仪表来说,没有什么神秘之处,简而言之,代理开发人员会编写激活程序来使仪器代码工作。就这些。
接下来是什么? 如果您想了解SkyWalking中的手动仪器库,请参阅手动仪器SDK部分
理论基础
核心概念 trace和traceId:trace是全局监控系统的一次跟踪(用traceId标示一次跟踪,贯穿整个跨进程请求),多个span信息,及其关系信息。
span:一个span代表系统中具有开始时间和执行时长的逻辑运行单元。span之间通过嵌套或者顺序排列建立逻辑因果关系,包含logs和tags。
Logs:每个span可以进行多次Logs操作,每一次Logs操作,都需要一个带时间戳的时间名称,以及可选的任意大小的存储结构。
tags: 每个span可以有多个键值对(key:value)形式的Tags,Tags是没有时间戳的,支持简单的对span进行注解和补充,在一个span的生命周期有效不能跨越span传递。
SpanContext: SpanContext跨越进程边界,传递到下级span的状态。(例如,包含trace_id, span_id, sampled、baggage等数据),并用于封装Baggage.
Baggage: 存储在SpanContext中的一个键值对集合,在整个trace链路生命周期有效,可以跨越span、跨越进程进行传递.
ActiveSpan: 当前线程的活跃Span,对Span做了封装,也可以理解为一个Span的指针.
inject: SpanContext要做跨进程(如RPC)传输的时候,把SpanContext中的数据序列化到传输协议中。
extract: 与inject对应,从传输协议里,抽取数据反序列化成SpanContext。