当前位置: 首页 > 科技观察

Node.js应用全链路追踪技术——全链路信息存储

时间:2023-03-14 08:34:13 科技观察

1.背景目前业界主流的做法是使用分布式链路追踪系统,其理论基础是谷歌的一篇论文《大规模分布式系统的跟踪系统》。论文如下图所示:(来源:网络)基于这个理论,诞生了很多优秀的实现,比如zipkin,jaeger。同时,为了保证API兼容性,它们都遵循OpenTracing标准。那么什么是OpenTracing标准呢?OpenTracing翻译过来就是开发分布式追踪,它是一个轻量级的标准化层,位于应用程序/类库和链接追踪系统之间。这一层可以用下图来表示:从上图可以看出,OpenTracing有以下优点:统一了API,开发者可以方便的添加跟踪系统的实现。OpenTracing已入驻CNCF,正在为全球分布式链路跟踪系统提供统一的模型和数据标准。通俗一点解释:就像手机的接口标准。现在的手机基本都是TypeC接口,方便了各种手机能力的共享。因此,全链路信息存储需要按照业界公认的OpenTracing标准来实现。本文将向大家讲解Node.js应用是如何通过已有的优秀实现——zipkin来连接分布式链路跟踪系统的。2.什么是zipkin2.1zipkin?Zipkin是Twitter基于Google的分布式跟踪系统论文开发实现,遵循OpenTracing标准。Zipkin用于跟踪分布式服务之间的应用程序数据链接。2.2zipkin官方架构文档上的架构如下图所示:为了更好的理解,我在这里简化了架构图。简化架构图如下:从上图可以看出,分为三部分:一部分:全链路信息获取,我们不使用zipkin自带的全链路信息获取,我们使用zone-context获取全链接信息第二部分:传输层,使用zipkin提供的transportapi将全链接传递信息给zipkin第三部分:zipkin核心功能,各模块介绍如下:collector是信息收集器,作为一个守护进程,它会一直等待客户端传来的跟踪数据,对这些数据进行验证、存储和创建查询所需要的索引。storage是一个存储组件。默认情况下,zipkin将数据直接存储在内存中,支持使用ElasticSearch和MySQL。search是一个查询过程,它提供了一个简单的JSONAPI供外部调用查询。webUI是zipkin的服务端展示平台,主要调用search提供的接口,将链接信息用图表清晰的展示给开发者。至此,zipkin的整体架构介绍完毕。接下来我们来搭建zipkin环境。2.3zipkin环境使用docker搭建。这里我们使用docker中的docker-compose来快速搭建zipkin环境。docker-compose.yml文件内容如下:version:'3.8'services:elasticsearch:image:docker.elastic.co/elasticsearch/elasticsearch:7.5.0container_name:elasticsearchrestart:alwaysports:-9200:9200健康检查:测试:[“CMD-SHELL”,“curl--silent--faillocalhost:9200/_cluster/health||exit1”]间隔:30s超时:10s重试:3start_period:40s环境:-discovery.type=单节点-bootstrap.memory_lock=true-"ES_JAVA_OPTS=-Xms512m-Xmx512m"-TZ=Asia/Shanghaiulimits:memlock:soft:-1hard:-1zipkin:image:openzipkin/zipkin:2.21container_name:zipkindepends_on:-elasticsearchlinks:-elasticsearchrestart:alwaysports:-9411:9411environment:-TZ=Asia/Shanghai-STORAGE_TYPE=elasticsearch-ES_HOSTS=elasticsearch:9200在上述文件所在目录执行docker-composeup-d完成本地构建。搭建完成后,在浏览器中打开地址http://localhost:9411,会看到如下图所示的页面:然后打开地址http://localhost:9200,会看到页面如下图所示:至此,zipkin本地环境搭建完成。接下来介绍Node.js应用如何连接zipkin。3、node.js连接zipkin3.1获取完整链接信息。我已经在文章《??Node.js 应用全链路追踪技术——全链路信息获取??》中详细解释了如何获取完整的链接信息。3.2搞定传输层,因为zipkin是基于OpenTracing标准实现的。所以,只要我们解决了zipkin的传输层,也就解决了其他主流的分布式追踪系统。这里我们使用zipkin官方提供的两个npm包,即:zipkinzipkin-transport-httpzipkin包是官方支持Node.js的核心包。zipkin-transport-http包的作用是通过HTTP异步向zipkin发送数据。下面我们将详细介绍如何在传输层向zipkin发送数据。3.3传输层基础封装核心代码实现及相关注释如下:const{BatchRecorder,Tracer,//ExplicitContext,jsonEncoder:{JSON_V1,JSON_V2},}=require('zipkin')const{HttpLogger}=require('zipkin-transport-http')//constctxImpl=newExplicitContext();//配置对象constoptions={serviceName:'zipkin-node-service',targetServer:'127.0.0.1:9411',targetApi:'/api/v2/spans',jsonEncoder:'v2'}//异步HTTP传输函数记录器({targetServer,targetApi,jsonEncoder})=>newBatchRecorder({logger:newHttpLogger({endpoint:`${targetServer}${targetApi}`,jsonEncoder:(jsonEncoder==='v2'||jsonEncoder==='V2')?JSON_V2:JSON_V1,})})//基本记录constbaseRecorder=awaitrecorder({targetServer:options.targetServertargetApi:options.targetApijsonEncoder:options.jsonEncoder})至此,基本的封装传输层完成,我们提取了baseRecorder,下面将完整的链路信息连接到传输层。3.4获取全链接信息这里是官方获取SDK,代码如下:const{Tracer}=require('zipkin')constctxImpl=newExplicitContext()consttracer=newTracer({ctxImpl,recorder:baseRecorder})//还需要处理请求头,手动逐层传递等,上面的方法缺点很明显,需要额外传递一些东西。这里我们使用上一篇文章中提到的Zone-Context。代码如下:constzoneContextImpl=newZoneContext()consttracer=newTracer({zoneContextImpl,recorder:baseRecorder})//就这样,不需要额外处理来比较两者,很明显Zone的实现-上下文更隐含,对代码入侵的抵抗力更小。这也是单独花一篇文章介绍Zone-Context技术原理的价值所在。至此,我们完成了传输层的适配,基本完成了Node.js应用接入zipkin的核心步骤。3.5获取zipkin的采集、存储、展示这部分的采集、展示功能,zipkin官方自带完整实现,无需二次开发。存储区提供MySQL、Elasticsearch等访问方式。可以根据实际情况进行相应的访问。本文使用docker-compose集成ElasticSearch。4.总结至此,我们完成了zipkin基于业界通用的OpenTracing标准的Node.js方案。希望大家看完这两篇文章后,对Node.js全链路跟踪有一个全面清晰的认识。参考:zipkin官网