Dapr提供了一些开箱即用的分布式链路追踪解决方案,今天我们来讲一讲如何通过dapr的configuration来实现非侵入式链路追踪的
目录:
一、通过Dapr实现一个简单的基于.net的微服务电商系统
二、通过Dapr实现一个简单的基于.net的微服务电商系统(二)——通讯框架讲解
三、通过Dapr实现一个简单的基于.net的微服务电商系统(三)——一步一步教你如何撸Dapr
四、通过Dapr实现一个简单的基于.net的微服务电商系统(四)——一步一步教你如何撸Dapr之订阅发布
五、通过Dapr实现一个简单的基于.net的微服务电商系统(五)——一步一步教你如何撸Dapr之状态管理
六、通过Dapr实现一个简单的基于.net的微服务电商系统(六)——一步一步教你如何撸Dapr之Actor服务
七、通过Dapr实现一个简单的基于.net的微服务电商系统(七)——一步一步教你如何撸Dapr之服务限流
八、通过Dapr实现一个简单的基于.net的微服务电商系统(八)——一步一步教你如何撸Dapr之链路追踪
附录:(如果你觉得对你有用,请给个star)
一、电商Demo地址
首先依然简单聊聊什么是链路追踪以及我们为什么需要它,知道链路追踪的同学可以跳过。在传统的单体应用中,我们的每一次请求往往在同一个进程中被一次性处理。而在分布式系统中,我们需要通过不同容器隔离甚至物理机隔离的服务间协同作业来实现某些业务,同时由于业务流转会涉及到接口调用、事件订阅、状态读写、actor调用等等情况,往往想要追踪它们形成一个链式调用的记录会比较困难。这里举一个例子,某分布式系统集群运行在生产环境上,某日收到预警某接口调用非常缓慢。这个时候开发人员排查发现该聚合网关接口调用了服务A、B、C但是不知道具体是哪个服务导致的缓慢,通知A、B、C对应的开发组人员通过本地调试发现A、B、调用正常,C缓慢,但是C发现并非由于自身业务逻辑缓慢,而是自己调用D时返回比较缓慢,这时又只得通知D负责的团队进行业务排查,最终D发现自己的代码问题,然后逐一修复并发布到生产环境解决该问题。这个例子比较极端哈,这里仅举个例子说明。链路追踪系统就是帮助分布式系统在链路调用时记录每一个接口的响应时间以及自己依赖的下游接口的响应时间并提供可视化UI方便开发运维团队快速排查接口调用耗时异常定位问题。
传统的链路追踪一般是通过代码侵入式的方式由开发人员集成SDK插入代理,应用上线运行后这些代理即可自动化监视我们的应用进程记录流量流入、流出请求/响应时间并统一上报到链路追踪系统,而service mesh由于sidecar的存在可以确保流量在流入/流出应用时一定会经过sidecar,所以天生更容易实现链路追踪,从而免于让开发人员人工通过SDK的方式去集成一个分布式链路追踪系统,接下来就讲讲我们在dapr下如何来实现它。
首先我们需要在k8s环境跑起来一个链路追踪系统,大家可以看看这里是目前dapr支持的链路后端,我这里就选型我比较熟悉的zipkin来实现。zip在k8s中很容易跑起来,这是yaml:
--- apiVersion: apps/v1 kind: Deployment metadata: name: zipkin spec: selector: matchLabels: app: zipkin replicas: 1 template: metadata: labels: app: zipkin spec: containers: - name: zipkin image: openzipkin/zipkin:latest imagePullPolicy: IfNotPresent ports: - containerPort: 9411 env: - name: TZ value: "Asia/Shanghai" --- apiVersion: v1 kind: Service metadata: name: zipkin spec: type: NodePort selector: app: zipkin ports: - protocol: TCP port: 9411 targetPort: 9411
由于需要在本地访问zip的website,我这里偷懒直接将nodeport暴露到本地k8s集群,方便等会儿通过浏览器访问。现在我们apply一下,稍微等待一段时间k8s拉取镜像并运行起来后,通过kubectl get svc 查询zipkin暴露的随机端口即可通过localhost:nodeport访问到zipkin的界面:
接下来就比较简单了,我们创建一个类型为configuration的配置文件,并注入到每一个需要追踪的服务即可,其中samplingRate是指采样率,而endpointAddress是指我们在k8s集群内通过svc能访问到的zipkin的地址(如果你的zipkin部署在非本集群,则可通过ip or 网址的方式访问):
apiVersion: dapr.io/v1alpha1 kind: Configuration metadata: name: zipkin spec: metric: enabled: true tracing: samplingRate: "1" zipkin: endpointAddress: "http://zipkin.infrastructure.svc.cluster.local:9411/api/v2/spans"
接着我们将这个configuration注入到我们需要的服务中,这里我们直接看电商demo yaml文件账户服务的情况(红字部分):
apiVersion: apps/v1 kind: Deployment metadata: name: accountservice namespace: dapreshop labels: app: accountservice spec: replicas: 1 selector: matchLabels: app: accountservice minReadySeconds: 5 strategy: type: RollingUpdate rollingUpdate: maxUnavailable: 1 maxSurge: 1 template: metadata: labels: app: accountservice version: v1 annotations: dapr.io/enabled: "true" dapr.io/app-id: "accountservice" dapr.io/app-port: "80" dapr.io/config: "zipkin" spec: containers: - name: web image: accountservice:release imagePullPolicy: Never readinessProbe: httpGet: path: v1.0/healthz port: 3500 initialDelaySeconds: 5 periodSeconds: 10 timeoutSeconds : 5 failureThreshold : 3 ports: - containerPort: 80
现在我们来下单看看,访问admin.dapreshop.com:30882,初始化系统后,访问m.dapreshop.com:30882,下单一次。接着打开我们的zipkin,查询run query即可看到最新一条链路追踪记录如下:
可以看到链路追踪的root是我们的apigateway,因为客户端请求是从这里被聚合的。接着apigateway会调用商品服务、交易服务、用户服务、以及作业系统。这里我们再看看我们的代码看看createorder明细:
这个用例服务会调用用户服务获取一个mockaccount模拟用户用于下单,接着会调用一个创建订单的领域服务用于下单这里会调用商品的actor服务用于原子减扣库存(此部分可参考之前的actor文章),下单完成后会发送一个订单创建成功事件,由作业系统订阅并等待5分钟后进行未支付订单取消操作,整个下单流程如下:
整个流程相对比较简单,通过在daprd sidecar上申明了zipkin configuration后 daprd会忠实的将我们的请求转化为链路追踪记录并上报zipkin,我们点开zipkin那条记录查看明细如下:
可以非常清楚的看到我们的订单创建调用的账户服务的mockaccount接口,然后调用了商品服务的商品信息接口,接着调用数个商品actor进行库存减扣,最终持久化我们的订单后发起一个事件并且成功的被作业系统订阅。每一个接口请求了多少时间被清楚的记录了下来,这样在生产环境下就很容易排除慢接口的问题而不用像上面提到的那样各个团队忙的焦头烂额了
dapr目前还提供了其他的一些链路追踪客户端,但是整体大的流程基本如本文所述,今天的分享就到这里,希望大家多多支持dapr,多多转发fork+star。下一次我们将分享一下如何集成一个第三方的oauth授权服务来实现oauth。