前两轮修的是「点了会失败」和「打得开但要等」。这一轮换了问题: 把整条链真的跑一遍,看它到底接不接得上。 结论是——三个模块各自单测都过,但中间是断的:报价器收了国别却不用、收了预算也不传、 建单时从进程环境变量取归因(WSGI 下永远是空)。这些 bug 之所以活了这么久, 是因为询盘表一直是 0 条,没有任何东西能证明这条链能用。
同时挖出一个 25,667 次的漏洞:全站主按钮「¥19.9 试试看」指向一个不存在的商品。
此前 dh_ask=0 / dh_quote=0。表是空的,意味着「询盘链路正常」只是一句猜测——
没有任何一次真实提交能证明它。本轮写了一个探针,用真实数据走完全程,每一步都读出数据库里的真实行来断言,
跑完精确清理并校验回到基线(台账仍是 1 笔 ¥980.01)。
| 环节 | 断言 | 实测 |
|---|---|---|
| 归因落地 | 带 ?r=mx-s2-de-btmail 访问 | HTTP 200 |
| 自测隔离 | 探针不得污染真人漏斗 | funnel 新增 0 条 |
| 询盘落库 | dh_ask 记录且 ch 正确 | QM 单号 · ch 继承成功 |
| 自动报价 | 询盘即出报价 | 3 条,真实 SKU + 真实价 |
| 国别命中 | cc=DE 必须报德国包 | 德国包 ¥980 在列 |
| 预算不超 | budget=1000-5000 | 最高 ¥1,280(修前会报 ¥127,399) |
| 报价归因 | 3 条报价 ch 全部继承 | 全为 mx-s2-de-btmail |
| 下单 | 订单落库且 ch 正确 | ¥980 · ch 正确 |
| 合约 | 合约 ch 必须等于订单 ch | 两者一致(修前是 direct) |
| 台账 | mark_paid 入账 | 金额/ch/txn 正确 |
| 开票 | 付款即自动开票 | INV 单号 · issued |
| 归档 | 一单一档 + 文件落盘 | 文件 exists=True |
| 幂等 | 重复确认不得重复入账 | 台账仍 1 行 |
| 清理 | 删净探针并回到基线 | 7 张表差异为无,金额未变 |
_quote_pick(item, ask_text, sku_hint, cc, limit) 签名里有 cc,
但整个函数体 877 字节里,cc 只在签名出现过 1 次。后果是可验证的:
| 询盘国别 | 修复前实际报出的货 | 货架上真实存在的同国包 |
|---|---|---|
| 德国 DE | 澳大利亚法人主体包 ¥199 | 德国包 dpk-de · 258,127 行 · ¥980 |
客户填「德国」,报价单推澳洲数据——对方一眼就能看出系统不懂他,直接丢单。 修复后 8 国全部命中本国包,并加了国别硬闸:名称明确指向别国的包,不给这个客户报。
表单有 budget,_ask_post 读了、存了、也传给了 _ask_quote(bud),
但 _ask_quote 调 _quote_pick 时压根没传,而 _quote_pick 也没有这个参数。实测差异:
| 场景 | 修复前 | 修复后 |
|---|---|---|
| DE · 预算 1000-5000 | 可报出 ¥127,399 | ¥19.9 入口 + 德国包 ¥980 + 全球名录 ¥1,280 |
| FR · 预算 5000 | 无中间档,直接跳高价 | gleif tier ¥7,470 + 全球匹配 ¥5,000 |
| CN · 预算 500 | 可能推 ¥128,000 全域包 | 中国包 ¥480 + 展位 ¥500 |
同时把报价单排成「1 件入口款 + 真货」:此前两条 ¥1 引流样本会把名额占满,客户看不到任何可买的正价商品。
这条最隐蔽。订单的 ch 最终是对的,因为 /buy 建单后有一句
UPDATE dh_order SET ch=? 兜底。但合约是在建单函数内部生成的,那时用的还是错值。
根因:create_order 里写的是 _ch_ref(os.environ)。
waitress 为每个请求现造一个 environ dict,不回写 os.environ——
所以 os.environ['QUERY_STRING'] 恒为进程启动时的空值,永远落成 direct。
这条只在 CLI 里偶然能对,在 web 上必错。
联动审计扫出 /buy/ 链接里有 2,404 个指向不在货架的 SKU。
按出现次数排序,第一名不是零头:
| SKU | 页面出现次数 | 货架状态 | 点击后果 |
|---|---|---|---|
DS-TRIAL-19.9 | 25,667 次 | 不存在 | 「未找到该资源」→ 直接流失 |
这是全站几乎每个页面的主按钮:「…条真实数据样例:招标/欧盟出口商/碳报价/采购需求,先花 19.9 元验真伪」。 文案写得很清楚,货从来没上过架。
从 4 个真实源各取 50 条,生成 DS-TRIAL-19.9.csv:
| 源 | 取数 | 字段 |
|---|---|---|
| 欧盟 TED 招标 | 50 条最新公告 | 采购方 / 国别 / CPV / 金额 / 截止日 / 原文链接 |
| 欧盟出口商名录 | 50 家 | 公司 / 行业 / 官网(剔除电话与邮箱) |
| 全国碳市场 CEA | 50 个交易日 | 开高低收 / 成交量 |
| 全球撮合供需对 | 50 对(S/A 级) | 需求方 / 供应方 / 配对依据 / 截止日 |
统一 10 列,每行带 url 可自行回源核验。只取真实字段,不合成、不补空;
落盘前跑了 PII 扫描(邮箱 + 11 位手机号),命中 0 行才允许发布。
/dl/<单号>?t=<token>
返回 67,294 字节,正是那份 CSV。卖得出货,也拿得到货。补掉最大的那个之后,还剩 1,262 个 SKU 被页面引用但不在货架(历史下架的数据包 PK-*、
入口款 DS-ECOPASS-9.9、模板残留 DS-EVBUYERS-498…)。
它们此前一律返回一个白页:「未找到该资源 · 请回货架重新选择」。
逐个补货不现实,也不该——有些确实是下架了。改的是兜底逻辑:
buy_miss 事件(同 SKU 每小时一次,防刷)——客户想买什么但没有,就是补货优先级PAY202609… 看起来是死链,实际是合法的
/payout/buy/<单号> 分账路由,是我的正则没排除;② 死链「种类数」会掩盖真实影响——
2,404 种里有一个占 25,667 次,按种类排根本看不出来。要用出现次数排,不是用种类数排。用户要的是「所有功能、引擎、部署联动一致」。这句话要能验收,就得变成可数的边。 本轮建了审计器,量六条边:
| 边 | 含义 | 实测 | 结论 |
|---|---|---|---|
| E1 SKU→交付物 | 买了能不能拿到东西 | 484 / 484 齐备 | 静态交付全通 |
| E2 库→全量包 | vault 里的库有没有全量包 | 126 / 126 | 全部齐备 |
| E3 引擎→路由 | 引擎是否真被进程挂载 | 57 / 78 | 21 个未被引用 |
| E4 采集器→调度 | 采集脚本是否真被 cron/systemd 调用 | 15 / 30 | 15 个未纳管 |
| E5 SKU→页面入口 | 货架上的货页面上有没有入口 | 1,505 / 1,657 | 91% 有入口 |
| E6 底本→多 SKU | 一份数据供几件商品(倍增) | 1.19 | 复用偏低 |
985 个底本,只有 98 个被 2 件以上 SKU 共用。一份数据平均只卖 1.19 次——
所谓「倍增」目前基本没有发生。这不是 bug,是产品结构问题:
大部分 SKU 各配各的文件,没有形成「一个底本 → 快照 / 订阅 / 授权 / 行业切片」的梯次。
真正跑通的只有 GLEIF 那条线(vault_dpk-all 一底三档)。
审计器第一版报了三个大红灯,查到底全是我自己判错:
| 第一版结论 | 真相 | 根因 |
|---|---|---|
| 184 件 SKU 交付物缺失 | 实际 0 件缺失 | 自造候选路径,漏了 private/leads 合规私库 |
| 24 个引擎未挂载 | deal_hub/world_lib 是 systemd 主入口 | 只查 import,没查 ExecStart |
| 16 个采集器未调度 | crawler_compliance 由 systemd 常驻 | 只查 crontab,没查 systemd |
| 22 个 SKU 的 ref 是占位符 | 全是 svc/bundle/sub,语义合理 | 没按 kind 分口径 |
deal_hub._resolve_deliver(),挂载状态查 systemd ExecStart。
自造一套=凭空造红灯,最后只会逼人去调阈值。在服务器回环跑(外网跨境单页 30 秒,回环 60 秒跑完全站):
| 指标 | 结果 | 说明 |
|---|---|---|
| URL 总数 | 900 | 从首页起爬,深度与链接全展开 |
| 正常 200 | 595 | 无 5xx |
| 连接异常 | 0 | 无超时、无 TLS 失败 |
| 死链 | 1 | /world/lead —— 留资端点只收 POST,GET 404 属设计 |
| 429 | 304 | 自测在打自家 limit_req,反证限流在工作 |
| 慢页(≥1.0s) | 3 个 | 最慢 1.23s(service 页渲染真实数据) |
对比上一轮:慢页维持 3 个、最慢从 1.70s 降到 1.23s;无新增异常。
static/datastore/ 在 nginx 层 403 直连禁止,交付只走 /dl/ 与 /datastore/deliver(root 进程)。| 门禁 | 守什么 | 本轮实测 |
|---|---|---|
| G89 报价国别与预算 | 8 国报价必须命中本国包且不超预算 | 8 国全中,超预算不加推 |
| G90 交付可达 | file 类 SKU 全部可解析到实际文件 | 484 件全通过 |
| G91 下架承接 | 无货 SKU 必须有同类推荐,不许裸「未找到」 | 3 个探针均承接 |
| G92 底本 ref 卫生 | file 类不得用占位符当路径 | 985 底本 / 复用 98 / 1.19 |
连同此前 88 条,全量 92/92 全绿(首轮 run_id=108,167 秒;报告上传后复验 run_id=109,161.7 秒,仍 92/92)。
空闲态响应复测(门禁跑完、机器无其他负载,回环 + 浏览器 UA + gzip,每页两次取最快):/deal-desk/ 0.075s|/world/ 0.023s|/world/data 0.061s|/deal-desk/market 0.007s,全部远低于 G84 的 3.0s 线。门禁并发期间 /deal-desk/ 曾测出 9.48s,现已证实是 2 核被门禁占满所致,不是页面本身慢——这也是「性能门禁每页两次取最快」的由来。
外网实测(本机→HK,含 TLS,Accept-Encoding: gzip):/deal-desk/ 200、TTFB 1.2–2.3s、总耗时 9.2–11.7s,响应体 113,992 字节 → 折合约 12 KB/s。TTFB 与总耗时差 8–10s 全在传输段,瓶颈是跨境出口带宽,不是服务端(回环同页 0.075s)。唯一可量化的下一步是砍首屏字节(首屏外分段延迟渲染),把 113KB 压到 45KB 量级;继续优化后端无用。
| 事项 | 状态 | 为什么不能靠改代码解决 |
|---|---|---|
| 询盘 0 条 | 链路已验证可用 | 不是功能问题,是没人来问。现在可以确定:客户一提交,系统会正确出单、出价、出合约 |
| 一底本只供 1.19 件 | 未动 | 要做产品结构化(底本→梯次),不是修 bug |
| 21 个引擎未被引用 | 未动 | 需逐个确认是「该挂没挂」还是「已废弃」。盲目挂载会引入未测入口 |
| 15 个采集脚本未纳管 | 未动 | 不能为了数字好看就加 cron:2 核机器,且未确认会否写脏数据 |
| 1,262 个断链 | 已承接 | 不再流失,但对应商品仍缺货;buy_miss 会累积出补货优先级 |