| IP 节点 |
路由表里的一个出口:一组 IP + 伪装身份(sni 骗墙 / verify 锚点),hosts 列出它服务哪些域名;连接按 IP 复用,一条连接可服务多个域名 |
| 串发 |
排队逐个试,失败换下一个;大文件域例外——按字节切段给各候选并行跑(分段竞速),慢段让位 |
| 游标 |
每个域名记住"上次谁接通了",下次从它开始试;其余候选按真实拨号回流的 latency 升序排,没拨过的垫底。没有后台定时全量测速 |
| 冷却 |
绕表全灭后 30 秒内快速失败,不反复烧表;TCP 层死亡另有 60/300/1800 秒退避 |
| 边冷却 |
某个 (IP, 路由键) 的实测小黑屋,三档:响应 421 → 4 小时;新拨连接发送超时/断连 → 2 分钟;风控拦截页 → 10 分钟(免疫成功清黑,只能等过期)。只有响应层会写边:TLS 证书校验失败不写边、只前移游标并打日志;TCP 连不上也不写边,走死亡退避。业务状态码 403/404/429 一律不碰边 |
| 直连全灭 |
内容域串发把候选全试完仍失败才交镜像链(死亡退避逐 IP 记账,串发零成本跳过死 IP);不做 host 级熔断——全试完之前不判定「直连没救」,池里的活通道永远先骑 |
| 流式直通 |
大请求体不进内存,边收边泵给上游;响应头一到立即交付客户端,不等请求体泵完。不进镜像链、不进页面缓存 |
| 镜像链 |
每种资源的"复印店优先级名单"。全新安装双字典为空,一个镜像也没有,要自己在工作台填;名单来自 routes.json,可加自部署镜像(支持拼接即可) |
| 分段竞速 |
大文件按字节切段:镜像一家一份;整包(无 Range)请求里直连入列两次,对应主/副两条 h2 通道各领一段;下载器带 Range 时按「在途区间总字节 ÷(镜像数 + 1)」算段大小,大区间先占位、小区间保底一段,不设最小切片尺寸;慢段尾巴让给最快者;仅适用于支持 Range 的域(objects / release-assets) |
| 直连多段(README 大图/视频) |
与镜像链正交的另一条切片路径:只认 raw / user-images / private-user-images / media / camo / gist / avatars 七个内容 CDN,先发 1 字节 Range 探总长和 content-type,≥512KB 且为 image/* 或 video/* 才按约 192KB 切 4~8 段,摊到池内多条伪装 SNI 直连通道上并发拉(gather_channels 申报需求量),按字节边界合成一条 200 流。先直连后镜像:每段挂 5s 界——成功的段一字节不重拉;段失败立即、或 5s 没拉完的部分由 mirrors_small 里的保留键链(图片段走"图片"链、视频段走"视频"链;与小文件链同一套注册表对齐——工作台启用的镜像自动进这两条链,也支持手改)按已交付偏移续传剩余 Range,链全灭记 60s 熔断,救援也失败才整请求退回单流;镜像整段单流续取、不分段,自己从不拨号。URL 查询串与 Cookie / Authorization 原样保留,段请求只换 Range、剥掉会改变段语义的头;github.com / api.github.com 会话域与 /raw/ 302 第一跳不在白名单内。并发三层叠加:同通道多 stream(实测 1MB 单流 73.8s、8 段 45.0s,约 1.6 倍封顶)+ 多通道多窗口 + 5s 镜像兜尾 |
| 206 段边界校验 |
主切片与补发收 206 时都要 Content-Range 起点等于本段 s、终点不越过本段末端;缺头或不符就当段失败走补发,绝不把错段字节拼进合并流。单段 body 超出自己那份字节预算也要报错 |
| 让位 |
慢段的尾巴按「接手划算才抢」的算术切给最快的源,缓冲里的字节一个不丢,交付线零缺口 |
| ECT 时间槽 |
大文件派发打分:手里的字节 ÷ 上一窗(500ms)实收 = 还需几个槽跑完,最少者胜;零历史垫底,有债零收(卡死)立即避开。每面镜像 5 个原子量记账 + 1 个并列轮转计数 |
| 预算 |
一次尝试最多等几秒。完整阈值见下表 |
| 首字节看门狗 |
电话通了但对方 8 秒不吭声 → 判死 |
| gh_defuse |
拦截页化解机制的名字(仍在运行) |
| 连接槽 |
按 IP 记,上限按 host 类别:会话域恒 1 条(风控面不漂移,全忙骑现有连接排队);内容域/其他 3 条——常态 2 条分落两个 IP,全忙才溢出补;失效按连接 id 精确摘除 |
| 溢出通道(临时) |
溢出补的通道是一次性临时工:句柄只归触发那次溢出的调用方,pick/通道清单从此不再外发;驱动在它空闲(在途流归零)后的第一个探活拍单方面掐断出池——用完即焚,最多滞后一个探活拍(≤30s)。常驻通道(建造双腿/DNS 兜底入库的)不受此限 |
| 已有通道口径 |
"这个 IP 有没有通道"全仓只有一个来源:连接池本身(occupied_ips)。没有第二本账,也就没有两账本漂移的竞态 |
| 每连接驱动任务 / ConnDriver |
每条连接自带一个任务:持续 poll conn 让 h2 帧收发活着(协议硬要求,不是保活)、按类探活(内容域极小请求 / 会话域 PING,计时器驱动,只探闲置通道)、连接结束或探活判死按 id 自摘出池;没有补拨 |
| 探活 |
通道持续存在(无批窗),健康由驱动探活保证:内容域/其他闲置超 30s 开 stream 发 GET Range:bytes=0-0(1 字节 Range 是正常 HTTP 请求,PING 帧探不了黑洞),2s 无响应头 = 黑洞 → 当场出池;会话域闲置超 30s 发 PING,PONG 超时判死。内容域/其他闲置(无真实流量)超 10 分钟主动放手,稳态不多养连接;会话域是长期资产不限 |
| 建造锁 |
per-host 建造锁(pool::get_or_build 内部):同 host 取通道未命中只放一个进拨号(雷群去重),等锁者重查池子,等在途建造最多 3s(30ms 步进),超时交兜底 |
| 双通道资格 |
拨号阶段按 host 类别决定开几条腿:内容域主副两条;会话域自建单条;大文件域与 docs/agent 等低频子域单条。内容域两条都顶满时由溢出在同 IP 补一条(上限 3 条/IP) |
| 主副通道 |
拨号阶段的分工:主腿只开新坑(本 host 候选里已有通道的 IP 一律跳过、按游标优先串发),副腿起跑前先查「本 host 候选 ∩ 已有通道」,捡到就用、不拨号,捡不到才跟主腿一样串发;两腿共享「谁试过哪个 IP」,绝不重复试。这只是拨号分工,不限制取用:连好后两条通道都承载并发 |
| 拨号并发 |
无仲裁:两个 host 同时抢拨同一个空 IP 就让它俩都拨,入库时 store_h2 按类别上限处置(会话域去重、内容域并存),输家的握手(300-700ms,连上即关)是接受的代价。独立仲裁器已退役(保护面只有每批省两三条白打握手,撑不起全局协调器,git 历史可寻回) |
| 取用(占用率 × 延迟) |
每条连接记在途流数和服务端 SETTINGS_MAX_CONCURRENT_STREAMS 下发的上限;分数 =(在途 + 1)÷ 上限 × EWMA 延迟,取最小。闲着又快的优先,顶到上限的让给另一条;两条通道都参与打分、都承载并发,没有「差不到 1.5 倍就轮转各吃一半」这回事 |
| 遥测拦截 |
GitHub 前端上报(/_private/browser/*、alive、collector)本地读掉回 204,不发往上游 |
| 伪装通道 / 首包分片 |
池内所有受管域名统一用假 SNI 握手、按锚点验证书,业务路由靠 h2 :authority;v1 为 docs 等 10 子域专设的真名 SNI 腿与 real/donor 标志已退役。但 CONNECT 纯透传由客户端自持 SNI、全灭 DNS 兜底腿也用真名,这两处不是伪装。ClientHello 首包分片仍在跑:透传时把首包拆 23 段(首刀 116 字节随机切点、间隔 20~70ms 随机),总闸是编译期常量 HELLO_SPLIT_ENABLED = true,没有运行时 A/B 开关 |
| SESSION_EPOCH |
页面缓存的会话号:首次文档导航写当前毫秒,之后间隔超过 15 分钟或时钟回拨就 +1 并清空会话级条目。非首页缓存键带 -s{epoch},重启/换会话不会串到旧副本;首页骨架不带会话号,跨会话复用 |
| 可信镜像 |
工作台每个镜像旁的「信任」勾选。带 sig / jwt / x-amz-* 等签名 query 的 URL 默认剥空镜像、只走直连;标记「信任」的镜像例外放行。判断依据是 URL 形状,不是仓库公私 |
| 诊断头 |
响应带 x-gitport-route,取值 cache / 302memo / direct-split / dns / direct / stream / mirror;缓存命中另带 x-gitport-cache: hit |