brpc parallel_http 实战:一条命令并行访问数万个 HTTP 服务并聚合内置信息
【免费下载链接】brpcbrpc 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/GitHub_Trending/brpc/brpc
导读
parallel_http是 brpc 官方提供的高并发 HTTP 访问工具,可在命令行中同时发起成千上万个 HTTP 请求(量级可达数万),典型场景是查询线上所有 server 的内置信息(如 /status、/vars)供其他工具进一步过滤与聚合。阅读本文后,你将掌握 parallel_http 的编译方法、全部命令行参数、典型管道用法,以及其基于 bthread 与 brpc Channel 的异步并发实现原理。
一、为什么需要 parallel_http:curl 做不到的高并行度
在大型分布式系统中,运维排查常需要"一次性查询线上全部机器的状态"。brpc 每个 server 都通过 HTTP 暴露了丰富的内置服务(见 内置服务说明),包括 /status、/vars、/connections、/flags、/rpcz 等,而parallel_http正是为"批量拉取这些信息"而生的命令行工具。
原文档(docs/cn/parallel_http.md)点明了它的定位:
parallel_http 能同时访问大量的 http 服务(几万个),适合在命令行中查询线上所有 server 的内置信息,供其他工具进一步过滤和聚合。
为什么 curl 很难胜任?关键瓶颈在并行度:
- curl 单进程一次只能访问一个 URL,即使以多个 curl 后台运行的方式"并行",并行度一般也只有百左右;
- 当目标机器规模达到几万台时,用 curl 需要等待极长的时间,且进程管理、结果汇聚都非常繁琐;
- parallel_http 基于 brpc 的异步 HTTP Channel 与 bthread 协程调度,默认即可同时保持上千个在途请求(
-concurrency默认 1000),并可大幅调高,使"几万台机器"的量级在合理时间内完成拉取。
brpc 官方将其收录于"工具"分类(见 README_cn.md),与 rpc_press、rpc_replay、rpc_view、benchmark_http 并列,是日常排障工具箱中面向 HTTP 批量访问的一环。
二、获取与编译
2.1 前置条件:先编译 brpc
parallel_http 是 brpc 源码树内自带的小工具(源码位于 tools/parallel_http/parallel_http.cpp),需要先按 快速开始指南 编译出 brpc 静态库后才能构建。
使用 CMake 编译 brpc(同时会构建 tools 下的 parallel_http):
mkdir build && cd build cmake .. && cmake --build . -j6在 CMake 构建体系下,tools/CMakeLists.txt 通过add_subdirectory(parallel_http)将其纳入构建,并把可执行文件输出到${PROJECT_BINARY_DIR}/output/bin;tools/parallel_http/CMakeLists.txt 中将其链接到brpc-static静态库,同时通过install(TARGETS parallel_http ...)支持安装到${CMAKE_INSTALL_BINDIR}。
2.2 使用 Makefile 单独编译
也可以进入工具目录单独编译(使用 config_brpc.sh 体系时):
cd tools/parallel_http && make对应的 Makefile 依赖仓库根目录的config.mk,头文件取自output/include,静态链接output/lib/libbrpc.a,编译选项为-std=c++14 -O2,产物即为当前目录下的parallel_http可执行文件。
三、命令行参数全解
parallel_http 使用 gflags 解析命令行参数,全部参数由源码中的DEFINE_*宏定义(见 tools/parallel_http/parallel_http.cpp),用法为-参数名=值,也可用--help查看完整说明。核心参数如下:
| 参数 | 默认值 | 含义 |
|---|---|---|
-url_file | 空 | 存放待访问 URL 的文件路径;为空时从标准输入 stdin 逐行读取 |
-timeout_ms | 1000 | 单次 RPC 超时时间(毫秒) |
-max_retry | 3 | 最大重试次数(不含首次 RPC) |
-thread_num | 8 | 用于访问 URL 的 bthread 线程数 |
-concurrency | 1000 | 同时在途的 HTTP 调用数上限(全局并发度) |
-one_line_mode | false | 输出为URL HTTP响应单行格式 |
-only_show_host | false | 仅打印主机名(host),不打印完整 URL 与路径 |
参数间的内在约束(源码可印证):
- 单线程并发额度:每个线程的并发上限为
FLAGS_concurrency / FLAGS_thread_num(源码 parallel_http.cpp),因此增大-thread_num会分摊全局并发,二者需搭配调整; - 连接超时:
connect_timeout_ms被设定为timeout_ms / 2(源码 parallel_http.cpp),即默认 1000ms 超时时,建连超时为 500ms; - 重试语义:
max_retry=3表示在首次请求之外最多再重试 3 次,配合 ChannelOptions 生效(源码 parallel_http.cpp)。
四、使用场景与实战示例
4.1 基本用法:文件列表与标准输入
方式一:URL 列表文件
# 每行一个 URL,空行与首尾空白会被自动忽略 ./parallel_http -url_file=urls.txturls.txt 示例:
http://10.0.0.1:8000/status http://10.0.0.2:8000/status http://10.0.0.3:8000/status方式二:标准输入管道
cat urls.txt | ./parallel_http源码中,当-url_file为空时fp = stdin(parallel_http.cpp),随后用getline逐行读取,去除末尾换行、trim_spaces()去空白后入队;若读到的 URL 列表为空则直接退出(parallel_http.cpp)。
4.2 输出格式:默认多行模式与单行模式
默认模式(多行):每条结果以####前缀开头,便于 shell 工具按行切分,响应体另起一行输出:
#### http://10.0.0.1:8000/status ...响应体内容... #### http://10.0.0.2:8000/status ...响应体内容...单行模式:加-one_line_mode,输出为URL 响应体的一行形式;若响应体为空(请求失败或空响应)则输出ERROR标记。
./parallel_http -url_file=urls.txt -one_line_mode # 输出形如: # http://10.0.0.1:8000/status {...} # http://10.0.0.2:8000/status ERROR仅主机名模式:加-only_show_host只输出 host(去掉http://前缀、截断到第一个/之前),适合只关心"哪些机器可达、哪些失败"的场景,常与-one_line_mode组合使用:
./parallel_http -url_file=urls.txt -one_line_mode -only_show_host4.3 典型实战:全集群内置信息聚合
结合 brpc 内置服务,可以批量拉取整个集群的状态,再交给 grep/awk 等工具过滤聚合:
# 1. 生成全集群 /vars 地址列表 for ip in $(cat cluster_ips.txt); do echo "http://$ip:8000/vars"; done > urls.txt # 2. 高并发拉取,只关心出错的机器 ./parallel_http -url_file=urls.txt -one_line_mode -only_show_host -concurrency=2000 | grep ERROR # 3. 拉取完整状态,按行分割后过滤关键指标 ./parallel_http -url_file=urls.txt -one_line_mode | grep -E "latency|qps"调优建议:目标机器规模大、单机响应快时,可同时调大-thread_num(如 16~32)与-concurrency(如 5000 以上);若单机响应慢,适当调大-timeout_ms避免批量超时。
五、源码实现原理:bthread + 异步 Channel 的并发模型
parallel_http 的高并行度并非来自多进程,而是 brpc 的协程调度与异步 RPC。其核心结构(tools/parallel_http/parallel_http.cpp)可拆解为四层:
1. 工作线程划分(bthread)主程序按-thread_num创建等量的 bthread(bthread_start_background,见 parallel_http.cpp),每个线程以步长thread_num从 URL 列表取任务(i += FLAGS_thread_num,见 parallel_http.cpp),天然实现任务分片。
2. 并发闸门(原子计数)全局并发通过butil::atomic<int> current_concurrency控制:发送前fetch_add(1),若超过本线程额度则fetch_sub(1)后bthread_usleep(5000)退让等待(parallel_http.cpp)。注意此处等待是协程级睡眠,不会阻塞 worker 线程,这正是能支撑高并发的原因之一。
3. 异步 HTTP 调用(Channel + Closure)每个 URL 新建一个brpc::Channel,以brpc::PROTOCOL_HTTP协议初始化(parallel_http.cpp);随后构造继承自google::protobuf::Closure的OnHttpCallEnd回调,通过channel.CallMethod(nullptr, &cntl, nullptr, nullptr, done)发起异步调用(parallel_http.cpp),请求 URI 由cntl.http_request().uri() = url指定。回调Run()中:加锁把(url, response_attachment)推入输出队列,并fetch_sub(1)释放并发额度,同时std::unique_ptr自销毁(parallel_http.cpp)。
4. 主线程结果汇聚主线程循环轮询各线程的output_queue,swap取出结果并打印,直到打印数量等于 URL 总数(nprinted != url_list.size(),见 parallel_http.cpp);结束后依次bthread_join并等待所有在途并发归零(parallel_http.cpp)。
从源码结构可以推断,parallel_http 把"并发控制、异步回调、结果汇聚"三段逻辑解耦,任何一段都不依赖阻塞式同步 I/O,因此并行度上限远高于多进程 curl 方案;其单线程并发额度 + 全局原子计数的设计,也让超大并发下不会对目标集群造成瞬时冲击。
六、延伸阅读
- 内置服务清单与访问方式:docs/cn/builtin_service.md(/status、/vars、/connections、/flags、/rpcz 等)
- 单机 HTTP 压测工具 benchmark_http:docs/cn/benchmark_http.md
- RPC 压测/回放工具 rpc_press 与 rpc_replay 的使用说明见 README_cn.md 工具分类
- 编译环境搭建与依赖安装:docs/cn/getting_started.md
【免费下载链接】brpcbrpc 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/GitHub_Trending/brpc/brpc
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考