大家都知道istio可以帮助我们实现灰度发布、流量监控、流量治理等一些功能。
每一个功能都帮助我们在不同场景中实现不同的业务。那么其中比如流量监控这种复杂的功能Istio是如何让我们在不同的应用中实现呢?
因篇幅所限,我们今天重点介绍Istio里面实现这些功能的关键技术--调用链跟踪。
虽然 Istio 代理能够自动发送 Span 信息,但还是需要一些辅助手段来把整个跟踪过程统一起来。应用程序应该自行传播跟踪相关的 HTTP Header,这样在代理发送 Span 信息的时候,才能正确的把同一个跟踪过程统一起来。在Istio中的Sidecar里面已经实现了埋点的逻辑,业务代码不用调用以上这些埋点方式来创建trace,维护span等这些复杂逻辑,但是为了能真正形成一个完整的链路,业务代码在某些场景下还是需要做适当修改。
1
服务调用关系
为了便于大家理解,我们以Istio最经典的Bookinfo为例来说明。Bookinfo的4个微服务的调用关系如下图所示,在这里我们不就具体阐述了。
然后我们要弄明白几个问题:什么是调用链跟踪?为什么要用调用链跟踪?
调用链跟踪顾名思义就是服务与服务之间相互调用的时候,来记录下调用的关系。比如用户发起请求访问Ingress,这是入口。然后Ingress——>Productpage——>Reviews——>Ratings这是一个完整的调用链,而这个过程中的谁调用谁的关系就是调用链跟踪。
当我们获得了服务之间调用的关系,就可以对流量状况进行一个微观监控。比如当我们发现流量异常时,通过调用链跟踪我就可以清晰的知道流量异常出现在哪一块服务调用中,又或是提取调用中的响应时延等等。
2
如何实现
在上文中,我们说Istio要实现调用链跟踪需要去修改用户的代码,其实就是采用一种被称为埋点的方法。
在Istio中对于经过sidecar流出的流量,如例子中ingress调用productpage,或者productpage调用details和reviews的请求。如果经过sidecar时header中没有任何跟踪相关的信息,则会创建根span,并将该根span相关上下文信息放在请求头中传递给下一个调用的服务,当然调用前会被目标服务的sidecar拦截掉执行上面流入的逻辑;当存在trace信息时,sidecar从header中提取span相关信息,并基于这个span创建子span,并将新的span信息加在请求头中传递。
如下所示就是需要在请求头中传递的字段信息,包括traceid、spanid等。被调用的服务接收trace相关的header并在请求时发送出去,这样在出流量的proxy向下一跳服务发起请求前才能判断并生成子span并和原span进行关联,进而形成一个完整的调用链。否则,如果在应用容器未处理Header中的trace,则Sidecar在处理outbound的请求时会创建根span,最终会形成若干个割裂的span,并不能被关联到一个trace上。这就是为何需要部分的修改应用代码。
-
x-request-id
-
x-b3-traceid
-
x-b3-spanid
-
x-b3-parentspanid
-
x-b3-sampled
-
x-b3-flags
-
x-ot-span-context
3
业务场景
最后让我们看一下实现了调用链跟踪的一些具体场景,如下图所示:
从上图中可以看到在某种场景下的所有应用、实例名称、状态以及总调用耗时、traceID等信息,这些信息给我们提供了最直观的调用数据,点击查看调用关系,将会看到更加详细的调用链信息。如下图:
从这张图中,我们可以监测到不同服务间更加详细的调用数据。
如该调用链包含三个应用,最大调用深度为2,不同应用直接调用的耗时以及应用状态等,这些都是在实际场景中非常具有价值的信息。设想在一个大规模高并发以及巨大访问量的业务中,如果我们可以对业务的监测可以细化到这种程度,那么我们的业务将会处于更加安全的保护中。
通过以上场景以及扩展信息我们就可以清晰的看到服务之间调用的具体信息,例如请求状态、响应时延等等,而这些信息都是通过调用链跟踪获取的。
相关服务请访问