💎 远程 Mac 或自托管 Runner 跑 Ruby 流水线时,Bundler 会并行拉取 rubygems 与 Git 源 gem,跨境下易出现连接池打满、镜像与 lock 校验不一致、Git 鉴权断裂。下文给可执行对照表、环境变量与命令、Gemfile.lock 验收清单与失败重试阈值。延伸阅读 PHP Composer 矩阵、Git/npm 镜像优化、GHA 自托管 Runner;首页、博客列表、购买、帮助免登录可阅。
场景与瓶颈
1)双通道争用:同一 bundle install 既走 HTTPS 宝石库又 git clone,跨境 RTT 放大,易超时与半开连接堆积。
2)锁文件刚性:Gemfile.lock 含版本与校验信息,镜像滞后或篡改路径会触发安装失败;CI 上误跑更新会漂移。
3)缓存键过粗:忽略 lock 哈希会把旧 bundle 目录复用到新依赖,表现为诡异的解析错误。
| 决策维度 | 优先选型 | 谨慎场景 |
|---|---|---|
| 并行度 | BUNDLE_JOBS 2~4 起步,稳定后再升 | 弱网顶满默认线程 |
| 源策略 | 企业聚合镜像优先,官方兜底 | 仅单一境外源且无重试 |
| 可复现 | 锁文件提交 + frozen 安装 | 共享机随意 update |
并行与连接池参数
BUNDLE_JOBS 控制安装阶段并行编译与获取;BUNDLE_RETRY 为网络类失败的内置重试次数。外层建议再包二四八秒退避,最多三次,避免与限流正面对冲。
| 变量 / 参数 | 推荐起点 | 说明 |
|---|---|---|
| BUNDLE_JOBS | 4(共享出口 2~3) | 与 CPU 核数解耦,先看网络与文件句柄 |
| BUNDLE_RETRY | 3 | 瞬时错误可恢复;持续失败应降并发或换源 |
| 壳层退避 | sleep 2 / 4 / 8 | 三次为阈值;仍失败转人工看日志与 HTTP 状态 |
export BUNDLE_JOBS=4 BUNDLE_RETRY=3
bundle install --jobs 4 --retry 3 --path vendor/bundle
跨境镜像与 Git 源策略
gems 走镜像可显著降低跨境 RTT;Git 源需单独配置主机级凭证,避免交互提示卡死流水线。
| 场景 | 可执行配置 |
|---|---|
| rubygems 镜像 | bundle config set --global mirror.https://rubygems.org https://gems.ruby-china.com |
| 清华源(示例) | bundle config set --global mirror.https://rubygems.org https://mirrors.tuna.tsinghua.edu.cn/rubygems/ |
| GitHub HTTPS | export BUNDLE_GITHUB__COM=username:$GITHUB_TOKEN 并 export GIT_TERMINAL_PROMPT=0 |
私服或 GitLab 可改用 bundle config set --local gitlab.corp.com user:$TOKEN(按 Bundler 文档主机键名);SSH 场景统一 GIT_SSH_COMMAND 指向专用密钥。
lockfile 漂移与缓存键
Gemfile.lock 一致性验收清单
- 锁文件已进主分支,CI 使用
bundle install --deployment或等价 frozen 行为。 - 流水线打印
ruby -v、bundle -v与bundle config,与本地对齐。 vendor/cache:执行bundle package --all提交或作为产物缓存,减少跨境重复拉取。- CI 缓存键包含
Gemfile.lock哈希(及 Ruby 版本 slug),例如bundle-{{ checksum Gemfile.lock }}-3.3。 - 变更依赖后强制冷缓存一次,观察全量安装耗时再收紧并行。
bundle package --all
# 缓存路径示例:vendor/bundle + vendor/cache
五步落地 Runbook
按序执行
- ① 固定 Ruby 与 Bundler 版本(asdf、rbenv 或容器镜像)。
- ② 写入镜像与 Git 凭证环境变量,跑通一次冒烟
bundle check。 - ③ 设定
BUNDLE_JOBS、BUNDLE_RETRY,记录失败率曲线。 - ④ 启用
vendor/cache或远程 gem 缓存目录,配置含 lock 哈希的缓存键。 - ⑤ 将壳层二四八退避写入脚本,超时阈值与告警对接日志或 Slack。
FAQ
Git 源 gem 认证失败?
查 BUNDLE_GITHUB__COM 或 bundle config 主机键是否与 Gemfile git 源一致,并确认 GIT_TERMINAL_PROMPT=0。
校验或与 lock 冲突?
优先换源复现;清空本 Job 的 bundle 缓存路径;避免混用未镜像的直连与旧缓存。
BUNDLE_JOBS 越高越慢?
多为限流与握手;降并发、错峰 Job、配合 BUNDLE_RETRY 与退避。
CI 与本地不一致?
比对 Ruby 次版本、Bundler 主版本与 bundle config;干净目录重装后再评审 lock。