微服务:哪个地方出问题了

43 阅读4分钟

背景

项目向微服务转变过程中(还未上K8S,为主机版本),有一天早上我愉快的研究这K8S,突然线上产生了严重的告警,mongodb的CPU,内存激增,并且微服务部署机器内存已经爆满;从而导致平台崩掉。紧急情况下,部门开始对线上的机器进行逐一排查,最终发现是某个服务某个接口性能存在问题,耗时2小时;

从结果来看,我们急需一些手段进行线上问题的跟踪排查;对于微服务来说存在以下几个问题:

  • 未对微服务的内存,CPU的使用进行限制;
  • 用户是通过前端网关进行接口访问,没有手段快速得知是后端哪个服务,哪个接口产生的问题;

对于第一个问题,简单的处理方式也是演进方向就是直接上K8S进行限制;第二个问题,我们思考下,如果我通过各种手段已经知道了是哪个微服务,哪个接口=>如果想看日志的话,我该去这个服务的哪个实例上看日志=>如果我们也有日志中心汇总了=>那么我们因为怎么找到这一次调用对应的日志(日志都是时间顺序);

思路

云原生中有一个概念叫做服务可观测性,可观测性分为:metric,trace,log;

对于以上问题,可以通过tracing结合log进行快速定位;

  1. 在前端API调用时生成一条tracing,向下调用时,关键路径都传入该链路信息,将traceID写入到http响应头中,这样一次调用报错,可以通过前端http响应头中的TraceID到链路追踪系统中查询到该链路;快速定位服务以及接口。
  2. 在微服务关键日志打印可采取以下两种策略:
    1. 关键信息少许重要日志可直接打印到链路追踪中;
    2. 程序日志打印时都携带tracingId作为索引,最终吐到ELK的日志系统中;

日志方面比较简单,接下来重点介绍下什么是trace;

什么是Trace

Trace的规范叫:OpenTracing;

早在 2005 年,Google 就在内部部署了一套分布式追踪系统 Dapper,并发表了一篇论文《Dapper, a Large-Scale Distributed Systems Tracing Infrastructure》,阐述了该分布式追踪系统的设计和实现,可以视为分布式追踪领域的鼻祖。

--《opentracing详解》

当这个论文发布后,开启了各派的华山论剑,比较有名的比如Twitter的zipkin,Uber的jaeger,大众点评的CAT,以及吴晟大佬的Skywalking;

在选型过程中,需要对自身项目的技术栈,后续的演进方向,性能等综合方面考虑进行。而我想法就比较简单的,跟踪CNCF大哥走,选择了jaeger。当然jaeger的性能也不差,毕竟CNCF毕业推荐组件。

话说回来,OpenTracing作为一个规范,有必要了解它是啥?这里只介绍关键最应该理解的部分:

Trace:一条跟踪调用链,每一个跨度叫做Span, Span的调用数据结构一样,有祖宗,有爷爷,有父亲,有儿子等等,每个阶段(Span)包含如下状态:

  • Operation Names: 操作名称,在创建时需要传参;
  • 起始时间(组件自动生成,跟当前程序时区相关)
  • 结束时间(同上)
  • Tags/Attribute: 一组 KV 值,作为阶段的标签(Span Tags)
  • Log: 阶段日志
  • SpanContext: 阶段上下文,其中包含 Trace ID 和 Span ID
  • 引用关系(References)

查询如下:

每一条span点开,可以看到状态信息:

如果有阶段服务发生问题,那么前端会打红色感叹号。

总结

在云原生中,有丰富的组件能够帮助观测服务性能指标,当然在各派华山论剑过程中,CNCF站了出来,发布了未来可观测性重磅炸弹--->openTelemetry,小唐的项目中就采用opentelemetry+jaeger进行分布式链路追踪部署。

公众号图片.png