如今企业内部的 API 服务越来越多,对业务应用的管理质量要求也随之提高。因此,在当下敏捷开发、持续交付的行业趋势中,如何快速发现与定位服务故障成了企业不可忽视的重要环节。
品高云通过分布式跟踪与日志服务(DTLS,Distributed Tracing and Logging Service)与 API 网关的结合,形成以请求为维度的分布式跟踪信息机制,使开发、维运人员能够快速发现、定位与响应 API 服务的潜在与已存在的各种问题,从而提高企业的服务品质。

两大困局

在传统模式的 API 开发与运维过程中,开发、运维人员多多少少都会遇到以下两个问题。

重复埋点

埋点指的是在开发人员在对一个不稳定的、关键的代码点增加调试信息,而这些 “点” 往往在外部系统。
在分布式环境下,往往一个 API 接口的业务处理执行了多个远程调用以及大量的 SQL 语句,而这些调用往往都具有关键性与不稳定性,为了保证线上能够定位问题,开发人员就需要到处埋点,最后输出到日志文件中。

大海捞针

当 API 发生应用故障时(尤其在生产环境下),传统的问题定位模式基本都是通过查看日志文件的方式,然而在巨大的日志文件面前,如何找到用户 “那一次出问题的请求” 或者 “那一堆出问题请求的所有信息” 成为了一件很有挑战的事情,其根源归结于:

  • 日志文件太大;
  • 日志文件中各请求信息以时间穿插,并不是以请求划分;
  • 开发人员缺漏埋点信息;

在这些条件下,光是找到问题信息往往就要花掉不少时间;而如果事先没做好埋点,甚至还有可能定位不到问题产生的原因。

三种视图

围绕以上两个问题,再根据品高云多年项目经验中对企业需求的理解,我们的解决方法是通过分布式跟踪与日志服务结合网关为企业提供以 API、请求为维度的可视化的分布式调用跟踪。

企业内的各信息化供应商可以通过接入网关轻松获得分布式跟踪的能力,以帮助企业进行信息化运营与维护;企业管理者也可以通过网关查看各种 API 信息视图,获得有价值的决策参考数据。

调用日志

当 API 接入 DTLS 后,通过网关控制台的调用日志,可以很清楚的看到每一次的请求信息,并且还包括该请求所有的 HTTP 外部调用、JDBC 执行、程序日志信息等,同时带有多种维度的过滤过能。

通过该界面,研发人员、运维人员都可以很方便的定位问题所在,其中包括:

  • 是哪个用户调用的?
  • 调用了哪些外部系统?用了多少时间?
  • 都执行了哪些 SQL?用了多少时间?
  • 各个节点的 API 都输出了哪些程序日志?

    ……

访问趋势

访问趋势视图可以提供以时间为维度的图形数据,企业可以很容易的看到各 API 在不同时间段内的使用情况。

错误统计

通过该视图,可以很容易地看到 API 的错误数量,发现潜在的问题。

四个阶段

从上图可以看到,DTLS 的核心组件 Agent 嵌入到了网关运行时与后端应用中。通过 javaagent 技术,Agent 可以无缝嵌入到已有的应用中,负责日志生成、日志采集、日志推送等阶段,而当日志推送到日志数据库后,网关控制台便会通过查询日志数据库来获得以请求为维度的跟踪日志与程序日志。

日志生成

Agent 在应用加载类时,能够动态修改类的字码节,从而在关键方法中植入跟踪的埋点代码,形成 Google Dapper 规范的跟踪日志并输出到日志文件。
目前支持的跟踪类型包括:

  • HTTP 接收:在 Servlet 的 service 方法 与 Filter 的 doFilter 方法中植入埋点代码跟踪请求的接到与响应信息。
  • HTTP 发送:在 Socket 的读写方法中植入埋点代码,由于 Socket 的数据是二进制数据,所以还需要进行数据解析,如果判断的结果是 HTTP 外调,则会跟踪请求与响应信息。
  • JDBC:拦截 JDBC 的 Connection、Statement、PreparedStatement 这几个接口的实现类,关在执行 SQL 的关键方法中植入跟踪代码,记录 SQL 的语句、执行时间、返回结果等。
  • Logback:拦截 Logback 的日志输出方法,记录其内容。

通过以上三种类型的拦截,最后会形成两大类日志:

  • 跟踪日志:主要包含 Servlet、Filter 处理、与 SQL 这种外部调用的接收与发送时间以及其中的内容与结果,通过记录这些信息最后形成调用日志。
  • 程序日志:通过拦截 Servlet 与 Filter 处理请求时由 Logback 产生的程序日志,最终将这些日志与上一步的跟踪日志结合起来,最终形成以请求为维度的程序日志。

目前,Agent 的拦截支持 JDK6、JDK7、JDK8。

日志采集

Agent 程序包内嵌了 Filebeat 采集程序,随 Agent 启动与关闭,实时对 Agent 产生的日志进行解析,最后根据不同的日志类型推送到相应的索引库中。

日志推送

日志数据入库时,首先会经过品高云的 ES 插件 IdxRouter 对需要入库的日志数据进行索引路由。IdxRouter 支持可配置的的路由策略,通过表达式定义的方式,以日志数据内容为依据,最后将日志写到不同的索引库中。
网关通过 IdxRouter 将日志数据作应用级别的隔离,保障了企业内各 IT 供应商的数据安全。
示例如下:

 1idxrouter.routers:
 2  # 路由器的名称
 3  dtls:
 4    actions:
 5    # 这里指定什么 action 需要路由,不设置则表示全部路由
 6      - "indices:data/write/index"
 7      - "indices:data/write/update"
 8    # 要匹配的索引(正式表达式) 
 9    from"^(trace-log|prog-log|op-log).*$"
10    # 把匹配的索引重命名为新的索引名,目前支持变量
11    # - index 当前的索引名称
12    # - username 当前登录的用户名
13    # - date:[format] 日期,并支持定义日期变量的格式
14    to"{{index}}-{{doc:log_account,username}}-{{date:yyyyMM}}"

 日志查询

通过连接日志数据库,网关可以为终端用户提供多种维度的、以请求为基础的跟踪与日志信息,让用户能清晰的知道这次请求的过程。

总结

随着企业信息化程度越来越发达,品高云分布式跟踪与日志服务将致力于帮助用户在难以计数的 API 面前实现清晰、可视的统筹管理,深度发掘 API 的价值,进而提高企业的整体服务质量,在激烈的市场竞争中立于不败之地。