《架构师》2017年4月
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

Uber最初的追踪系统

Uber最初广泛使用的追踪系统叫做Merckx,这一名称源自全球速度最快的自行车骑行选手。Merckx很快就帮助我们了解了有关Uber基于Python的整体式后端的很多问题。我们可以查询诸如“查找已登录用户的请求,并且请求的处理时间超过2秒钟,并且使用了某一数据库来处理,并且事务维持打开状态的时间超过500ms”这样的问题。所有待查询的数据被组织成树状块,每个块代表某一操作或某个远程调用,这种组织方式类似于OpenTracing API中“Span”这个概念。用户可以在Kafka中使用命令行工具针对数据流执行即席查询,也可以使用Web界面查看预定义的摘要,这些信息均从API端点的高级别行为和Celery任务中摘要汇总而来。

Merckx使用了一种类似于树状块的调用图,每个块代表应用程序中的一个操作,例如数据库调用、RPC,甚至库函数,例如解析JSON。

Merckx的编排调度可自动应用于使用Python编写的一系列基础架构库,包括HTTP客户端和服务器、SQL查询、Redis调用,甚至JSON的序列化。这些编排调度可记录有关每次操作的某些性能度量值和元数据,例如HTTP调用的URL,或数据库调用的SQL查询。此外还能记录其他信息,例如数据库事务维持打开状态的时长,访问了哪些数据库Shard和副本。

Merckx架构使用了拉取模式,可从Kafka的指令数据中拉取数据流。

Merckx最大的不足在于其设计主要面向Uber使用整体式API的年代。Merckx缺乏分布式上下文传播的概念,虽然可以记录SQL查询、Redis调用,甚至对其他服务的调用,但无法进一步深入。Merckx还有另一个有趣的局限:因为Merckx数据存储在一个全局线程本地存储中,诸如数据库事务追踪等大量高级功能只能在uWSGI下使用。随着Uber开始使用Tornado(一种适用于Python服务的异步应用程序框架),线程本地存储无法体现Tornado的IOLoop中同一个线程内运行的大部分并发请求。我们开始意识到不借助全局变量或全局状态,转为通过某种方式保存请求状态,并进行恰当的传播的重要性。