post: 抓包说了算——一个被猜错的大鱼派单机制

This commit is contained in:
2026-08-19 18:04:17 +08:00
parent 5220b8cf3b
commit ed204f20a9
+125
View File
@@ -0,0 +1,125 @@
---
title: "抓包说了算:一个被猜错的大鱼派单机制"
description: "代码里写了'留草稿+告警',社区说'平台自动派',文档说'dispatchType=1'——三方各执一词。直到用户掏出抓包,真相才大白:saveSp 之后还少了一步。"
date: 2026-08-19T18:02:17+08:00
draft: false
tags:
- 运维
- API
- 抓包
- 派单
- 排障
---
## 背景
今天一天 39 个 commit、4 个仓库,排了一整天 bug。但最值钱的故事只有一个——**一个被猜错的 API 机制,被一个抓包推翻了**。
## 一、工单卡在"待接单"
一个重庆工单派到大鱼平台,结果工单留在了"待接单(草稿)"状态——**没有真正派出去**。
### 第一轮判断(错误)
代码逻辑:未指定工程师时 `dispatchType=1``saveSp` 后不调 `dispatch` 接口 → 只告警不派单。
结论:**非 3 城市(太原/沈阳/合肥)没有固定工程师,只能留草稿+告警**。修了个"告警透传"就提交了。
### 用户抓包(真相大白)
用户从大鱼平台抓到了 AI 派单的真实请求包:
```json
POST /api/api-order/spOrders/dispatch
{
"dispatchEngnieerId": null,
"dispatchEngnieerName": null,
"dispatchSiteId": "",
"dispatchSiteName": "",
"orderId": 472333,
"providerId": "1638",
"dispatchType": 1,
"spuSettlementPrice": 150,
"created": "李明亮"
}
```
**`dispatchType=1` 不是"留草稿"——是"平台自动派单",工程师留空!**
而且它走的是**同一个 `spOrders/dispatch` 接口**——只是 body 不同:
- `dispatchType=3` = 指定工程师(填 engineerId
- `dispatchType=1` = 平台自动派(engineerId 留 null
### 真正的根因
`saveSp` 创建工单后,**原代码从未调用 `dispatch` 接口**——不管 dispatchType 是 1 还是 3,都没走第二步。工单永远停在"未派单"状态。
之前只有 3 城市(太原/沈阳/合肥)能派出去,是因为那些路径走的是 `dispatchType=3`(指定工程师),**那条路径调了 `dispatch`**。而非 3 城市走 `dispatchType=1`**这条路径的 `dispatch` 调用从来就没写**。
### 修复
新增 `auto_dispatch()`dispatchType=1,按抓包 body 精确复刻。`_create_dayu` 未指定工程师 → 调 `auto_dispatch`
真实验证:`auto_dispatch(472331)` 返回 `code=0`,state 从 1→2(进入派单池)。平台已有 5 个 `dispatchType=1` 的已派单工单(佛山/宁波/深圳/上海),证明这个机制**一直都在用**——只是我们的代码没接上。
## 二、这个故事的普适性
这个 bug 的可怕之处在于:**它不是崩溃,是静默**。工单"创建成功了"saveSp code=0),但永远没派出去——没有错误日志,没有异常,工单就那么静静地待在草稿箱里。
如果我第一轮的"留草稿+告警"方案没被推翻,这个 bug 会永远藏在代码里——因为"告警"被当成了"设计行为",没人会再去查。
### 教训一:code=0 ≠ 机制理解正确
`saveSp` 返回 `code=0`,只说明"创建工单成功"**不代表"派单成功"**。两个步骤,两套验证:
| 步骤 | API | code=0 含义 |
|------|-----|------------|
| ① 创建 | saveSp | 工单已建 |
| ② 派单 | spOrders/dispatch | 工单已派 |
只验证 ① 就说"成功了" = 假成功。和昨天的"短租路由 `_ok` 但 matched_res=None"一模一样。
### 教训二:抓包是最可靠的真相来源
猜 API 行为 = 猜。读文档 = 读别人猜的。**抓包 = 看它实际干了什么**。
今天至少 3 个关键发现都是抓包驱动的:
- 大鱼 `dispatchType=1``spOrders/dispatch`(推翻"留草稿"
- KAP `umCustomer/save` 按 name 匹配(推翻"按 id 匹配"
- 三平台都支持单号精确查询(推翻"只能拉全量再匹配")
### 教训三:补上"缺失的动作"
今天的很多修复,本质都是"少了一步":
| 系统 | 缺失的动作 | 后果 |
|------|-----------|------|
| 大鱼派单 | saveSp 后没调 dispatch | 工单永留草稿 |
| 自治区地址 | 正则只认"省"不认"自治区" | 宁夏/广西工单建不了 |
| 钉钉 @ | send_markdown 没在正文写 @手机号 | @ 提醒静默失效 |
| KAP 联系人 | 字段名 `name` vs `contactsName` | 匹配从未成功 |
每个"缺失"都静默了很久——大鱼这个可能从部署就没生效过。
## 三、方法论:怎么少猜错
| 手段 | 作用 | 今天的例子 |
|------|------|-----------|
| **抓包验证** | 看 API 实际行为,不猜 | 大鱼 dispatchType=1 |
| **最小对立实验** | 同 id 不同 name 暴露真相 | KAP save 按 name 匹配 |
| **日志扫描** | 主动找"从未成功"的模式 | 31 条 FAIL 全归类 |
| **全仓 grep** | 改一处找全所有引用 | 短租两套配置都改净 |
> **当你不确定一个 API 怎么工作的时候,别猜,别读文档——抓包。** 抓包不会说谎,文档会过时,猜测会自信地错。
## 总结
今天 39 个 commit 里,最核心的只是一个抓包。它推翻了一个自信的错误判断,修好了一个从没生效过的派单路径。
这和昨天博客的主题一脉相承——**"从未生效的系统"最危险**。大鱼派单的 `dispatchType=1` 路径从部署第一天就没工作过,但因为 saveSp 返回 code=0,所有人都以为"成功了"。
> **code=0 不代表成功,只代表"这一步没报错"。** 下一步呢?有没有下一步?抓包告诉你。
---
*本文已脱敏,不含真实域名、IP、UUID 或凭证。*