RPC 系列(三十二):brpc 的 vars 变量

bvar 是多线程环境下的计数器类库,方便记录和查看用户程序中的各类数值,它利用了 thread local 存储减少了 cache bouncing,相比 UbMonitor(百度内的老计数器库)几乎不会给程序增加性能开销,也快于竞争频繁的原子操作。brpc 集成了 bvar,/vars 可查看所有曝光的 bvar,/vars/VARNAME 可查阅某个 bvar,增加计数器的方法参见 bvar 的说明。

brpc 大量使用了 bvar 提供统计数值,当你需要在多线程环境中计数并展现时,应该第一时间想到 bvar。但 bvar 不能代替所有的计数器,它的本质是把写时的竞争转移到了读:读得合并所有写过的线程中的数据,而不可避免地变慢了。当你读写都很频繁或得基于最新值做一些逻辑判断时,你不应该用 bvar。

访问 vars

  • /vars:列出所有曝光的 bvar。
  • /vars/NAME:查询名字为 NAME 的 bvar。
  • /vars/NAME1,NAME2,NAME3:查询名字为 NAME1 或 NAME2 或 NAME3 的 bvar。
  • /vars/foo*,b$r:查询名字与某一通配符匹配的 bvar,注意用 $ 代替 ? 匹配单个字符,因为 ? 是 URL 的保留字符。

以下动画演示了如何使用过滤功能。你可以把包含过滤表达式的 url 复制粘贴给他人,他们点开后将看到相同的计数器条目(数值可能随运行变化):

在 /vars 页面使用过滤表达式筛选 bvar 的演示动图

/vars 左上角有一个搜索框,能加快寻找特定 bvar 的速度。在这个搜索框你只需键入 bvar 名称的一部分,框架将补上 * 进行模糊查找。不同的名称间可以逗号、分号或空格分隔:

/vars 左上角搜索框输入部分名称进行模糊查找的演示动图

你也可以在命令行中访问 vars:

$ curl brpc.baidu.com:8765/vars/bthread*
bthread_creation_count : 125134
bthread_creation_latency : 3
bthread_creation_latency_50 : 3
bthread_creation_latency_90 : 5
bthread_creation_latency_99 : 7
bthread_creation_latency_999 : 12
bthread_creation_latency_9999 : 12
bthread_creation_latency_cdf : "click to view"
bthread_creation_latency_percentiles : "[3,5,7,12]"
bthread_creation_max_latency : 7
bthread_creation_qps : 100
bthread_group_status : "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 "
bthread_num_workers : 24
bthread_worker_usage : 1.01056

查看历史趋势

点击大部分数值型的 bvar 会显示其历史趋势。每个可点击的 bvar 记录了过去 60 秒、60 分钟、24 小时、30 天总计 174 个值。当有 1000 个可点击 bvar 时大约会占 1M 内存:

点击数值型 bvar 后查看历史趋势图的演示动图

分位值

x% 分位值(percentile)是指把一段时间内的 N 个统计值排序,排在第 N x% 位的值。比如一段时间内有 1000 个值,先从小到大排序,排在第 500 位(1000 50%)的值是 50% 分位值(即中位数),排在第 990 位的是 99% 分位值(1000 * 99%),排在第 999 位的是 99.9% 分位值。分位值能比平均值更准确地刻画数值的分布,对理解系统行为有重要意义。工业级应用的 SLA 一般在 99.97% 以上(此为百度对二级系统的要求,一级是 99.99% 以上),一些系统即使平均值不错,但不佳的长尾区域也会明显拉低和打破 SLA。分位值能帮助分析长尾区域。

分位值可以绘制为 CDF 曲线和按时间变化的曲线。

CDF 曲线

下图是分位值的 CDF,横轴是比例(排序位置/总数),纵轴是对应的分位值。比如横轴 50% 处对应的纵轴值便是 50% 分位值。如果系统要求的性能指标是”99.9% 的请求在 xx 毫秒内完成”,那么你就得看 99.9% 那儿的值:

延时分布的 CDF 曲线示例:曲线平缓上升,在 99.99% 附近快速抬升

为什么叫它 CDF(Cumulative Distribution Function,累积分布函数)?当选定一个纵轴值 y 时,对应横轴的含义是”数值 <= y 的比例”,由于数值一般来自随机采样,横轴也可以理解为”数值 <= y 的概率”,即 P(数值 <= y),这就是 CDF 的定义。

CDF 的导数是概率密度函数(PDF)。如果把 CDF 的纵轴分为很多小段,对每个小段计算两端对应的横轴值之差,并把这个差作为新的横轴,那么我们便绘制了 PDF 曲线,就像顺时针旋转了 90 度的正态分布那样。但中位数的密度往往很高,在 PDF 中很醒目,这使得边上的长尾很扁而不易查看,所以大部分系统测量结果选择 CDF 曲线而不是 PDF 曲线。

可用一些简单规则衡量 CDF 曲线好坏:一条缓慢上升且长尾区域面积不大的 CDF 便是不错的曲线。

分位值随时间变化的曲线

下图是分位值按时间变化的曲线,包含了 4 条曲线,横轴是时间,纵轴从上到下分别对应 99.9%、99%、90%、50% 分位值,颜色从上到下也越来越浅(从橘红到土黄):

分位值随时间变化的曲线:99.9%、99%、90%、50% 四条曲线,悬停显示 39 秒前 99% 分位值为 330 微秒

滑动鼠标可以阅读对应数据点的值,上图中显示的是”39 秒钟前的 99% 分位值是 330 微秒”。这幅图中不包含 99.99% 的曲线,因为 99.99% 分位值常明显大于 99.9% 及以下的分位值,画在一起的话会使得其他曲线变得很”矮”,难以辨认。你可以点击以 _latency_9999 结尾的 bvar 独立查看 99.99% 曲线。按时间变化曲线可以看到分位值的变化趋势,对分析系统的性能变化很实用。

brpc 自动统计的延时分布

brpc 的服务都会自动统计延时分布,用户不用自己加了。如下图所示:

brpc server 自动统计的 echo 服务延时分布:count、平均延时、各分位值、cdf 与 qps

你可以用 bvar::LatencyRecorder 统计任何代码的延时:

#include <bvar/bvar.h>

...
bvar::LatencyRecorder g_latency_recorder("client");  // expose this recorder
...
void foo() {
    ...
    g_latency_recorder << my_latency;
    ...
}

如果这个程序使用了 brpc server,那么你应该已经可以在 /vars 看到 client_latency、client_latency_cdf 等变量,点击便可查看动态曲线。如下图所示:

bvar::LatencyRecorder 暴露的 client 延时变量:count、各分位值、cdf 与 qps

提示:如果你的程序只是一个 brpc client 或根本没有使用 brpc,并且你也想看到动态曲线,可以启动 dummy server 提供内置服务。

系列导航


   转载规则


《RPC 系列(三十二):brpc 的 vars 变量》 由 吴杭沉 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
RPC 系列(三十三):brpc 的连接管理 RPC 系列(三十三):brpc 的连接管理
/connections 服务可以查看所有的连接。一个典型的页面如下。 server 端的连接(server_socket_count: 5): CreatedTime RemoteSide SSL Protocol fd Bytes
2024-04-16
下一篇 
RPC 系列(三十一):bvar 与性能指标 RPC 系列(三十一):bvar 与性能指标
bvar 是多线程环境下的计数器类库,方便记录和查看用户程序中的各类数值。它利用了 thread local 存储减少了 cache bouncing,相比 UbMonitor(百度内的老计数器库)几乎不会给程序增加性能开销,也快于竞争频繁
2024-04-02
  目录