☰
brpc 服务状态总览 /status 完整指南:字段含义、源码实现与自定义扩展
2026/10/9 5:17:29 网站建设 项目流程

【免费下载链接】brpc

brpc is an Industrial-grade RPC framework using C++ Language, which is often used in high performance system such as Search, Storage, Machine learning, Advertisement, Recommendation etc. "brpc" means "better RPC".

项目地址:https://gitcode.com/gh_mirrors/brpc3/brpc
点击查看免费下载

brpc 内置的/status页面是服务运维与排障的第一站,它以"服务/方法"为维度重新组织与/vars同源的 bvar 统计,集中展示每个 RPC 服务的请求量、错误、延时分位值、并发度等核心指标。读完本文,你将掌握/status上每个字段的精确含义与统计口径、HTML 与纯文本两种输出形态的差异、页面背后的源码实现链路(StatusService与MethodStatus),以及如何通过实现brpc::Describable为服务注入自定义状态描述。

/status 是什么:与 /vars 同源,按服务重组

brpc server 启动后会挂载一批内置 HTTP 服务(builtin services),/status就是其中之一。它展示的是服务进程内部的主要统计信息,数据来源与/vars完全同源(底层都是 bvar 计数器),区别在于组织方式:

  • /vars是一个扁平的 bvar 大列表,按变量名平铺展示全部计数器;
  • /status则按注册的服务(service)与方法(method)重新分组,让运维人员能一眼看清"每个方法"的独立表现。

页面的渲染入口是内置的brpc::StatusService,其default_method位于 src/brpc/builtin/status_service.cpp。它首先输出服务器version,随后按顺序输出非服务错误数、连接数、并发上限、当前并发度,再遍历Server::_fullname_service_map中所有用户注册的服务,逐方法打印统计。

/status 页面上的典型结构: version: <server version> non_service_error: <N> connection_count: <N> max_concurrency: <N> | unlimited concurrency: <N> [服务完整名(含 proto 包名)] <自定义描述(若实现了 Describable)> 方法名 (请求类型) returns (响应类型) count / qps / error / eps / latency / latency_percentiles / latency_cdf / max_latency / concurrency / max_concurrency

核心字段逐项详解

原文档对页面上各个字段给出了精确定义,下面逐项展开,并结合源码补充其统计口径与底层实现。

non_service_error:服务处理之外的错误

non_service_error表示在 service 处理代码之外产生的错误个数。判定规则是:当请求被路由到一个合法的 service 之后,后续发生的错误计为service_error;反之,在获取到合法 service 之前发生的错误都算作non_service_error,典型场景包括:

  • 请求解析失败(协议解析层面的错误);
  • service 名称不存在(路由不到任何服务);
  • 请求并发度超过上限被拒绝。

需要特别澄清的两点(原文档明确强调):

  1. 服务处理过程中访问后端服务失败(如下游 RPC 超时、连接失败)属于 service 自己的错误,不算non_service_error;
  2. 即使服务成功写出 response、但 response 内容本身代表业务失败(比如返回了错误码),该错误也会被记入对应的 service,而不是 non_service_error。

从实现上看,该计数对应 Server 上的_nerror_bvar,在 src/brpc/builtin/status_service.cpp 中直接读取其get_value()输出;同时它在 src/brpc/server.cpp 中被expose_as(prefix, "error")暴露为/vars/<server_prefix>_error,因此在/vars里也能查到这个同源指标。当 non_service_error 持续增长时,应优先检查协议不匹配、路由配置、限流配置等服务外层因素。

connection_count:客户端连接数

connection_count是向该 server 发起请求的连接个数(即服务端视角的入站连接数),不包含server 作为客户端对外发起的连接——后者记录在/vars/rpc_channel_connection_count中(channel 是 brpc 的客户端对象)。

源码中该值由Server::GetStat累加各 Acceptor 上的ConnectionCount()得出(见 src/brpc/server.cpp),并通过bvar::PassiveStatus<int32_t>以connection_count为名暴露(src/brpc/server.cpp),页面读取的是同一计数器。注意:连接数并不等于并发请求数,一个连接上可并行/串行承载多个请求。

服务名与方法签名

  • example.EchoService:服务的完整名称,包含 proto 文件中定义的 package 名。比如 proto 中package example;且 service 名为EchoService,则完整名是example.EchoService。
  • Echo (EchoRequest) returns (EchoResponse):方法的签名。一个服务可以包含多个方法,页面会逐个列出。在 HTML 页面上,请求类型与响应类型是可点击链接,点击后跳转到/protobufs/<消息完整名>查看对应 protobuf 消息的结构体定义(字段、类型、编号等)。

源码遍历逻辑位于 src/brpc/builtin/status_service.cpp:对每个用户服务取其ServiceDescriptor(d->full_name())、遍历method_count()个方法,通过MethodDescriptor取得输入/输出类型完整名,并拼出/protobufs/链接;若方法配置了 HTTP URL,还会以@<http_url>的形式附带显示。

count / error:成功与失败请求数

  • count:成功处理的请求总个数(累积值)。
  • error:处理失败的请求总个数(累积值)。

从底层看,这两个量都来自每个方法对应的brpc::MethodStatus(定义在 src/brpc/details/method_status.h):count 实际取自bvar::LatencyRecorder的_count,error 取自_nerror_bvar。计数逻辑在MethodStatus::OnResponded(method_status.h):

inline void MethodStatus::OnResponded(int error_code, int64_t latency) { _nconcurrency.fetch_sub(1, butil::memory_order_relaxed); if (0 == error_code) { _latency_rec << latency; // 成功:计入延时分位统计 } else { _nerror_bvar << 1; // 失败:error 计数 +1 } ... }

可见"成功/失败"的判定依据是Controller::ErrorCode()是否为 0(由 method_status.cpp 中的ConcurrencyRemover析构时回调)。error 对应的 bvar 以error为名暴露(_nerror_bvar.expose_as(prefix, "error")),同时存在一个eps(errors per second,每秒错误率)衍生指标。

latency / latency_percentiles / latency_cdf / max_latency:延时四件套

这是/status上信息量最大的一组指标,且HTML 与纯文本两种形态的统计窗口不同:

  • HTML 页面:从右到左依次是过去60s / 60m / 24h / 30d四个窗口的数值(曲线图)。
  • 纯文本输出:默认是最近10 秒窗口的平均值,窗口长度由-bvar_dump_interval控制。

-bvar_dump_interval在 src/bvar/variable.cpp 中定义:DEFINE_int32(bvar_dump_interval, 10, "Seconds between consecutive dump"),默认 10 秒,指 bvar 后台"每次 dump/汇总的间隔秒数",纯文本下所有瞬时统计(latency、max_latency、qps)都以它为窗口宽度。该 flag 在运行期不可热加载(源码中注册了 validator 但注释说明bvar_dump_interval is actually unreloadable)。

各指标含义:

指标含义
latency平均延时。HTML 下为右到左 60s/60m/24h/30d 四个窗口;纯文本下为最近一个 dump 间隔(默认 10s)内的平均延时
latency_percentiles延时的80%、90%、99%、99.9%分位值,统计窗口默认 10 秒(受-bvar_dump_interval控制),HTML 下有历史曲线
latency_cdf以 CDF(累积分布函数) 方式展示分位值,仅 HTML 可用
max_latency最大延时。HTML 下为右到左 60s/60m/24h/30d 四个窗口;纯文本下为最近一个 dump 间隔内的最大值

分位值的默认档位在 src/bvar/latency_recorder.cpp 中由三个 gflags 控制:

-bvar_latency_p1=80 # 第一档分位值,默认 80% -bvar_latency_p2=90 # 第二档分位值,默认 90% -bvar_latency_p3=99 # 第三档分位值,默认 99%

每档都被校验在(0, 100)开区间内(valid_percentile),且源码注释明确"修改这些 flag 不会改变已暴露 bvar 的名字,实际使用中应避免运行期重载"。99.9% 档位是固定值(_latency_999),不随上述 flag 变化。

值得一提的是:LatencyRecorder::expose()(src/bvar/latency_recorder.cpp)会按前缀暴露latency、max_latency、count、qps、latency_80/90/99(纯文本)、latency_999、latency_9999、latency_cdf(HTML)与latency_percentiles(HTML)等一组 bvar,这就是/status与/vars同源的直接证据——页面字段与 bvar 名一一对应。

qps:每秒请求数

qps(Queries Per Second)在 HTML 下同样是从右到左的 60s/60m/24h/30d 四个窗口;纯文本下是最近一个 dump 间隔(默认 10s)内的平均 QPS。底层来自LatencyRecorder的_qps(bvar::PerSecond衍生指标),读取的是latency窗口内的请求数与时间跨度之比(见LatencyRecorder::qps(),src/bvar/latency_recorder.cpp),实现上用浮点换算以避免溢出。

processing / concurrency:当前正在处理的请求数

processing(master 分支已改名为concurrency)表示正在被方法处理的请求个数。这是排查服务卡死最关键的指标:如果服务流量归零后该计数仍持续不为 0,server 大概率存在 bug,例如忘记调用done->Run()(回调未触发),或请求卡死在某个处理步骤上。

从源码看,该方法级并发数来自MethodStatus的原子计数器_nconcurrency(butil::atomic<int>,method_status.h):

  • 请求到达时MethodStatus::OnRequested中_nconcurrency.fetch_add(1, ...)(method_status.h);
  • 请求结束时OnResponded中_nconcurrency.fetch_sub(1, ...)。

两个操作都使用memory_order_relaxed,仅用于观测统计、不参与同步。方法级concurrency通过_nconcurrency_bvar(PassiveStatus<int>,读取回调cast_int)以concurrency为名暴露(method_status.cpp)。

页面头部还输出两个服务级指标(见 status_service.cpp):

  • max_concurrency:服务级并发上限,取自ServerOptions::max_concurrency;若<= 0则显示unlimited(不限流);
  • concurrency:服务级当前并发数,来自Server::Concurrency()(src/brpc/server.h),是_concurrency的原子读。

方法级同样有独立的max_concurrency(当该方法配置了ConcurrencyLimiter时输出,读取_max_concurrency_bvar)。

HTML 与纯文本:两种输出形态

/status会根据 HTTP 请求的 Accept 头/访问方式自动选择输出形态(UseHTML(cntl->http_request())判定),并设置对应的Content-Type:

  • HTML(text/html):带完整页面骨架(<!DOCTYPE html>)、tab 导航(PrintTabsBody)、flot 曲线占位符(class="flot-placeholder"),latency_percentiles / latency_cdf / qps / concurrency 等字段均渲染为可点击的动态曲线。支持?expand查询参数控制是否展开全部曲线(cntl->http_request().uri().GetQuery("expand"))。
  • 纯文本(text/plain):源码注释明确其格式刻意兼容public/configure的键值格式,便于脚本直接解析加载。此时分位值展开为独立的latency_50 / latency_90 / latency_99 / latency_999 / latency_9999五行(见MethodStatus::Describe的非 HTML 分支,method_status.cpp),且 99.9% 与 99.99% 档位只在纯文本下可见。可用curl直接拉取:
# 纯文本形态,每行一个 "key: value" curl http://<server_addr>/status # 只看某个服务的分位值(通过 /vars 定位同名 bvar) curl http://<server_addr>/vars/<server_prefix>_latency_percentiles

需要说明:页面上的 latency/latency_percentiles/max_latency/qps 等字段在 HTML 下展示的是 60s/60m/24h/30d 多窗口曲线(对应 bvar 内部为可点击变量保存的历史采样值),而纯文本形态只反映当前 dump 窗口(默认 10s)内的值,两者统计口径不同、各有用途。

源码级原理:StatusService 与 MethodStatus 的分工

/status的生成可以拆成两条链路:

1. 页面骨架与字段排版 ——StatusService::default_method(src/brpc/builtin/status_service.cpp)

  • 输出version(server->version());
  • 输出服务级指标:non_service_error(server->_nerror_bvar)、connection_count(server->GetStat)、max_concurrency、concurrency(server->Concurrency());
  • 遍历_fullname_service_map,跳过非用户服务(!sp.is_user_service())与Tabbed类型服务(这类监控页自己的状态不重要,源码注释// Tabbed services are probably for monitoring);
  • 若服务实现了Describable,先输出自定义描述;
  • 逐方法输出签名与MethodStatus::Describe的结果;
  • 末尾追加可选的BaiduMasterService、NsheadService、ThriftService(ENABLE_THRIFT_FRAMED_PROTOCOL编译开关下)及 RTMP 消息统计。

2. 方法级指标采集与格式化 ——MethodStatus(src/brpc/details/method_status.h、method_status.cpp)

每个服务方法对应一个MethodStatus实例,它在OnRequested(请求进入)与OnResponded(请求结束,携带error_code与耗时微秒)之间完成全部计数。Describe方法负责把内部 bvar 组织成可读输出(count/qps/error/eps/latency/latency_percentiles/latency_cdf/max_latency/concurrency[/max_concurrency]),HTML 模式下每个数值都包上<span id="value-<bvar_name>">与 flot 占位 div,供前端 JS 拉取曲线。

由于所有数值底层都是 bvar,你可以随时在/vars中按名字精确定位到同一份数据(例如<server_prefix>_connection_count、<server_prefix>_concurrency、<service_name>.<method_name>_latency_percentiles),实现页面与脚本监控的互相印证。

自定义描述:实现 brpc::Describable

用户可以通过让对应 Service 实现brpc::Describable接口,在/status的服务名下追加自定义描述文本。接口定义在 src/brpc/describable.h:

class Describable { public: virtual ~Describable() {} virtual void Describe(std::ostream& os, const DescribeOptions&) const { os << butil::class_name_str(*this); } };

默认实现只输出类名;子类重写Describe即可输出任意状态。DescribeOptions(describable.h)包含两个成员:

  • verbose:是否输出详细信息(页面渲染时StatusService置为true);
  • use_html:是否以 HTML 形式输出(跟随页面形态,status_service.cpp中按use_html透传)。

原文档给出的标准写法:

class MyService : public XXXService, public brpc::Describable { public: ... void Describe(std::ostream& os, const brpc::DescribeOptions& options) const { os << "my_status: blahblah"; } };

StatusService在遍历服务时通过dynamic_cast<Describable*>(sp.service)探测服务是否实现该接口(status_service.cpp),命中则调用Describe,并把输出插在服务名([服务完整名])与方法列表之间;输出不以换行结尾时自动补\n。因此你可以在描述里输出业务自定义状态、版本号、缓存水位、后端依赖健康状况等,随/status一并暴露给监控系统。若实现的是可写状态(需要非 const 访问),可使用配套的NonConstDescribable接口。

基于 /status 的常见排障实践

  1. 服务卡死排查:流量归零后,观察各方法concurrency(processing)是否归零。若某个方法持续不为 0,优先检查该方法的回调是否遗漏done->Run(),或是否存在死锁/阻塞调用——ConcurrencyRemover在析构时才回调OnResponded(method_status.cpp),回调不触发则计数永远挂住。
  2. 错误分类定位:non_service_error上涨,问题在服务外层(协议解析、路由、限流拒绝);某个方法自己的error/eps上涨,问题在该服务处理链路(含对后端的访问失败)。
  3. 长尾延迟分析:平均latency正常不代表 SLA 达标,要看latency_percentiles的 99%/99.9% 与latency_cdf曲线在 99%~100% 区间(长尾区)的表现;99.9% 与 99.99% 分位值在纯文本形态下以latency_999 / latency_9999单独给出。
  4. 容量观测:qps多窗口曲线反映流量趋势,connection_count反映连接规模,max_concurrency/concurrency反映限流与积压情况,可结合 docs/en/vars.md 中的-bvar_dump_interval、分位值背景知识一起阅读。

说明:本文所有字段释义均以 docs/en/status.md 为准,源码引用来自上述 brpc 仓库文件;/status页面为 brpc server 内置服务,运行任一 brpc server 后即可通过http://<server_addr>:<port>/status访问验证(HTML 形态可直接浏览器打开,纯文本形态可用curl获取)。

【免费下载链接】brpc

brpc is an Industrial-grade RPC framework using C++ Language, which is often used in high performance system such as Search, Storage, Machine learning, Advertisement, Recommendation etc. "brpc" means "better RPC".

项目地址:https://gitcode.com/gh_mirrors/brpc3/brpc
点击查看免费下载

相关推荐

上一篇:一条命令搞定 WAV 转 M4A:qaac 音频编码器实用指南
下一篇:G6 交互式创建边 CreateEdge 行为完全指南:配置、事件机制与源码解析

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询