文章转载自:brpc学习:bvar
一.介绍
bvar是多线程环境下的计数器类库,方便记录和查看用户程序中的各类数值,它利用了thread local存储减少了cache bouncing,相比UbMonitor(百度内的老计数器库)几乎不会给程序增加性能开销,也快于竞争频繁的原子操作。
brpc集成了bvar,http接口下的/vars可查看所有曝光的bvar,/vars/VARNAME可查阅某个bvar,在brpc中的使用方法请查看vars。
brpc大量使用了bvar提供统计数值,当你需要在多线程环境中计数并展现时,应该第一时间想到bvar。
但bvar不能代替所有的计数器,它的本质是把写时的竞争转移到了读:读得合并所有写过的线程中的数据,而不可避免地变慢了。当你读写都很频繁或得基于最新值做一些逻辑判断时,你不应该用bvar。
常用的bvar有:
•bvar::Adder : 计数器,默认0,varname << N相当于varname += N。
•bvar::Maxer : 求最大值,默认std::numeric_limits::min(),varname << N相当于varname = max(varname, N)。
•bvar::Miner : 求最小值,默认std::numeric_limits::max(),varname << N相当于varname = min(varname, N)。
•bvar::IntRecorder : 求自使用以来的平均值。注意这里的定语不是“一段时间内”。一般要通过Window衍生出时间窗口内的平均值。
•bvar::Window : 获得某个bvar在一段时间内的累加值。Window衍生于已存在的bvar,会自动更新。
•bvar::PerSecond : 获得某个bvar在一段时间内平均每秒的累加值。PerSecond也是会自动更新的衍生变量。
•bvar::LatencyRecorder : 专用于记录延时和qps的变量。输入延时,平均延时/最大延时/qps/总次数 都有了。
•bvar::Status:记录和显示一个值,拥有额外的set_value函数。
•bvar::PassiveStatus:按需显示值。在一些场合中,我们无法setvalue或不知道以何种频率setvalue,更适合的方式也许是当需要显示时才打印。用户传入打印回调函数实现这个目的。
二. bvar的导出
最常见的导出需求是通过HTTP接口查询和写入本地文件。前者在brpc中通过内置的http服务提供(即通过/vars/xxx访问),后者则已实现在bvar中,默认不打开。
1. bvar_dump方式
可以通过flag打开:
当bvar_dump_file不为空时,程序会启动一个后台导出线程以bvar_dump_interval指定的间隔更新bvar_dump_file,其中包含了被bvar_dump_include匹配且不被bvar_dump_exclude匹配的所有bvar。
注意:bvar程序必须要在持续运行中,才会记录下bvar,一闪而过的简单程序,不会记录下bvar值。
三.通过bvar_dump方式导出示例代码
#include <bvar/bvar.h>
#include <gflags/gflags.h>
#include <glog/logging.h>
#include <iostream>
using namespace std;
int main(int argc, char* argv[]) {
google::ParseCommandLineFlags(&argc, &argv, true);
bvar::Adder<int> g_read_error;
g_read_error << 10 << 20;
g_read_error.expose("add_reader");
bvar::Status<int> foo_count2;
foo_count2.expose("foo_count2");
for(int i=0; i<2000; ++i) {
foo_count2.set_value(i);
int a;
cin >> a;
if(a == 0){
break;
}
}
return 0;
}
编译:
cc_binary(
name = 'bvar',
srcs = 'bvar.cpp',
deps = [
'#brpc',
'#gflags',
'#glog'
]
)
flag文件bvar.gflags:
-bvar_dump=true
-bvar_dump_interval=1
运行后,在当前目录会生成monitor文件夹,进入后会产生两个文件:
bvar.bvar.data
bvar.bvar.system.data
带system的bvar记录了系统监控值,第一个文件里记录了add_reader和foo_count2值:
bvar_add_reader : 30
bvar_bthread_key_count : 0
bvar_bthread_keytable_count : 0
bvar_bthread_keytable_memory : 0
bvar_bthread_stack_count : 0
bvar_bvar_dump_interval : 1
bvar_bvar_sampler_collector_usage : 0.000225182
bvar_foo_count2 : 4
默认bvar_dump_interval是10s,即每10s更新一次文件,可以设置短一点,看出效果,每执行一次循环,bvar_foo_count2值就加1。
四.http获取bvar示例代码
当然也可以通过brpc内置的http服务获取bvar。
如果你的程序只使用了brpc的client或根本没有使用brpc,但你也想使用brpc的内置服务,只要在程序中启动一个空的server就行了,这种server称为dummy server。
只要在程序运行目录建立dummy_server.port文件,填入一个端口号(比如8888),程序会马上在这个端口上启动一个dummy server。在浏览器中访问它的内置服务,便可看到同进程内的所有bvar。
示例代码:
#include <bvar/bvar.h>
#include <iostream>
#include <brpc/server.h>
using namespace std;
int main(int argc, char* argv[]) {
brpc::StartDummyServerAt(8080);
bvar::Status<int> foo_count2;
foo_count2.expose("foo_count2");
for(int i=0; i<2000; ++i) {
foo_count2.set_value(i);
int a;
cin >> a;
if(a == 0){
break;
}
}
return 0;
}
编译文件与上面一样,运行后,就可以像brpc那样,通过访问http接口就可以访问所有的bvar了。
如访问foo_count2这个bvar,就通过下面的url访问:http://192.168.12.32:8080/vars/foo_count2