转自:bvar | bRPC
1.介绍
bvar是多线程环境下的计数器类库,方便记录和查看用户程序中的各类数值,它利用了thread local存储减少了cache bouncing。
适用情况:
bvar不能代替所有的计数器,它的本质是把写时的竞争转移到了读:读时需要合并所有写过的线程中的数据,而不可避免地变慢了。当你读写都很频繁或得基于最新值做一些逻辑判断时,你不应该用bvar。适用于写多读少的情况。
2.单维度bvar
https://github.com/apache/brpc/blob/master/docs/cn/bvar_c++.md#bvarpassivestatus

#include <bvar/bvar.h>
namespace foo {
namespace bar {
// bvar::Adder<T>用于累加,下面定义了一个统计read error总数的Adder。
bvar::Adder<int> g_read_error;
// 把bvar::Window套在其他bvar上就可以获得时间窗口内的值。
bvar::Window<bvar::Adder<int> > g_read_error_minute("foo_bar", "read_error", &g_read_error, 60);
// ^ ^ ^
// 前缀 监控项名称 60秒,忽略则为10秒
// bvar::LatencyRecorder是一个复合变量,可以统计:总量、qps、平均延时,延时分位值,最大延时。
bvar::LatencyRecorder g_write_latency("foo_bar", "write");
// ^ ^
// 前缀 监控项,别加latency!LatencyRecorder包含多个bvar,它们会加上各自的后缀,比如write_qps, write_latency等等。
// 定义一个统计“已推入task”个数的变量。
bvar::Adder<int> g_task_pushed("foo_bar", "task_pushed");
// 把bvar::PerSecond套在其他bvar上可以获得时间窗口内*平均每秒*的值,这里是每秒内推入task的个数。
bvar::PerSecond<bvar::Adder<int> > g_task_pushed_second("foo_bar", "task_pushed_second", &g_task_pushed);
// ^ ^
// 和Window不同,PerSecond会除以时间窗口的大小. 时间窗口是最后一个参数,这里没填,就是默认10秒。
} // bar
} // foo
// 使用时的例子
// 碰到read error
foo::bar::g_read_error << 1;
// write_latency是23ms
foo::bar::g_write_latency << 23;
// 推入了1个task
foo::bar::g_task_pushed << 1;
- Window<>和PerSecond<>都是衍生变量,会自动更新。确认变量名是全局唯一的。
- 不要跨文件定义全局Window或PerSecond。因为存在编译优化,不同cpp的变量并不能确定定义的先后顺序。
为什么要区分前缀和监控项?
前缀可以表示命名空间,形成层级结构,比如你可能有 foo_bar 前缀下的多个不同监控项(如 write、read、update 等),它们共享相同的前缀,但监控项不同。这样在查看指标时,可以很方便地过滤和分组相关的指标。
3.注册到全局表
用户以默认参数建立一个bvar时,这个bvar并未注册到任何全局结构中。况下,bvar纯粹是一个更快的计数器。我们称把一个bvar注册到全局表中的行为为“曝光”,可通过expose函数曝光:
全局曝光后的bvar名字便为name或prefix + name。
// 没太理解,用到时再说吧。
4.PassiveStatus
PassiveStatus 是一个用于动态生成指标值的类。与常规的 bvar 指标(如 bvar::LatencyRecorder 等)不同,PassiveStatus 的值并不是直接由代码逻辑主动设置的,而是通过一个回调函数动态计算和获取的。
例子:
static void get_username(std::ostream& os, void*) {
char buf[32];
if (getlogin_r(buf, sizeof(buf)) == 0) {
buf[sizeof(buf)-1] = '\0';
os << buf; // 将用户名输出到流中
} else {
os << "unknown"; // 如果获取失败,返回 "unknown"
}
}
PassiveStatus<std::string> g_username("process_username", get_username, NULL);
- g_username:一个 PassiveStatus 对象,用于暴露当前进程的用户名作为监控指标,指标名称为 process_username。
- get_username:这是一个回调函数,PassiveStatus 会调用这个函数来生成其值。
- 使用 getlogin_r 获取当前进程所属的用户名。
每当 PassiveStatus 的值被访问时(例如通过 /vars 页面),get_username 函数都会被调用,以动态生成当前的用户名。
PassiveStatus 通常用于以下场景:动态生成数据、减少存储开销、便捷的指标暴露;
构造函数:
template <typename T>
class PassiveStatus {
public:
PassiveStatus(const std::string& name, void (*callback)(std::ostream&, void*), void* arg);
// ...
};
- name:指定指标的名称,用户可以通过 /vars/<name> 查看对应的值。例如,上述代码中可以通过 /vars/process_username 查看当前用户名。

1020

被折叠的 条评论
为什么被折叠?



