背景
随着微服务技术的发展和普及,复杂的单体应用被逐渐地拆分成多个简单的服务。随着各应用系统不断地被拆解,服务的规模以及服务间调用关系的复杂度也不断地扩大,在这种复杂的调用关系和庞大的服务规模下,问题的排查和优化的性能,不管是研发同学或者运维同学来说无疑是盲人摸象。
Google在2010年发布的一篇名为《Dapper, a Large-Scale Distributed Systems Tracing Infrastructure》,论文中提出了一个分布式链路追踪的概念,它提到:每次请求都生成唯一的ID,跨实例请求的的时候将这个ID传递到对端,同时记录每一个方法的开始时间和结束时间,最终这次请求通过追踪ID进行串联,形成一张有向无环图,图中的每个节点都代表个方法,图中的关系代表方法的执行顺序和关系。
上面这图,左边是微服务下一次请求的执行过程,右边是最终产生的Trace图,开发同学或者运维同学通过这张图可以直观地看出一次请求所经过的所有应用,方法以及调用关系,快速定位业务故障和性能瓶颈。监控系统对于快速定位分析问题非常重要,大量的开源和商业解决方案不断涌现,比如Jaeger,Open Telemetry, Apache SkyWalking,Zipkin等开源方案和LightStep,AppDynamics,New relics等APM厂商。
Jaeger简介
Jaeger是Uber开发的分布式追踪系统。 2017年4月份开源,9月进入CNCF孵化;2019年10月正式从CNCF毕业,成为了CNCF顶级项目。下图是Jaeger的架构图, 两种结构大致相同,区别在于collector和DB之间加Kafka做缓冲,用来解决峰值流量过载问题。Jaeger同时支持多种后端存储,目前支持的数据存储包括:内存,Badger,Cassandra,Elasticsearch,GRPC插件。
Jaeger的高可靠方案
Jaeger作为一个可观察性/监控系统的组成部分,是开发和运维同学定位和发现业务系统问题的重要数据来源,而作为SRE,我们一定要保证监控系统比业务系统活的更久。一旦监控系统先于业务系统down掉,监控完全没有价值。可以说监控是业务异常分析最后的一道屏障,它相比于其他系统来说,对于高可用和高性能更加敏感。
而Jaeger作为一个开源项目,它本身只提供解决方案,并不会提供部署规模的评估方案和服务如何保证高可用的方案,这需要运维同学基于对服务高可用的经验和对业务系统规模的调研的给出具体部署方案。这种情况下怎么去提供高可用和高性能的后端服务?谁去为监控系统提供最后一层保障?
首先我们从部署架构分析Jaeger系统在高可用上需要着重优化的点(这里我们以上图右侧社区最新的方案为例):
- Jaeger Client和Agent都是随应用直接部署到服务器上,相对来说稳定性较强,只需要保证Agent到后端网络的质量即可。
- 新的部署模式为了解决流量突增的问题,增加了Kafka队列作为缓冲,但我们注意不是说只要有Kafka就能应对,我们还需要考虑Kafka本身能否有足够的资源来动态扩容;同样Collector的转发能力、Flink的流计算能力和Ingester的导入能力也需要随着流量突增而动态扩容。
- 部署方案中Kafka和DB(ES、Cassandra等)是带状态的服务,需要用多副本的方式去部署,保证可靠性。
- 此外,为了保证查询效率(尤其在报错突增的情况下),在大数据量的时候还需要对ES、Cassandra进行调优,这里涉及的工作会更多。
- Jaeger的后端系统涉及的组件比较多,还需要额外部署一套监控,用来监控Jaeger后端的稳定性和性能问题,配置好告警,及时去处理这些突发情况。
上述这些工作实施起来相比简单部署一套Jaeger的工作量大非常多,而且后面还要持续投入人力在运维和管理这套系统中,因此最简单的方式还是有服务化的产品来直接使用。
SLS作为Jaeger的后端
其实Jaeger的高可用最核心的部分是Jaeger后端(包括Collector、Kafka、Flink、DB、Query、UI),我们最好的方式是寻找一个能够兼容Jaeger的后端系统,提供高可靠、高性能的能力。
而SLS最近发布的Trace服务恰巧可以完美解决这个问题。SLS最大的一个特点就是高性能、弹性和免运维,让用户轻松应对激增流量或者规模评估不准确的问题,SLS服务本身提供99.9%的可用性以及11个9的数据可靠性。
一般情况下,我们希望用两种不同的方式来替换Jaeger的后端:
- 原生的数据用Jaeger SDK产生,查询模式继续使用Jaeger的UI,这样对于应用开发同学来说继续沿用之前的使用模式
- 原生的数据用Jaeger SDK产生,使用查询使用SLS提供的Trace UI,相比Jaeger UI,SLS的Trace功能要强大的多,包括Trace指标计算、Dependency分析、自定义分析等,相关的功能介绍可以参考:SLS Trace1.0介绍、SLS Trace1.1介绍
接入方式
SLS的Trace服务为各个开源的链路追踪提供易于各个开源软件接入的后端服务,统一的数据模型和性能分析能力。SLS可以完全兼容Jaeger的部署模式,目前提供了两种接入方式,分别应对上述的两类需求:
- 原生Jaeger接入方式,只是把SLS当做Jaeger的后端存储,使用上还可以用原来的Jaeger UI(当然也可以登录到SLS使用SLS的Trace功能)
- 简化版Jaeger接入方式,只是使用Jaeger的数据接入,后续所有功能都使用SLS自身提供的Trace功能
原生Jaeger接入方式
原生Jaeger接入方式是采用了混合模式,Jeager UI作为前端,SLS作为存储后端。已习惯Jaeger页面操作的用户,多了一种接入方式。
以下是原生Jeager接入步骤,更详细的参数配置和容器部署方式请参考github
- 登陆SLS控制台,并创建用于存储Span的Project
- 登陆SLS实例列表,并创建一个Trace实例。注: Project选择上一步创建的Project
- 进入Jaeger下载页面,下载并解压Jaeger包
- 启动Agent。下面执行的命令以MacOS为例。
./agent-darwin --collector.host-port=localhost:14267
- 启动Jaeger Collector
export SPAN_STORAGE_TYPE=aliyun-log-otel && \
./collector-darwin \
--aliyun-log.project=<PROJECT> \
--aliyun-log.endpoint=<ENDPOINT> \
--aliyun-log.access-key-id=<ACCESS_KEY_ID> \
--aliyun-log.access-key-secret=<ACCESS_KEY_SECRET> \
--aliyun-log.span-logstore=<SPAN_LOGSTORE> \
--aliyun-log.init-resource-flag=false
- 启动UI
export SPAN_STORAGE_TYPE=aliyun-log-otel && \
./query-darwin \
--aliyun-log.project=<PROJECT> \
--aliyun-log.endpoint=<ENDPOINT> \
--aliyun-log.access-key-id=<ACCESS_KEY_ID> \
--aliyun-log.access-key-secret=<ACCESS_KEY_SECRET> \
--aliyun-log.span-logstore=<SPAN_LOGSTORE> \
--aliyun-log.span-dep-logstore=<SPAN_DEP_LOGSTORE> \
--aliyun-log.init-resource-flag=false \
--query.static-files=./jaeger-ui-build/build/
下面是各参数详细描述
参数名 |
描述 |
PROJECT |
指定用于存储 Span 的 Project |
ENDPOINT |
指定用于存储 Span 的 Project 所在的 Endpoint。 其格式为
|
ACCESS_KEY_ID |
指定用户标识 Access Key ID |
ACCESS_KEY_SECRET |
指定用户标识 Access Key Secret |
SPAN_LOGSTORE |
指定用于存储 Span 的 Logstore,名称为 |
SPAN_DEP_LOGSTORE |
指定用于存储Service调用关系的Logstore,名称为 |
简化版Jaeger接入方式
简化版的数据提供了两种接入方式:Jaeger直发模式和Jaeger转发模式。直发模式部署简单,需要每个Agent都有连接SLS的能力;转发模式支持更高级的流控和和下面分别介绍这两种方式。
直发模式
直发模式是通过在jaeger agent端配置上SLS地址,将Trace直接发送SLS后端,该方式最大的好处就是不用部署Jaeger Collector实例。以下是直发模式下启动参数命令。
./jaeger-agent --reporter.grpc.host-port=${ENDPOINT} --reporter.grpc.tls.enabled=true --agent.tags=sls.otel.project=${PROJECT},sls.otel.instanceid=${INSTANCE},sls.otel.akid=${ACCESS_KEY_ID},sls.otel.aksecret=${ACCESS_SECRET}
以下是各个参数的详细描述:
参数 |
描述 |
ACCESS_KEY_ID |
阿里云账号AccessKey ID。 建议您使用只具备日志服务Project写入权限的RAM用户的AccessKey(包括AccessKey ID和AccessKey Secret)。 |
ACCESS_SECRET |
阿里云账号AccessKey Secret。 建议您使用只具备日志服务Project写入权限的RAM用户的AccessKey。 |
PROJECT |
日志服务Project名称。 |
INSTANCE |
Trace服务实例名称。 |
ENDPOINT |
接入地址,格式为
|
转发模式
转发模式通过OpenTelemetry Collector统一收集jaeger-agent传入的Span数据,并将Trace数据统一发送到后端。下面是转发模式的部署步骤:
- 下载Collector
OpenTelemetry Collector下载地址: https://github.com/open-telemetry/opentelemetry-collector-contrib/releases/tag/v0.30.0
- 新增配置文件
新增config.yaml配置文件,并根据实际情况修改配置内容,配置中的参数解释参考直发模式中的参数解释。
receivers:
jaeger:
protocols:
grpc:
endpoint: 0.0.0.0:6831
thrift_binary:
endpoint: 0.0.0.0:6832
thrift_compact:
endpoint: 0.0.0.0:6833
thrift_http:
endpoint: 0.0.0.0:6834
exporters:
logging/detail:
loglevel: debug
alibabacloud_logservice/sls-trace:
endpoint: "{ENDPOINT}"
project: "{PROJECT}"
logstore: "{LOGSTORE}"
access_key_id: "{ACCESS_KEY_ID}"
access_key_secret: "{ACCESS_KEY_SECRET}"
service:
pipelines:
traces:
receivers: [jaeger]
exporters: [alibabacloud_logservice/sls-trace]
# for debug
#exporters: [logging/detail,alibabacloud_logservice/sls-trace]
- 运行Collector
启动命令如下:
./otelcontribcol_linux_amd64 --config="PATH/TO/config.yaml"
SLS Trace功能速览
Trace依赖分析可以自动计算并生成Trace的依赖拓扑,相比Jaeger增加了非常多的指标计算,包括QPS、错误率、平均延迟、PXX延迟等。
Trace列表显示所上传的Span的概览信息,同时搜索框支持基于Span的Attribute、Tag、延迟时间等条件进行组合搜索。
Trace详情页面展示了各个方法执行的耗时,调用关系以及span的信息。
两种接入方式对比
上述两种方式都可以完成Jaeger Trace数据的接入和使用,下面我们总结一下两种方式的一些异同点。
原生Jeager接入方式 |
简化版Jaeger接入方式 |
|
可靠性 |
较强,需要保证Query UI服务的稳定性 |
强 |
数据处理能力 |
强 |
强 |
部署复杂度 |
较低,需要额外部署一套Query UI的服务 |
低,除了接入之外,无需部署任何组件 |
定位和发现故障能力 |
一般(也可以使用SLS提供的Trace UI)
|
强
|
使用习惯 |
保留了jaeger的页面,无需调整用户习惯 |
需要调整用户习惯 |
整体而言,简化版本的jaeger接入更胜一筹,因为作为一个监控系统,监控系统是需要让用户快速地定位和发现故障,所以定位和发现故障的能力需要首先考虑,通过查看service和Span级别的Metric,可以快速的过滤一些出现异常的service和Span,再通过基于Span的属性的多条件查询能力,快速的定位和发现异常的Trace,从而快速的分析和定位问题所在。
总结
Jaeger作为OpenTracing协议的代表实现,在CNCF也是顶级的Project,还是非常受欢迎的Project。但如果你的公司正在新建设一套Trace系统,那不建议使用Jaeger的方案,因为最近OpenTracing已经和OpenCensus合并成了OpenTelemetry,后续Trace的统一标准是OpenTelemetry方案。所以还是建议大家直接去使用原生的OpenTelemetry的Trace。相关的介绍可以参考:《OpenTelemetry统一方案》、《OpenTelemetry Trace方案》。