Bazel C++ 构建系列文档(九):远程缓存与分布式构建 Bazel C 构建系列文档九远程缓存与分布式构建1. 远程缓存原理Bazel 的远程缓存是其性能核心特性通过存储构建产物编译输出、测试结果并复用它们来大幅加速构建。1.1 缓存的基本概念命中未命中源代码变更缓存查询直接使用缓存产物本地构建上传产物到缓存继续构建1.2 缓存存储的产物类型产物类型描述缓存级别Action Outputs编译器的输出.o、.a、.so细粒度缓存Test Results测试执行结果测试缓存Analysis Cache构建分析结果分析缓存Build Metadata构建元数据会话级别1.3 缓存策略缓存策略 1. 按内容哈希存储 → 同一内容只存储一次 2. 只存储中间产物 → 源代码不缓存 3. 缓存分层 → 本地磁盘 → 远程缓存 → 重新构建 4. 原子性操作 → 避免部分构建2. 远程缓存配置2.1 基本配置# 配置远程缓存gRPCbazel build //...--remote_cachegrpc://cache.example.com:9092# 配置远程缓存HTTPbazel build //...--remote_cachehttp://cache.example.com:8080# 配置本地磁盘缓存bazel build //...--disk_cache~/.cache/bazel2.2 .bazelrc 配置# .bazelrc # 默认启用远程缓存 build --remote_cachegrpc://cache.example.com:9092 build --remote_timeout60 # 超时时间秒 # 本地缓存配置 build --disk_cache/tmp/bazel_cache build --remote_upload_local_resultstrue # 本地结果上传到远程 # 缓存大小限制 build --max_idle_secs3600 # 缓存保留时间 build --remote_default_exec_propertiesplatformx86_642.3 企业级配置# .bazelrc # 远程执行配置 build --remote_executorgrpc://executor.example.com:9091 build --remote_instance_nameinstance1 build --remote_default_platform_propertiesplatformx86_64,oslinux # 缓存配置 build --remote_cachegrpc://cache.example.com:9092 build --remote_timeout300 build --remote_retries3 # 证书配置 build --remote_cafile/path/to/ca.crt build --remote_cacert_pinsha256...3. 本地磁盘缓存3.1 磁盘缓存结构~/.cache/bazel/ ├── execroot/ # 执行根目录 ├── cache/ # 缓存数据 │ ├── action_cache/ # Action 输出缓存 │ ├── content_cache/ # 文件内容缓存 │ └── test_logs/ # 测试日志 └── tmp/ # 临时文件3.2 配置磁盘缓存# .bazelrc# 设置缓存大小限制build--remote_max_connections20# 最大并发连接build--remote_timeout60# 连接超时# 缓存清理策略build--max_idle_secs86400# 24小时不访问则清理build--experimental_remote_downloader_cache_size100# 100GB# Windows 特定配置build--experimental_windows_symlink_in_runfilesfalse3.3 管理磁盘缓存# 查看缓存大小du-sh~/.cache/bazel/# 清理缓存bazel clean--expunge# 完全清理rm-rf~/.cache/bazel/cache# 手动清理缓存# 设置缓存清理任务# 在 .bashrc 或 crontab 中添加# 每周清理一次*/5 * * * *find~/.cache/bazel/cache-typef-mtime7-delete4. 远程执行远程执行与远程缓存协同工作将计算任务分发到远程执行器。4.1 远程执行配置# 启用远程执行bazel build //...--remote_executorgrpc://executor.example.com:9091# 同时使用缓存和执行bazel build //...\--remote_cachegrpc://cache.example.com:9092\--remote_executorgrpc://executor.example.com:9091# 指定执行平台bazel build //...--platform_targetplatforms//os:linux4.2 工作区配置# WORKSPACE 或 MODULE.bazelload(bazel_tools//tools/build_defs/repo:http.bzl,http_archive)# 注册远程执行器http_archive(namemy_remote_tools,urls[https://example.com/tools.tar.gz],patch_cmds[echo my_executable remote_executor,chmod x remote_executor,],)# BUILD 文件中使用toolchain(nameremote_toolchain,toolchain_typebazel_tools//tools/cpp:toolchain_type,toolchain:remote_toolchain_impl,)4.3 安全配置# .bazelrc # 启用认证 build --remote_timeout60 build --remote_downloader_cafile/path/to/ca.crt build --remote_downloader_cacert_pinsha256... build --remote_executor_cafile/path/to/ca.crt # 令牌认证 build --remote_downloader_headerAuthorization: Bearer token build --remote_executor_headerAuthorization: Bearer token5. 缓存优化策略5.1 缓存命中率优化# 查看缓存命中率bazel build //...--remote_verbose# 分析构建缓存效果bazel analyze-profile--build\--output_htmlcache_analysis.html# 使用 bazel analyze-action-inputsbazel analyze-action-inputs //...action_inputs.log5.2 Action 合并# 合并相似的 Actioncc_library(nameoptimized_lib,srcs[a.cc,b.cc,c.cc],copts[-O2],# 相同编译选项)# 而不是分开编译# cc_library(name a, srcs [a.cc], copts [-O2])# cc_library(name b, srcs [b.cc], copts [-O2])5.3 内容感知的缓存# 使用文件的哈希值而不是文件名cc_library(nameversioned_lib,srcs[lib.cc],copts[-DVERSION_SHA$(cat .git/HEAD)],# 包含版本信息)6. 企业级部署方案6.1 架构图┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ 开发者机器 │ │ 本地 CI/CD │ │ 构建/测试集群 │ │ │ │ │ │ │ │ ├── 本地缓存 │ │ ├── 本地缓存 │ │ ├── 远程缓存 │ │ ├── 远程缓存 │◄──►│ ├── 远程缓存 │◄──►│ ├── 远程执行 │ │ └── 开发工具 │ │ └── CI 代理 │ │ └── 容器运行时 │ │ │ │ │ │ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ ▼ ┌─────────────────┐ │ 代码仓库 │ │ │ │ ├── Git │ │ ├── Monorepo │ │ └── 依赖管理 │ │ │ └─────────────────┘6.2 部署步骤# 1. 部署缓存服务器以 gRPC 为例# 使用 Bazel 官方的 remote execution (RE) 服务器# https://github.com/bazelbuild/remote_execution# 2. 配置客户端cat.bazelrcEOF # 远程缓存 build --remote_cachegrpc://cache.example.com:9092 build --remote_timeout60 # 远程执行 build --remote_executorgrpc://executor.example.com:9091 build --remote_default_platform_propertiesplatformx86_64 # 认证 build --remote_downloader_cafile/etc/bazel/ca.crt build --remote_executor_cafile/etc/bazel/ca.crt EOF# 3. 配置 CI/CD 代理catci/bazel-remote.shEOF #!/bin/bash # CI 代理脚本 export BAZELISK_SKIP_WRAPPERtrue export USE_BAZEL_VERSION7.3.1 exec bazel --bazelrc/etc/bazel/ci.bazelrc $ EOF6.3 监控与报警# 监控脚本Pythonimportrequestsimporttimedefmonitor_cache_health():# 检查缓存服务器状态try:responserequests.get(https://cache.example.com/health,timeout5)ifresponse.status_code!200:alert(Cache server unhealthy)else:statsresponse.json()ifstats[cache_hit_ratio]0.8:alert(Low cache hit ratio)exceptExceptionase:alert(fCache server error:{e})# 定期执行whileTrue:monitor_cache_health()time.sleep(60)7. 故障排查7.1 常见问题问题可能原因解决方案缓存命中率低Action 过于细碎合并相似的 Action缓存缓慢网络带宽不足优化网络或使用本地缓存构建失败远程服务器不可用切换到本地构建测试缓存失效测试用例依赖时间使用固定时间戳7.2 调试命令# 启用详细日志bazel build //...--remote_verbose# 测试缓存连接bazel build //:hello--remote_cachegrpc://cache.example.com:9092# 查看缓存的 Actionbazel querybuildfiles(//...)--outputgraph# 分析构建缓存bazel analyze-profile--build--output_htmlanalysis.html7.3 缓存统计# 缓存使用统计bazel info--disk_cache_usagebazel info--remote_cache_usage# 查看缓存中的 Actionbazel cquerykind(cc_compile, //...)--outputlabel|wc-l8. 性能基准测试8.1 本地 vs 远程构建对比#!/bin/bash# build_benchmark.sh# 确保构建目录干净bazel clean--expunge# 构建时间测试echo 本地构建 timebazel build //...echo 本地缓存构建 timebazel build //...echo 远程缓存构建 timebazel build //...--remote_cachegrpc://cache.example.com:9092echo 远程执行构建 timebazel build //...--remote_executorgrpc://executor.example.com:90918.2 缓存命中测试# 测试不同场景的缓存命中率importsubprocessimportjsondeftest_cache_hit_ratio():# 记录初始状态resultsubprocess.run([bazel,info,disk_cache_usage],capture_outputTrue)initial_cacheint(result.stdout.decode().strip())# 构建并测量subprocess.run([bazel,build,//...],checkTrue)resultsubprocess.run([bazel,info,disk_cache_usage],capture_outputTrue)final_cacheint(result.stdout.decode().strip())cache_growthfinal_cache-initial_cachereturncache_growth# 测试不同配置print(Action-level cache size:,test_cache_hit_ratio())9. 成本优化9.1 缓存压缩# .bazelrc # 启用压缩 build --remote_compressiontrue build --remote_timeout60 # 压缩级别 build --remote_compression_level69.2 智能缓存策略# 自动清理旧缓存importosimporttimedefcleanup_old_cache():cache_diros.path.expanduser(~/.cache/bazel/cache)max_age30*24*60*60# 30天forroot,dirs,filesinos.walk(cache_dir):forfileinfiles:file_pathos.path.join(root,file)iftime.time()-os.path.getmtime(file_path)max_age:os.remove(file_path)print(fRemoved:{file_path})9.3 冷热数据分离存储策略 1. 热数据最近7天→ 存在高速存储 2. 温数据30天→ 存在标准存储 3. 冷数据30天以上→ 存在低成本存储或删除 // .bazelrc 配置 build --remote_cache_cleanup_age2592000 # 30天 build --remote_cache_retention_multiplier1.510. 小结本篇详细介绍了 Bazel 的远程缓存与分布式构建✅ 远程缓存原理与基本概念✅ 本地磁盘缓存配置与管理✅ 远程执行与缓存协同工作✅ 缓存优化策略与技巧✅ 企业级部署方案✅ 故障排查与监控✅ 性能基准测试✅ 成本优化策略