应用程序通过 Envoy 代理和 Jaeger 进行分布式追踪 —— Ingress Controller + Http服务 + Grpc服务(三)
1、概述
在《应用程序通过 Envoy 代理和 Jaeger 进行分布式追踪(一)》这篇博文中,我们详细介绍了单个应用程序通过 Envoy 和 Jaeger 实现链路追踪的过程。通过这个示例我们知道,Istio 支持通过 Envoy 代理进行分布式追踪,代理会自动为其应用程序生成追踪 span,只需要应用程序转发适当的请求上下文即可。特别是,Istio 依赖于应用程序传播 b3 追踪 Header 以及由 Envoy 生成的请求 ID,即应用程序服务请求时需携带这些 Header。如果请求中没有 B3 HTTP Header,Istio Sidecar 代理(Envoy) 会自动生成初始化的 Headers。
在《Nginx Ingress Contoller 通过 Envoy 代理和 Jaeger 进行分布式追踪(二)》这篇博文中,进一步扩展链路追踪范围,演示了如何将 Nginx Ingress Controller 与之前提到的应用程序一起使用,从而实现更为复杂的分布式链路追踪。
在本文将继续扩展链路追踪范围,演示 Nginx Ingress Controller(http协议)——》前端服务(http协议)——》后端服务(http协议)——》告警客户端后端服务 (grpc协议)——》告警服务端后端服务的分布式链路追踪。
其中 Nginx Ingress Controller 服务和前端服务默认会自动转发请求的上下文信息(Header),后端服务通过少量的代码侵入将原请求的上下文信息(Header)转发给告警客户端后端服务,告警客户端后端服务通过少量的代码侵入将原请求的上下文信息(Grpc Metadata)转发给告警服务端后端服务。
2、示例演示
2.1 环境准备
本文主要目的是讲解分布式链路追踪,因此不再讲解各组件的部署,这些组件部署时都需要注入 Envoy 边车,注入边车后,各组件通过 Envoy 代理和 Jaeger 进行分布式追踪。
2.2 Nginx Ingress Controller(http协议)——》前端服务
Nginx Ingress Controller 的部署本文略,这里只展示下 Nginx Ingress Controller 是如何将服务代理到前端服务的。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: xxxx
nginx.ingress.kubernetes.io/service-upstream: "true"
nginx.ingress.kubernetes.io/upstream-vhost: dashboard.xxxx.svc.cluster.local
name: dashboard-tracing
spec:
rules:
- host: dashboard-tracing.10.20.32.203.nip.io
http:
paths:
- backend:
service:
name: dashboard
port:
number: 80
path: /
pathType: ImplementationSpecific
2.3 前端服务(http协议)——》后端服务
前端服务默认会自动转发请求的上下文信息(Header)信息到后端服务,所以前端服务无需侵入,其他前端相关内容本文不再赘余,我们只需要知道前端服务会自动转发请求的上下文信息即可。
2.4 后端服务(http协议)——》告警客户端后端服务
后端服务需要通过少量的代码侵入将原请求的上下文信息(Header)信息转发给告警客户端后端服务,下面通过侵入源码来分析下是如何将原请求的上下文信息转发给告警客户端后端服务的。
主要是使用 k8s.io/apimachinery 库的 proxy 包,通过 proxy 包的 ServeHTTP 方法作为客户端调用告警客户端后端服务。调用 ServeHTTP 方法时后端服务会将 request 对象作为参数(request对象除了组织告警客户端 Host 信息外,还将前端服务传递过来的 Header 信息放到了request 对象中,此块代码因隐私问题不再粘贴),这样在 ServeHTTP 方法逻辑里面就能获取到前端服务传递过来的上下文信息(Header)了。
......
httpProxy := proxy.NewUpgradeAwareHandler(u, http.DefaultTransport, false, false, &errorResponder{})
httpProxy.ServeHTTP(response, request.Request)
下面看下 ServeHTTP 方法逻辑,可以看到通过调用 utilnet.CloneHeader 方法将前端服务传递过来的上下文信息(Header)传递给告警客户端后端服务。
// 方法包路径: k8s.io/apimachinery@v0.21.7/pkg/util/proxy/upgradeaware.go
// ServeHTTP handles the proxy request
func (h *UpgradeAwareHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
.......
// WithContext creates a shallow clone of the request with the same context.
newReq := req.WithContext(req.Context())
// 主要看这里,新的请求会克隆老请求对象里面的 Header 头信息
newReq.Header = utilnet.CloneHeader(req.Header)
if !h.UseRequestLocation {
newReq.URL = &loc
}
......
proxy.ServeHTTP(w, newReq)
}
2.5 告警客户端后端服务(grpc协议)——》告警服务端后端服务
在2.2-2.4中,都是 http 之间的链路追踪,都是通过 header 传递链路追踪相关的上下文信息,2.5告警客户端后端服务是通过 grpc 协议访问告警服务端后端服务的,但是在 grpc 中怎么传递呢?
grpc 底层采用 http2 协议也是支持传递数据的,采用的是 Metadata,Metadata 对于 gRPC 本身来说透明, 它使得 client 和 server 能为对方提供本次调用的信息。
就像一次 http 请求的 RequestHeader 和 ResponseHeader,http header 的生命周期是一次 http 请求, Metadata 的生命周期则是一次 RPC 调用。
下面来看下告警客户端后端服务是如何将从后端服务转发的上下文信息通过 Metadata 传递给告警服务端后端服务的。
下面以修改查询告警消息列表方法逻辑为例,演示警客户端后端服务如何将从后端服务转发的上下文信息通过 Metadata 传递给告警服务端后端服务,其他方法修改方式和此方法一致。
......
// 传播追踪上下文信息,将后端服务传递过来的上下文信息放置到metadata对象中,通过context传递给告警服务端后端服务
// type MD map[string][]string
httpHeader := metadata.MD(utilnet.CloneHeader(request.Request.Header))
ctx = metadata.NewOutgoingContext(ctx, httpHeader)
......
2.6 客户端在前端服务访问查询告警消息列表功能,然后在 Jaeger UI 查看上报链路信息
客户端在前端服务访问查询告警消息列表功能时,告警客户端后端服务作为 grpc 客户端调用了两次告警服务端后端服务的接口,总共11个 span,envoy 上报链路信息如下:
(1)Nginx Ingress Controller 入站流量劫持 ——》nginx ——》(2)Nginx Ingress Controller 出站流量劫持 ——》(3)前端服务入站劫持 ——》前端服务 ——》(4)前端服务出站劫持 ——》(5)后端服务入站劫持 ——》 后端服务 ——》(6)后端服务出站劫持 ——》(7)告警客户端后端服务入站劫持 ——》告警客户端后端服务 ——》(8)告警客户端后端服务出站劫持 ——》(9)告警服务端后端服务入站劫持 ——》 告警服务端后端服务消息列表方法(回包)——》 告警客户端后端服务 ——》 (10)告警客户端后端服务出站劫持 ——》(11)告警服务端后端服务入站劫持 ——》 告警服务端后端服务消息历史方法(回包)
注意 1:如果访问容器的入站流量不是inbound、或者出站流量不是outbound,请检查对应服务的服务协议是否正确,尤其出站流量是 PassthroughCluster。
这时候可以通过 istioctl pc listener <pod-name>.<pod-namespace> --port 端口命令排查是否没有进行路由匹配。例如以下示例能成功匹配下面路由的话出站流量就为 outbound。
3、总结
通过《应用程序通过 Envoy 代理和 Jaeger 进行分布式追踪(一)》、《Nginx Ingress Contoller 通过 Envoy 代理和 Jaeger 进行分布式追踪(二)》加上本篇三篇博文,详细解决了应用程序如何通过 Envoy 代理和 Jaeger 进行分布式追踪,最主要的还是这一点:为了将各种追踪 span 整合在一起以获得完整的追踪图,应用程序(不管是http协议、grpc协议、或者是其他Istio支持的能上报链路追踪的服务协议)必须在传入和传出请求之间传播追踪上下文信息。
应用程序通过 Envoy 代理和 Jaeger 进行分布式追踪 —— Ingress Controller + Http服务 + Grpc服务(三)的更多相关文章
- ASP.NET Core使用Jaeger实现分布式追踪
前言 最近我们公司的部分.NET Core的项目接入了Jaeger,也算是稍微完善了一下.NET团队的技术栈. 至于为什么选择Jaeger而不是Skywalking,这个问题我只能回答,大佬们说了算. ...
- 总结两种动态代理jdk代理和cglib代理
动态代理 上篇文章讲了什么是代理模式,为什么用代理模式,从静态代理过渡到动态代理. 这里再简单总结一下 什么是代理模式,给某个对象提供一个代理对象,并由代理对象控制对于原对象的访问,即客户不直接操控原 ...
- 通过一个工具类更深入理解动态代理和Threadlocal
动态代理和Threadlocal 一个代理类返回指定的接口,将方法调用指定的调用处理程序的代理类的实例.返回的是一个代理类,由指定的类装载器的定义和实现指定接口指定代理实例调用处理程序最近用到一个工具 ...
- 爬虫--requests模块高级(代理和cookie操作)
代理和cookie操作 一.基于requests模块的cookie操作 引言:有些时候,我们在使用爬虫程序去爬取一些用户相关信息的数据(爬取张三“人人网”个人主页数据)时,如果使用之前requests ...
- java的静态代理、jdk动态代理和cglib动态代理
Java的代理就是客户端不再直接和委托类打交道,而是通过一个中间层来访问,这个中间层就是代理.使用代理有两个好处,一是可以隐藏委托类的实现:二是可以实现客户与委托类之间的解耦,在不修改委托类代码的情况 ...
- JAVA高级架构师基础功:Spring中AOP的两种代理方式:动态代理和CGLIB详解
在spring框架中使用了两种代理方式: 1.JDK自带的动态代理. 2.Spring框架自己提供的CGLIB的方式. 这两种也是Spring框架核心AOP的基础. 在详细讲解上述提到的动态代理和CG ...
- AOP的底层实现-CGLIB动态代理和JDK动态代理
AOP是目前Spring框架中的核心之一,在应用中具有非常重要的作用,也是Spring其他组件的基础.它是一种面向切面编程的思想.关于AOP的基础知识,相信多数童鞋都已经了如指掌,我们就略过这部分,来 ...
- JDK动态代理和CGLIB的区别
Aspect默认情况下不用实现接口,但对于目标对象,在默认情况下必须实现接口 如果没有实现接口必须引入CGLIB库 我们可以通过Advice中添加一个JoinPoint参数,这个值会由spring自动 ...
- JDK动态代理和CGLib动态代理简单演示
JDK1.3之后,Java提供了动态代理的技术,允许开发者在运行期间创建接口的代理实例. 一.首先我们进行JDK动态代理的演示. 现在我们有一个简单的业务接口Saying,如下: package te ...
- SpringAOP-JDK 动态代理和 CGLIB 代理
在 Spring 中 AOP 代理使用 JDK 动态代理和 CGLIB 代理来实现,默认如果目标对象是接口,则使用 JDK 动态代理,否则使用 CGLIB 来生成代理类. 1.JDK 动态代理 那么接 ...
随机推荐
- pycham2022最新破解
pycharm破解方式常见有2种: 1 .破解插件+激活码,一般激活到2099年或者2089年! 2 .破解插件.该破解插件可以无限重置30天,也就是pycharm永远有30天的试用期,永不到期! ...
- 牧云 • 主机管理助手|正式开放应用市场,梦幻联动雷池WAF等多款开源软件
0x00 前言 上个月,我司长亭开源了雷池WAF,不到三天就吸引了超过上千个师傅使用,几个交流群里,师傅们讨论的热火朝天,其中两个话题引起了我们牧云 • 主机管理助手 ( Collie ) 团队的关注 ...
- Netty实战(五)
一.什么是ByteBuf 我们前面说过,网络数据的基本单位总是字节.Java NIO 提供了 ByteBuffer 作为它的字节容器,但是这个类使用起来过于复杂,而且也有些繁琐.ByteBuffer ...
- 解决log4j:WARN No appenders could be found for logger (org.apache.ibatis.logging.LogFactory). log4j:WARN Please initialize the log4j system properly.警告
1. 问题分析 使用log4j时不起作用,因为找不到配置文件log4j.properties,存在的问题可能是没有配置log4j.properties文件,也可能是配置文件log4j.properti ...
- Gitlab恢复数据报错解决方法
背景 在Gitlab迁移恢复数据出现must be owner of extension plpgsql解决方法:在做gitlab迁移时,按正常Gitlab备份数据gitlab-rake gitlab ...
- 1. Mybatis 简介
1. Mybatis历史 MyBatis最初是Apache的一个开源项目iBatis, 2010年6月这个项目由Apache Software Foundation迁移到了Google Code.随着 ...
- k8s驱逐篇(6)-kube-controller-manager驱逐-NodeLifecycleController源码分析
概述 k8s v1.16版本中NodeController已经分为了NodeIpamController与NodeLifecycleController,本文主要介绍NodeLifecycleCont ...
- mysql concat函数的用法
mysql中的这个函数非常强大,可以对查出的参数进行拼接,其实这个方法在java中也有api可以进行调用. 那么什么时候进行使用呢?例如,你老大叫你做一个数据库的数据采集,需要整理成文档,那么这个时候 ...
- 体细胞突变检测分析流程-系列1( WES&Panel)
Sentieon●体细胞变异检测-系列1 Sentieon 致力于解决生物信息数据分析中的速度与准确度瓶颈,通过算法的深度优化和企业级的软件工程,大幅度提升NGS数据处理的效率.准确度和可靠性. ...
- 使用Stable Diffusion生成艺术二维码
在数字艺术的世界中,二维码已经从单纯的信息承载工具转变为可以展示艺术表达的媒介.这是通过使用Stable Diffusion的技术实现的,它可以将任何二维码转化为独特的艺术作品.接下来,我们将一步步教 ...