Go微服务全链路跟踪详解
本文作者:倚天码农,授权发布
在微服务架构中,调用链是漫长而复杂的,要了解其中的每个环节及其性能,你需要全链路跟踪。它的原理很简单,你可以在每个请求开始时生成一个唯一的ID,并将其传递到整个调用链。该ID称为CorrelationID[1]1,你可以用它来跟踪整个请求并获得各个调用环节的性能指标。简单来说有两个问题需要解决。第一,如何在应用程序内部传递ID; 第二,当你需要调用另一个微服务时,如何通过网络传递ID。
什么是OpenTracing?
现在有许多开源的分布式跟踪库可供选择,其中最受欢迎的库可能是Zipkin[2]2和Jaeger[3]3。选择哪个是一个令人头疼的问题,因为你现在可以选择最受欢迎的一个,但是如果以后有一个更好的出现呢?OpenTracing[4]?可以帮你解决这个问题。它建立了一套跟踪库的通用接口,这样你的程序只需要调用这些接口而不被具体的跟踪库绑定,将来可以切换到不同的跟踪库而无需更改代码。Zipkin和Jaeger都支持OpenTracing。
如何跟踪服务器端点(server endpoints)?
在下面的程序中我使用“Zipkin”作为跟踪库,用“OpenTracing”作为通用跟踪接口。跟踪系统中通常有四个组件,下面我用Zipkin作为示例:
- recorder(记录器):记录跟踪数据
- Reporter (or collecting agent)(报告器或收集代理):从记录器收集数据并将数据发送到UI程序
- Tracer:生成跟踪数据
- UI:负责在图形UI中显示跟踪数据
上面是Zipkin的组件图,你可以在Zipkin Architecture[5]中找到它。
有两种不同类型的跟踪,一种是进程内跟踪(in-process),另一种是跨进程跟踪(cross-process)。我们将首先讨论跨进程跟踪。
客户端程序:
我们将用一个简单的gRPC程序作为示例,它分成客户端和服务器端代码。我们想跟踪一个完整的服务请求,它从客户端到服务端并从服务端返回。以下是在客户端创建新跟踪器的代码。它首先创建“HTTP Collector”(the agent)用来收集跟踪数据并将其发送到“Zipkin” UI, “endpointUrl”是“Zipkin” UI的URL。其次,它创建了一个记录器(recorder)来记录端点上的信息,“hostUrl”是gRPC(客户端)呼叫的URL。第三,它用我们新建的记录器创建了一个新的跟踪器(tracer)。最后,它为“OpenTracing”设置了“GlobalTracer”,这样你可以在程序中的任何地方访问它。
以下是gRPC客户端代码。它首先调用上面提到的函数“newTrace()”来创建跟踪器,然后,它创建一个包含跟踪器的gRPC调用连接。接下来,它使用新建的gRPC连接创建缓存服务(Cache service)的gRPC客户端。最后,它通过gRPC客户端来调用缓存服务的“Get”函数。
Trace 和 Span:
在OpenTracing中,一个重要的概念是“trace”,它表示从头到尾的一个请求的调用链,它的标识符是“traceID”。一个“trace”包含有许多跨度(span),每个跨度捕获调用链内的一个工作单元,并由“spanId”标识。每个跨度具有一个父跨度,并且一个“trace”的所有跨度形成有向无环图(DAG)。以下是跨度之间的关系图。你可以从The OpenTracing Semantic Specification[6]中找到它。
以下是函数“callGet”的代码,它调用了gRPC服务端的“Get"函数。在函数的开头,OpenTracing为这个函数调用开启了一个新的span,整个函数结束后,它也结束了这个span。
服务端代码:
下面是服务端代码,它与客户端代码类似,它调用了“newTracer()”(与客户端“newTracer()”函数几乎相同)来创建跟踪器。然后,它创建了一个“OpenTracingServerInterceptor”,其中包含跟踪器。最后,它使用我们刚创建的拦截器(Interceptor)创建了gRPC服务器。
以下是运行上述代码后在Zipkin中看到的跟踪和跨度的图片。在服务器端,我们不需要在函数内部编写任何代码来生成span,我们需要做的就是创建跟踪器(tracer),服务器拦截器自动为我们生成span。
怎样跟踪函数内部?
上面的图片没有告诉我们函数内部的跟踪细节, 我们需要编写一些代码来获得它。
以下是服务器端“get”函数,我们在其中添加了跟踪代码。它首先从上下文获取跨度(span),然后创建一个新的子跨度并使用我们刚刚获得的跨度作为父跨度。接下来,它执行一些操作(例如数据库查询),然后结束(mysqlSpan.Finish())子跨度。
以下是它运行后的图片。现在它在服务器端有一个新的跨度“db query user”。
以下是zipkin中的跟踪数据。你可以看到客户端从8.016ms开始,服务端也在同一时间启动。服务器端完成需要大约16ms。
怎样跟踪数据库?
怎样才能跟踪数据库内部的操作?首先,数据库驱动程序需要支持跟踪,另外你需要将跟踪器(tracer)传递到数据库函数中。如果数据库驱动程序不支持跟踪怎么办?现在已经有几个开源驱动程序封装器(Wrapper),它们可以封装任何数据库驱动程序并使其支持跟踪。其中一个是instrumentedsql[7]?(另外两个是luna-duclos/instrumentedsql[8]?和ocsql/driver.go[9]?)。我简要地看了一下他们的代码,他们的原理基本相同。它们都为底层数据库的每个函数创建了一个封装(Wrapper),并在每个数据库操作之前启动一个新的跨度,并在操作完成后结束跨度。但是所有这些都只封装了“database/sql”接口,这就意味着NoSQL数据库没有办法使用他们。如果你找不到支持你需要的NoSQL数据库(例如MongoDB)的OpenTracing的驱动程序,你可能需要自己编写一个封装(Wrapper),它并不困难。
一个问题是“如果我使用OpenTracing和Zipkin而数据库驱动程序使用Openeracing和Jaeger,那会有问题吗?"这其实不会发生。我上面提到的大部分封装都支持OpenTracing。在使用封装时,你需要注册封装了的SQL驱动程序,其中包含跟踪器。在SQL驱动程序内部,所有跟踪函数都只调用了OpenTracing的接口,因此它们甚至不知道底层实现是Zipkin还是Jaeger。现在使用OpenTarcing的好处终于体现出来了。在应用程序中创建全局跟踪器时(Global tracer),你需要决定是使用Zipkin还是Jaeger,但这之后,应用程序或第三方库中的每个函数都只调用OpenTracing接口,已经与具体的跟踪库(Zipkin或Jaeger)没关系了。
怎样跟踪服务调用?
假设我们需要在gRPC服务中调用另外一个微服务(例如RESTFul服务),该如何跟踪?
简单来说就是使用HTTP头作为媒介(Carrier)来传递跟踪信息(traceID)。无论微服务是gRPC还是RESTFul,它们都使用HTTP协议。如果是消息队列(Message Queue),则将跟踪信息(traceID)放入消息报头中。(Zipkin B3-propogation[10]有“single header”和“multiple header”有两种不同类型的跟踪信息,但JMS仅支持“single header”)
一个重要的概念是“跟踪上下文(trace context)”,它定义了传播跟踪所需的所有信息,例如traceID,parentId(父spanId)等。有关详细信息,请阅读跟踪上下文(trace context)[11]1?。
OpenTracing提供了两个处理“跟踪上下文(trace context)”的函数:“extract(format,carrier)”和“inject(SpanContext,format,carrier)”。“extarct()”从媒介(通常是HTTP头)获取跟踪上下文。“inject”将跟踪上下文放入媒介,来保证跟踪链的连续性。以下是我从Zipkin获取的b3-propagation[12]图。
但是为什么我们没有在上面的例子中调用这些函数呢?让我们再来回顾一下代码。在客户端,在创建gRPC客户端连接时,我们调用了一个为“OpenTracingClientInterceptor”的函数。以下是“OpenTracingClientInterceptor”的部分代码,我从otgrpc[13]11包中的“client.go”中得到了它。它已经从Go context[14]12获取了跟踪上下文并将其注入HTTP头,因此我们不再需要再次调用“inject”函数。
在服务器端,我们还调用了一个函数“otgrpc.OpenTracingServerInterceptor”,其代码类似于客户端的“OpenTracingClientInterceptor”。它不是调用“inject”写入跟踪上下文,而是从HTTP头中提取(extract)跟踪上下文并将其放入Go上下文(Go context)中。这就是我们不需要再次手动调用“extract()”的原因。我们可以直接从Go上下文中提取跟踪上下文(opentracing.SpanFromContext(ctx))。但对于其他基于HTTP的服务(如RESTFul服务), 情况就并非如此,因此我们需要写代码从服务器端的HTTP头中提取跟踪上下文。当然,您也可以使用拦截器或过滤器。
跟踪库之间的互兼容性
你也许会问“如果我的程序使用Zipkin和OpenTracing而需要调用的第三方微服务使用OpenTracing与Jaeger,它们会兼容吗?"它看起来于我们之前询问的数据库问题类似,但实际上很不相同。对于数据库,因为应用程序和数据库在同一个进程中,它们可以共享相同的全局跟踪器,因此更容易解决。对于微服务,这种方式将不兼容。因为OpenTracing只标准化了跟踪接口,它没有标准化跟踪上下文。万维网联盟(W3C)正在制定跟踪上下文(trace context)[15]1?的标准,并于2019-08-09年发布了候选推荐标准。OpenTracing没有规定跟踪上下文的格式,而是把决定权留给了实现它的跟踪库。结果每个库都选择了自己独有的的格式。例如,Zipkin使用“X-B3-TraceId”作为跟踪ID,Jaeger使用“uber-trace-id”,因此使用OpenTracing并不意味着不同的跟踪库可以进行跨网互操作。对于“Jaeger”来说有一个好处是你可以选择使用“Zipkin兼容性功能[16]"13来生成Zipkin跟踪上下文, 这样就可以与Zipkin相互兼容了。对于其他情况,你需要自己进行手动格式转换(在“inject”和“extract”之间)。
全链路跟踪设计
尽量少写代码
一个好的全链路跟踪系统不需要用户编写很多跟踪代码。最理想的情况是你不需要任何代码,让框架或库负责处理它,当然这比较困难。全链路跟踪分成三个跟踪级别:
- 跨进程跟踪 (cross-process)(调用另一个微服务)
- 数据库跟踪
- 进程内部的跟踪 (in-process)(在一个函数内部的跟踪)
跨进程跟踪是最简单的。你可以编写拦截器或过滤器来跟踪每个请求,它只需要编写极少的编码。数据库跟踪也比较简单。如果使用我们上面讨论过的封装器(Wrapper),你只需要注册SQL驱动程序封装器(Wrapper)并将go-context(里面有跟踪上下文) 传入数据库函数。你可以使用依赖注入(Dependency Injection)这样就可以用比较少的代码来完成此操作。
进程内跟踪是最困难的,因为你必须为每个单独的函数编写跟踪代码。现在还没有一个很好的方法,可以编写一个通用的函数来跟踪应用程序中的每个函数(拦截器不是一个好选择,因为它需要每个函数的参数和返回都必须是一个泛型类型(interface {}))。幸运的是,对于大多数人来说,前两个级别的跟踪应该已经足够了。
有些人可能会使用服务网格(service mesh)来实现分布式跟踪,例如Istio[17]或Linkerd[18]。它确实是一个好主意,跟踪最好由基础架构实现,而不是将业务逻辑代码与跟踪代码混在一起,不过你将遇到我们刚才谈到的同样问题。服务网格只负责跨进程跟踪,函数内部或数据库跟踪任然需要你来编写代码。不过一些服务网格可以通过提供与流行跟踪库的集成,来简化不同跟踪库跨网跟踪时的的上下文格式转换。
跟踪设计:
精心设计的跨度(span),服务名称(service name),标签(tag)能充分发挥全链路跟踪的作用,并使之简单易用。有关信息请阅读语义约定(Semantic Conventions)[19]1?。
将Trace ID记录到日志
将跟踪与日志记录集成是一个常见的需求,最重要的是将跟踪ID记录到整个调用链的日志消息中。目前OpenTracing不提供访问traceID的方法。你可以将“OpenTracing.SpanContext”转换为特定跟踪库的“SpanContext”(Zipkin和Jaeger都可以通过“SpanContext”访问traceID)或将“OpenTracing.SpanContext”转换为字符串并解析它以获取traceID。转换为字符串更好,因为它不会破坏程序的依赖关系。幸运的是不久的将来你就不需要它了,因为OpenTracing将提供访问traceID的方法,请阅读这里[20]。
OpenTracing 和 OpenCensus
OpenCensus[21]1?不是另一个通用跟踪接口,它是一组库,可以用来与其他跟踪库集成以完成跟踪功能,因此它经常与OpenTracing进行比较。那么它与OpenTracing兼容吗?答案是否定的。因此,在选择跟踪接口时(不论是OpenTracing还是OpenCensus)需要小心,以确保你需要调用的其他库支持它。一个好消息是,你不需要在将来做出选择,因为它们会将项目合并为一个[22]1?。
结论:
全链路跟踪包括不同的场景,例如在函数内部跟踪,数据库跟踪和跨进程跟踪。每个场景都有不同的问题和解决方案。如果你想设计更好的跟踪解决方案或为你的应用选择最适合的跟踪工具或库,那你需要对每种情况都有清晰的了解。
源码:
完整源码的github链接[23]
参考资料
[1]
CorrelationID: https://hilton.org.uk/blog/microservices-correlation-id
[2]
Zipkin: https://zipkin.io/
[3]
Jaeger: https://www.jaegertracing.io/
[4]
OpenTracing: https://opentracing.io/docs/getting-started/
[5]
Zipkin Architecture: https://zipkin.io/pages/architecture.html
[6]
The OpenTracing Semantic Specification: https://opentracing.io/specification/
[7]
instrumentedsql: https://github.com/ExpansiveWorlds/instrumentedsql
[8]
luna-duclos/instrumentedsql: https://github.com/luna-duclos/instrumentedsql
[9]
ocsql/driver.go: https://github.com/opencensus-integrations/ocsql/blob/master/driver.go
[10]
Zipkin B3-propogation: https://github.com/openzipkin/b3-propagation
[11]
跟踪上下文(trace context): https://www.w3.org/TR/trace-context/
[12]
b3-propagation: https://github.com/openzipkin/b3-propagation
[13]
otgrpc: http://github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc
[14]
Go context: https://blog.golang.org/context
[15]
跟踪上下文(trace context): https://w3c.github.io/trace-context/
[16]
Zipkin兼容性功能: https://github.com/jaegertracing/jaeger-client-go/tree/master/zipkin
[17]
Istio: https://istio.io/
[18]
Linkerd: https://linkerd.io/
[19]
语义约定(Semantic Conventions): https://github.com/opentracing/specification/blob/master/semantic_conventions.md
[20]
这里: https://github.com/opentracing/specification/blob/master/rfc/trace_identifiers.md
[21]
OpenCensus: https://opencensus.io/
[22]
将项目合并为一个: https://medium.com/opentracing/merging-opentracing-and-opencensus-f0fe9c7ca6f0
[23]
完整源码的github链接: https://github.com/jfeng45/grpcservice
深度解析iOS越狱科学上网:解锁网络自由的全方位指南
在当今互联网高度管控的环境下,科学上网已成为许多用户的刚需。而对于iOS设备用户来说,越狱科学上网无疑是一条充满诱惑却又暗藏风险的道路。本文将全面剖析越狱科学上网的方方面面,从基本概念到实操步骤,从优势到风险,为您呈现一份详尽的指南。
越狱科学上网的本质与意义
所谓越狱科学上网,是指通过对iOS设备进行越狱操作,突破苹果系统的原生限制,获取更高权限,从而能够自由安装和使用各类科学上网工具,如VPN、代理等。这种方式让用户能够绕过网络封锁,访问全球互联网资源,实现真正的网络自由。
越狱的本质是对iOS系统的"解放"。苹果公司出于安全和商业考量,对iOS设备施加了诸多限制,比如只能通过App Store安装应用、无法深度定制系统等。越狱就是打破这些枷锁,让用户真正成为设备的主人。
越狱带来的三大核心优势
1. 应用安装的自由王国
越狱后最直接的改变就是可以安装任意第三方应用,不再受限于App Store的审核。这意味着:
- 可以安装各种修改版应用和游戏
- 能够使用App Store下架的优秀工具
- 可以尝试各种系统增强插件
2. 系统定制的无限可能
越狱让iOS系统的深度定制成为现实:
- 可以彻底改变系统界面和交互方式
- 能够添加各种实用功能小部件
- 支持修改系统底层参数以获得更好性能
3. 科学上网的便捷通道
这是越狱最重要的价值之一:
- 可以直接安装各类VPN客户端
- 支持配置复杂的代理规则
- 能够使用更强大的网络工具组合
越狱的潜在风险不容忽视
安全威胁
越狱相当于打开了系统的安全大门:
- 恶意软件可能乘虚而入
- 系统漏洞容易被利用
- 个人数据面临更高风险
保修与稳定性问题
- 苹果官方不承认越狱设备
- 系统崩溃风险显著增加
- 可能影响设备使用寿命
法律与道德考量
在某些地区,越狱本身可能涉及法律问题,而使用科学上网工具访问特定内容也可能引发争议。
越狱科学上网的完整实操指南
准备工作
- 数据备份:使用iTunes或iCloud完整备份
- 设备检查:确认设备型号和系统版本
- 工具选择:根据设备选择合适的越狱工具
主流越狱工具推荐
- Checkra1n:支持A5-A11芯片设备
- unc0ver:适用于多种iOS版本
- TaiG:早期越狱工具的代表
详细越狱步骤
- 下载对应越狱工具
- 连接设备到电脑
- 关闭查找我的iPhone功能
- 运行越狱程序
- 等待过程完成
- 安装Cydia商店
科学上网工具配置
成功越狱后,可通过以下方式实现科学上网:
VPN类工具
- Shadowrocket:功能强大的全能工具
- Surge:专业级网络调试工具
- Quantumult X:规则配置灵活
代理工具
- SOCKS5代理:适合P2P传输
- HTTP/HTTPS代理:网页浏览首选
组合方案
可以结合VPN和代理使用,实现更复杂的网络需求。
常见问题深度解答
Q:越狱后如何选择安全的VPN?
A:优先选择知名品牌,查看隐私政策,避免免费VPN。
Q:越狱会影响设备性能吗?
A:合理使用影响不大,但安装过多插件可能导致卡顿。
Q:如何隐藏越狱状态?
A:可使用Liberty Lite等工具屏蔽越狱检测。
Q:越狱后如何保护隐私?
A:定期清理缓存,使用安全软件,避免可疑插件。
专业点评:越狱科学上网的双面性
越狱科学上网犹如一把双刃剑,它确实为用户打开了网络自由的大门,但同时也带来了不小的安全隐患。从技术角度看,越狱打破了iOS的沙盒机制,这种突破既有解放设备的积极意义,也可能成为系统安全的致命弱点。
对于普通用户而言,是否选择越狱需要慎重考虑。如果你对网络安全有较高要求,或者设备承载重要数据,或许应该三思而行。但对于技术爱好者来说,越狱带来的可能性确实令人难以抗拒。
无论选择哪条路,都请记住:网络自由固然可贵,但安全底线更不可破。在追求开放的同时,保持警惕和理性,才能真正享受科技带来的便利。
这篇指南希望能为您提供全面的参考,但最终决策还需结合个人实际情况。科技的本质是服务人类,而非束缚人类,愿每位用户都能找到最适合自己的上网方式。
版权声明:
作者: freeclashnode
链接: https://www.freeclashnode.com/news/article-3259.htm
来源: FreeClashNode
文章版权归作者所有,未经允许请勿转载。
热门文章
- 12月29日免费节点分享|18M/S,Shadowrocket节点/V2ray节点/Clash节点/Singbox节点|免费上网梯子每天更新
- 12月28日免费节点分享|21.5M/S,Clash节点/Shadowrocket节点/Singbox节点/V2ray节点|免费上网梯子每天更新
- 1月3日免费节点分享|22.9M/S,Clash节点/V2ray节点/Shadowrocket节点/Singbox节点|免费上网梯子每天更新
- 12月26日免费节点分享|18M/S,V2ray节点/Singbox节点/Clash节点/Shadowrocket节点|免费上网梯子每天更新
- 12月23日免费节点分享|21.9M/S,SSR节点/V2ray节点/Singbox节点/Clash节点|免费上网梯子每天更新
- 12月30日免费节点分享|22.7M/S,V2ray节点/Clash节点/Singbox节点/SSR节点|免费上网梯子每天更新
- 12月27日免费节点分享|18.8M/S,V2ray节点/SSR节点/Singbox节点/Clash节点|免费上网梯子每天更新
- 1月4日免费节点分享|22.8M/S,Singbox节点/V2ray节点/Clash节点/SSR节点|免费上网梯子每天更新
- 1月2日免费节点分享|21.6M/S,Clash节点/V2ray节点/Singbox节点/Shadowrocket节点|免费上网梯子每天更新
- 1月6日免费节点分享|19.8M/S,Singbox节点/Shadowrocket节点/V2ray节点/Clash节点|免费上网梯子每天更新
最新文章
- 1月19日免费节点分享|22.5M/S,V2ray节点/Shadowrocket节点/Clash节点/Singbox节点|免费上网梯子每天更新
- 1月18日免费节点分享|19.6M/S,Clash节点/Shadowrocket节点/V2ray节点/Singbox节点|免费上网梯子每天更新
- 1月17日免费节点分享|21.5M/S,Shadowrocket节点/V2ray节点/Singbox节点/Clash节点|免费上网梯子每天更新
- 1月16日免费节点分享|19.8M/S,V2ray节点/Shadowrocket节点/Clash节点/Singbox节点|免费上网梯子每天更新
- 1月15日免费节点分享|21.9M/S,Shadowrocket节点/Singbox节点/V2ray节点/Clash节点|免费上网梯子每天更新
- 1月14日免费节点分享|19.3M/S,V2ray节点/Singbox节点/SSR节点/Clash节点|免费上网梯子每天更新
- 1月13日免费节点分享|22.6M/S,V2ray节点/Clash节点/Shadowrocket节点/Singbox节点|免费上网梯子每天更新
- 1月12日免费节点分享|20.3M/S,SSR节点/Clash节点/V2ray节点/Singbox节点|免费上网梯子每天更新
- 1月11日免费节点分享|21M/S,Clash节点/V2ray节点/SSR节点/Singbox节点|免费上网梯子每天更新
- 1月10日免费节点分享|21.5M/S,V2ray节点/Singbox节点/Clash节点/Shadowrocket节点|免费上网梯子每天更新
归档
- 2026-01 33
- 2025-12 59
- 2025-11 55
- 2025-10 56
- 2025-09 55
- 2025-08 49
- 2025-07 31
- 2025-06 30
- 2025-05 31
- 2025-04 31
- 2025-03 383
- 2025-02 360
- 2025-01 403
- 2024-12 403
- 2024-11 390
- 2024-10 403
- 2024-09 388
- 2024-08 402
- 2024-07 424
- 2024-06 446
- 2024-05 184
- 2024-04 33
- 2024-03 32
- 2024-02 29
- 2024-01 50
- 2023-12 53
- 2023-11 32
- 2023-10 32
- 2023-09 3