技术分享 | jaeger链路日志实现

源宝导读:随着企业应用越来越复杂,内部的调用链条越来越长,性能问题也变得越来越难以定位和排查,为了应对此问题,我们在移动平台中引入了“jaeger调用链追踪工具”,帮助我们高效定位云端服务的性能问题。本文将分享我们相关的技术实践。

一、背景

    大家好,很幸运代表团队和大家分享一下,天际-移动平台团队在实现分布式链路日志追踪过程的心路历程。移动应用的后台服务,其内部调用链路往往很复杂,一旦发现性能问题,很难快速精准的定位,严重影响研发小伙伴们的幸福感。具体问题表现在这几个方面:

  • 容器内日志简单,某些前后端数据不一致导致的的问题无法定位。

  • PaaS小程序微服务化,服务之间调用虽然有严格规定,但是出现问题时还是无法快速定位问题的出处。

  • 测试人员登记bug需要粘贴详细的请求、响应,开发通过创造数据,模拟这个请求来慢慢排查问题所在。

二、技术选型

移动平台中关于PaaS小程序后端的现有架构:

    从上图中可知,我们当前同时支持了PHP、Go、Nodejs三种编程语言构建的应用,如果要做日志的链路追踪,起码需要兼容多编程语言。

    通过分析,我们总结出“日志追踪工具”应满足的条件:

  • 支持多语言。保证PHP、Go、Nodejs都可以接入日志,才能形成完整链路。

  • 一定是无侵入式的。这样在多个服务中埋点比较方便,日志服务升级维护成本也不会高。

  • 对于特定标签的日志可以通过微信、邮箱甚至短信的方式通知到开发或者运维同学。

  • 能够对API接口的性能统计分析。

  • 由于我们使用的阿里云日志,日志服务最好可以将阿里云日志作为数据存储。

三、jaeger工具介绍

3.1、简介

    Jaeger是由Uber开源的分布式追踪系统,一套完整的Jager追踪系统包括Jaeger-client、Jaeger-agent、Jaeger-collector、Database和Jaeger-query UI等基本组件。

3.2、Jaeger的优势

  • 采用Open Tracing标准,支持跨语言。

  • 分布式上下文传播。

  • 分布式是链路追踪。

  • 服务依赖性分析。

  • 性能延迟监控。

3.3、jaeger的技术原理

架构图:

  • jaeger-client:jaeger 的客户端,实现了opentracing协议。

  • jaeger-agent:jaeger-client 的一个代理程序,client将收集到的调用链数据发给agent,然后由agent发给collector。

  • jaeger-collector:负责接收jaeger client或者jaeger agent上报上来的调用链数据,然后做一些校验,比如时间范围是否合法等,最终会经过内部的处理存储到后端存储。后端存储是一个可插拔的组件,Jaeger on Aliyun Log Service 增加了对阿里云日志服务的支持。

  • jaeger-query:专门负责调用链查询的一个服务,有自己独立的UI。

  • spark-job:基于spark的运算任务,可以计算服务的依赖关系,调用次数等。

    说明:其中jaeger-collector和jaeger-query是必须的,其余的都是可选的,我们采用agent上报的方式,让客户端上报日志到agent,以减少部分性能消耗。jaeger-collector支持Aliyun Log Service,也是很好的满足我们要求。

    aliyun-log-jaeger-collector配置表:

3.4、日志

单条链路:

    可以清晰的看到一个请求的发起时间,所经过的服务数量、所调用服务的依赖关系、消耗的时长等信息。

3.5、技术名词解释

  • service:微服务的名称或者标识。

  • operation:一个span的名称,简单易读。

  • span:系统中具有开始时间和执行时长的逻辑运行单元 。具体可以理解为一次方法调用, 一个程序块的调用或者一次RPC/数据库访问。

  • tags:“键值对”形式的tags,一个span可以有多tags,tags是对span的简单注解,不会被子级span继承。tags value 的标准含义看参考https://opentracing.io/ specification/conventions

  • logs:一个span可以有多logs,每一个logs都可以自定名称以及任意大小的存储结构。

  • spanContext:跨进程边界,传递到下级span的状态,每个span都有访问spanContext的方法。当在创建span时,向传输协议Inject(注入)从上级span传输协议中Extract(提取)的spanContext既可。

  • Inject and Extract:spanContext可以通过Injected操作向Carrier增加,或者通过ExtractedCarrier中获取,跨进程通讯数据。通过这种方式,SpanContexts可以跨越进程边界,并提供足够的信息来建立跨进程的span间关系(因此可以实现跨进程连续追踪)。

四、落地应用

4.1、  核心设计思路:

  • 采用jaeger-client上报数据到jaeger-agent,再由jaeger-agent集中处理传输到jaeger-collector,之后jaeger-collector会将合法的数据存储到阿里日志。

  • 之后在我们需要时,可以通过jaeger-query + jaeger-ui来查询日志。

  • 我们采用jaeger的默认方式,将spanContext中跨进程数据(当前只有uber-trace-id)注入到header中,当下游服务在请求header中提取到对应的跨进程数据就会形成一个依赖和链路关系,如果没有就生成一个新的供下游服务发现和关联。

4.2、traceId传递方式

//  上游服务将traceId注入到header中$header = TraceJaeger::inject($header);
// 下游服务解析获取traceId,完成一个请求的传递
$target = [];
foreach (request()->headers->all() as $key => $value) {$target[$key] = Arr::first($value);
}
$spanContext = $this->tracer->extract(TEXT_MAP, $target);

4.3、应用结果

串行

traceId:1660cc5871c2df9e1660cc5871c34a59

并行

traceId:1660d1de34f6c7691660d1de34f5a93b

    以上都是我们实际的调用场景,应用创建的改造前(串行),改造后(并行)。可以很清晰的看到服务之间的调用和所花费的时间。

    我们打开可以看到app-service这个服务被调用的详细信息。包括请求方式、请求数据、响应数据等。

4.4、兼容Go语言

1、go服务gin中间件使用开源框架,代码仓库:https://github.com/yuchanns/bullets

go get -u github.com/yuchanns/bullets

2、中间件使用:

package main
import ("context""github.com/gin-gonic/gin""github.com/yuchanns/bullets/common""github.com/yuchanns/bullets/common/middlewares""os"
)
func main() {g := gin.Default()//服务名serviceName := "openapi-service"//上报agent地址agentAddr := os.Getenv("OPENTRACING_AGENT")//操作前缀operationPrefix := []byte("api-request-")opentracerCloseFunc, opentracerMiddleware, err := middlewares.BuildOpenTracerInterceptor(serviceName, agentAddr, operationPrefix)if err != nil {common.Logger.Error(context.Background(), err)} else {defer opentracerCloseFunc()g.Use(opentracerMiddleware)}
}

3、自定义打tag:

import ("github.com/gin-gonic/gin""github.com/opentracing/opentracing-go""github.com/opentracing/opentracing-go/log""github.com/pkg/errors"
)
func CustomTag(ctx *gin.Context) {if cspan, ok := ctx.Get("tracing-context"); ok {if span, ok := cspan.(opentracing.Span); ok {span.SetTag("error", true)span.LogFields(log.Error(errors.New("err")))span.LogFields(log.String("exampleKey", "stringValue"))}}
}

4.5、兼容PHP语言

1、安装composer包

composer require tracelog/jaeger

2、根目录执行

php artisan vendor:publish

3、选择发布配置⽂件

Tracelog\jaeger\config\jaeger.php文件拷贝到工程项目的config⽬录

4、修改配置⽂件

return['enabled' => env('JAEGER_ENABLED', true), //是否开启'service_name' => env('JAEGER_SERVICE_NAME', env('APP_NAME', 'Laravel')), //服务名称'agent' => [ 'host' => env('OPENTRACING_AGENT','0.0.0.0:6831'), //日志服务代理 地址],'watchers' => [Tracelog\jaeger\watchers\RequestWatcher::class, //请求日志监听Tracelog\jaeger\watchers\FrameworkWatcher::class //项目日志推送]
]

使⽤ jukylin/jaeger-php 直接记录。

参考:https://github.com/jukylin/jaeger-php/blob/master/example/HTTP.php

4.6、集成到Laravel Log

    使⽤框架中Log⻔⾯时,也可以将日志记录到代理。针对当前框架情况修改(添加)/app/Common/StreamHandler ---> Handle

if (config('jaeger.enabled')){$span = TraceJaeger::client()->startSpan($record['message'],['child_of' => TraceJaeger::getRootSpan()]);$span->setTag('log.level', $record['level_name']);$span->log($record['context']);$span->finish();TraceJaeger::client()->flush();
}

说明:对Nodejs的兼容,我们目前正在实现中。

五、总结

    自从链路日志工具上线后,我们排查问题的效率有了很大提升。我们可以直接通过日志定位出有问题的后端服务,通过请求和响应数据快速判断问题原因,极大的提高了工作效率和排查问题的幸福感!

------ END ------

作者简介

智同学: 研发工程师,目前负责天际-移动平台的研发工作。

也许您还想看

记AWSS3在iOS端的一次改造事件

明源云创CI/CD技术演进

微前端架构在容器平台的应用

AI云店小程序演变之路

天眼探针基于rrweb实现前端异常视频录制与回放功能

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/303398.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IT资料,重磅来袭!

现在IT行业越来越火爆,技术的更新也越来越快,不好好充实自己的话,就会被淘汰。小编这几年一直有意识地收集IT行业相关的资料,现在已经拥有8G左右的资料,如区块链、Python、大数据、人工智能深度学习等方面的资料&#…

开启php的文件上传扩展,linux中如何通过php.ini添加扩展?

在编译安装的时候,我只通过了以下命令来安装,然后我想像windows中那样修改 php.ini 就开启了扩展./configure \--enable-fpm \--with-fpm-userwww-data \--with-fpm-groupwww-data \--enable-soap \--enable-mysqlnd \--with-mysqlimysqlnd \--with-pdo-…

[C#.NET 拾遗补漏]16:几个常见的TAP异步操作

在本系列上一篇文章 [15:异步编程基础] 中,我们讲到,现代应用程序广泛使用的是基于任务的异步编程模式(TAP),历史的 EAP 和 AMP 模式已经过时不推荐使用。今天继续总结一下 TAP 的异步操作,比如…

荐书 | 10本书给你计算机大师思维

《黑客与画家》作者:保罗格雷厄姆 / 译者:阮一峰美国互联网界如日中天的教父、哈佛大学离经叛道的博士保罗格雷厄姆著作!一本书,你不曾想到的视角,彻底颠覆你对世界的认识!美国亚马逊、纽约时报超级畅销书&…

如何解决U盘无法停止通用卷设备

当我们使用完U盘,在电脑上安全删除时,电脑却提示:无法停止‘通用卷设备。这是什么问题呢?这时候不要硬拔哦,因为硬拔可能会损坏我们U盘的资料文件或者电脑的USB接口。正确的解决方法: 第一种: 往…

php按时间分组的sql语句,(SQL语句)按指定时间段分组统计

---------------------------------------Author : liangCK 梁爱兰--Comment: 小梁 爱 兰儿--Date : 2010-01-02 16:47:10---------------------------------------> 生成测试数据: #tbCREATETABLE#tb(列名1varchar(12),时间datetime)INSERTINTO#tbSELECT03174190188,2009…

NET问答: 说说你对 LookupTKey, TElement 的看法 ?

咨询区 dan-gph&#xff1a;MSND 上对 Lookup 做了如下的解释。Lookup<TKey, TElement> 类似于 Dictionary<TKey,TValue>, 不同点在于 Dictionary<TKey, TValue> 中的key对应的是单个value&#xff0c;而 Lookup<TKey, TElement> 中的 key 对应的是一个…

最多金的编程语言Top10:Python第3,R第10,你猜第1是谁?

导读&#xff1a;如果你还在纠结选哪门编程语言来开启你的码农生涯&#xff0c;这将是你的最佳指南。本文绝非标题党&#xff0c;而是基于大量数据和为期两周的深入探究&#xff0c;在18年初&#xff0c;对IT行业的现状、趋势以及预测进行客观观察&#xff0c;让大家对编程语言…

[转贴]制作windows 2003自动安装盘-集成补丁/Raid及硬件驱动

从事网游行业的工作人员&#xff0c;如果一款游戏上线&#xff0c;必须上大量服务器。用品牌机引导盘装系统&#xff0c;再打个补丁&#xff0c;速度真让人不敢恭维。为了提高效率&#xff0c;就尝试制作一张集成系统补丁/RAID及硬件驱动自动安windows 2003系统盘。下面以品牌机…

4月 .NET 线上 Meetup,快来报名

点击蓝字关注我们.NET 6 preview 2 在3月11日已经发布&#xff0c;.NET 6 将是 .NET Core 3.1 之后的第一个 LTS 版本&#xff0c;也是微软开启全平台统一一个 .NET 计划以来的第一个 LTS 版本&#xff0c;意义不可谓不大&#xff0c;那么 .NET 5/6 又会带来哪些新特性呢&#…

NP完全性理论与近似算法

一、图灵机根据有限状态控制器的当前状态及每个读写头读到的带符号&#xff0c;图灵机的一个计算步可实现下面3个操作之一或全部。改变有限状态控制器中的状态。清除当前读写头下的方格中原有带符号并写上新的带符号。独立地将任何一个或所有读写头&#xff0c;向左移动一个方格…

php文件上传实验总结,53 PHP文件处理(六)文件上传--总结---细说php

前台表单设计,表单view.html,提交给upload.php一.表单view.htmlphp配置文件和上传文件有关选项&#xff0c;注意几点:php.inifile_uploadsonupload_max_filesize2M 此值最大不超过服务器内存upload_tmp_dirc:/uploads 到时要拷贝出来post_max_size25M 要大于upload_max_fil…

CentOS 5.6 快速搭建LAMP

在虚拟机下安装了个CentOS&#xff0c;5.6版本的。利用NAT模式与宿主pc共享上网&#xff01; 当然可以采用编译源码的方式搭建lamp。这里只是介绍快速搭建php开发框架的方法。其实也没什么&#xff0c;主要是是是使用linux的yum来在线安装。如果上不了网请查找编译lamp的文…

阿里25k 百度25k,招WPF!

.NET5打通7大开发方向&#xff0c;CLR超高性能&#xff0c;.NET6支持Blazor嵌入WPF&#xff0c;还有MAUI跨平台UI解决方案&#xff0c;都是.NET的利好&#xff0c;也是WPF的利好。牛年跳槽季&#xff0c;.NET在客户端方向一骑绝尘&#xff0c;阿里影视、百度地图&#xff0c;以…

php转译html,使用php转义输出HTML到JavaScript

最近在做天地图是GIS集成要输出HTML到JavaScript里面涉及到代码转义什么的比较麻烦所以写个PHP的function分享一下&#xff1a;function jsformat($str){$str trim($str);$str str_replace(\\s\\s, \\s, $str);$str str_replace(chr(10), , $str);$str str_replace(chr(13)…

掌握神经网络模型的快捷方式

TensorFlow是Google基于DistBelief进行研发的第二代人工智能学习系统&#xff0c;其命名来源于本身的运行原理。Tensor&#xff08;张量&#xff09;意味着N维数组&#xff0c;Flow&#xff08;流&#xff09;意味着基于数据流图的计算&#xff0c;TensorFlow实际上就是张量从流…

Visual Entity 手册(十一)代码生成设置

NHibernate 代码生成设置&#xff08;仅选取比较难理解的选项&#xff09; 一、DataContext 设置选项 1、Auto-Implemented Properties 设为 True 时&#xff0c;生成自动属性&#xff0c;如下&#xff1a; public partial class Category{public virtual int CategoryID { get…

.Net项目模板(Project Template)

你有没有这样的感觉&#xff0c;开启一个新项目时&#xff0c;总是做一堆体力活——项目的结构层次&#xff0c;常用日志库&#xff0c;OpenAPI库&#xff0c;ORM库&#xff0c;的引入&#xff0c;权限认证方式选择添加&#xff0c;配置文件重新归置存放等等。公共框架的部分总…

php导出数据库的指定表数据,MYSQL教程mysql数据库导出指定表数据的方法

《MYSQL教程mysql数据库导出指定表数据的方法》要点&#xff1a;本文介绍了MYSQL教程mysql数据库导出指定表数据的方法&#xff0c;希望对您有用。如果有疑问&#xff0c;可以联系我们。导读&#xff1a;linux下导出mysql中指定表数据 &#xff1a;MYSQLdump -uroot -p databas…

谈通过测试与失败测试

在软件测试技术中&#xff0c;现有的测试方法、测试技术中均未提及到通过测试与失败测试。 而在实际项目测试过程中&#xff0c;很多项目组却再应用该方法。虽然该方法被采用&#xff0c;但是很多人对通过测试与失败测试理解并不透侧&#xff0c;在实际使用过程中并未按统一的标…