汉高 POS 与商品 Mapping 推送
维护与实施指南
覆盖两条数据链路的完整原理、前后端配置、页面操作、日常巡检、故障排查与变更流程。目标:新人按本指南可以独立接手维护与实施。
开始之前 · 零基础先读
这一节不讲代码。看完你会明白:这个系统为谁解决什么问题、两份数据分别是什么、你每天会在哪几个页面操作。
先讲一个每天都在发生的场景
假设周一有位顾客在京东「汉高家清京东自营旗舰店」买了 2 瓶施华蔻洗发水。接下来会发生这些事:
sku/time/deal_amt 转成 skuId/salesDate/actualSalesAmount,再加上汉高 token。如果没有这个系统
两份数据,用大白话解释
| POS(日销) | Mapping(商品对照) | |
|---|---|---|
| 打个比方 | 每天销售小票的汇总 | 商品身份证对照表 |
| 回答什么问题 | 某天、某店、某个商品,卖了几件、卖了多少钱 | 平台上的这个商品编码,是汉高的哪个产品、哪个条码 |
| 数据形态 | 增量,按天 | 全量快照,每天推一遍 |
| 汉高拿去做什么 | 销售分析、市场看板 | 识别商品、对账、结算 |
| 你不维护会怎样 | 汉高看不到当天销量 | 汉高不知道卖的是哪个货,数据挂错商品 |
spider_data 从数仓取数、清洗 → 推送汉高。我们不是数据的生产者,只是数仓的使用方。
先记住这 13 个词
| 词 | 大白话 | 在本系统里指什么 |
|---|---|---|
| 爬虫 | 从各电商平台抓取订单/退款/商品原始数据的程序 | 抓取结果存入数仓,供 spider_data 查询 |
| 数仓 / 宽表 | 存放爬虫原始数据、按维度整理后供下游取数 | src_tmcs_*、src_ppzh_*、src_vph_* |
| SKU / 平台编码 | 平台给每个商品规格编的号 | 京东 sku、猫超 sku_id、唯品会 goodsCode |
| 鲲驰码 / 69 码 | 鲲驰码或国家商品条码 | product_code、子表的 subBarCode |
| POS | 每日销售汇总 | 推送到汉高 /sales-daily |
| Mapping | 商品对照关系 | 推送到汉高 /product/mapping |
水位 nextStartTime | 系统记住「上次推到哪一天」 | report_job_task.nextStartTime |
| 模板 | 一段把内部字段翻译成汉高字段的脚本 | mongo data_flow_template |
| 订阅者 | broker 里的「收件人」配置 | broker_subscriber |
| 幂等 | 同一条数据重复推,结果不变 | 汉高按 id 或 shopId+skuId+salesDate 覆盖 |
| 补数 | 把水位拨回某一天重跑 | aiops 改时间 + xxl-job 手动触发 |
| 回流 / 补抓 | 回流:京东次月重推的上月完整数据;补抓:事后补的某天数据 | day_p1(回流)/ day_p2(补抓) |
| 全量 / 增量 | 每次都推全部 / 只推变化的部分 | Mapping 全量;POS 按天增量 |
你每天会碰到的 3 个界面 + 1 个后台
| 界面 | 你会在上面做什么 | 对应章节 |
|---|---|---|
| ffc-web · 商品对照 | 新增/编辑/导入映射,启用/禁用,导出 | 第 6 章 |
| aiops-web · Report任务配置 | 查看任务、改下次执行时间(补数)、改参数 | 第 7 章 |
| xxl-job | 看调度日志、手动触发、确认任务是否执行 | 7.4 / 9.4 |
| mongo / mysql | 查证据:任务配置、推送流水、消息与下游响应 | 9.3 |
本指南的图索引
0读前必看 & 30 分钟上手
如果你今天刚接手,按下面 5 步走一遍,就能把整条链路跑通并定位问题。
0.1 你需要拿到的权限/账号
| 系统 | 用途 | 找谁/在哪 |
|---|---|---|
| aiops-web | 查看/修改 Report 任务配置、改下次执行时间 | 菜单「汉高 → Report任务配置」 |
| ffc-web | 维护商品码对照(mapping) | 菜单「基础数据 → 商品对照」 |
| xxl-job 控制台 | 查看调度日志、手动触发、补数 | 运维/负责人 |
| MongoDB(thirdhub) | 查任务配置、消息、模板、路由 | 负责人提供只读/读写账号 |
| MySQL(fms_fnd) | 查映射台账、推送流水 | 负责人提供只读账号 |
| Nacos | 查看/修改 pipeline、data-flow 配置(汉高 appKey 等) | 运维 |
0.2 30 分钟上手路径
broker_message 找一条 subscriberId=hangao_report-jd_report_order 的记录,看 reqBody、respBody、resultStatus。nextStartTime 改成目标日期,在 xxl-job 手动触发一次,观察 brand_data_push_task 与 broker_message。0.3 一分钟版本(背下来)
report_job_task → spider_data → 逐条 → esb-broker → data-flow 模板 → 汉高 /sales-daily。Mapping:
brand_platform_sku_mapping → 每页 50 条 → esb-broker → data-flow 模板 → 汉高 /product/mapping。判断成功:pipeline 的
task_status=2 只代表 broker 收单;汉高真实结果看 broker_message.resultStatus。
1业务背景
先搞清楚“为什么要推两份数据”,后面的字段和过滤规则才有判断依据。
1.1 客户与场景
汉高(Henkel)是鲲驰代运营的品牌方之一,涉及施华蔻(Schwarzkopf)、丝蕴(Syoss)、资生堂专业美发、汉高家清等品牌,在猫超、京东自营、京东 POP、唯品会等多个渠道销售。汉高侧使用 DME 平台(域名 dmeapi-prod.schwarzkopfclub.com.cn)接收鲲驰推送的数据,用于:
- POS 日销:每天按「店铺 × SKU × 日期」报送销量、销售额、客户数、订单数等,供汉高做终端销售分析;
- 商品 Mapping:把平台侧的商品编码(京东 SKU、猫超 sku_id、唯品会 goodsCode 等)对照到汉高的商品主数据(鲲驰码 / 69 条形码 / 子品项),供汉高识别“卖的是哪个货”。
数据来源:爬虫从各平台抓取原始订单/退款/商品数据并存入数仓;本系统只从数仓取数、清洗、推送,不负责采集。
1.2 两份数据的区别
| 维度 | POS 日销 | 商品 Mapping |
|---|---|---|
| 业务含义 | 某天某店某 SKU 卖了多少 | 平台 SKU 对应哪个鲲驰商品/条码 |
| 数据形态 | 增量、按日期 | 全量快照、无日期 |
| 推送粒度 | 一行一条消息 | 一页(50 条)一条消息 |
| 汉高接口 | POST /sales-daily | POST /product/mapping |
| 失败影响 | 当天销售数据缺失 | 汉高无法识别新商品,销售数据可能挂错商品 |
| 维护入口 | aiops-web Report任务配置 | ffc-web 商品对照 |
period=day_p1,汉高侧标记“回流”)。汉高两份都看,回流用于修正上月。详见 4.5。
1.3 汉高接口与鉴权
| 项 | 说明 |
|---|---|
| 域名 | https://dmeapi-prod.schwarzkopfclub.com.cn(生产);测试环境域名由 data-flow 配置决定 |
| 鉴权 | 请求头 X-Auth-Token,token 由 GET /auth/access-token 获取,有效期 1800 秒,Redis 缓存 expiresIn-5 秒 |
| 签名 | signature = md5(appKey + appSecret + timestamp) |
| 成功判定 | HTTP 200 且响应体 {"code":"0","msg":"success"} |
| 配置位置 | data-flow 的 Nacos 配置:hangao.appKey、hangao.appSecret、hangao.ip |
2系统全景
六个系统各司其职,任何一段出问题都会表现为“汉高没收到”,所以必须能画出这张图。
2.1 系统职责
| 系统/服务 | 仓库 | 职责 | 关键类 |
|---|---|---|---|
| mall-pipeline-provider | D:\java-project\pipeline | 定时取数、逐条/分页推送、写推送流水、回写映射 | CommReportPublishJobHandlerCommSkuMappingPublishJobHandlerBrandDataPushTaskService |
| spider_data | 独立取数服务(不在本地仓库) | 按 table/db_type/日期 查询数仓宽表(爬虫采集后入库),返回分页 JSON | HTTP 接口 /openapi/spider_data |
| esb-broker-provider | D:\java-project\esb-broker | 消息总线:同步收单、落库、异步投递、失败重试 | MessageControllerDeliveryMessageListener |
| data-flow-provider | D:\java-project\data-flow | 用 FreeMarker 模板把内部报文转成汉高报文,并加鉴权头推送 | CommControllerRequestTemplateSupportHangaoTemplateFlow |
| fms-fnd-provider | D:\java-project\fms-fnd | 商品映射台账、推送流水、店铺配置 | BrandPlatformSkuMappingControllerBrandDataPushTaskController |
| ffc-web | D:\java-project\ffc-web | 商品码对照维护页面 | src/views/baseData/goods-comparison.vue |
| aiops-web | D:\java-project\aiops-web | Report 任务配置页面 | src/views/reportJobTask/ |
2.2 POS 日销链路
report_job_task每个店铺/口径一条配置,_id = jobName,nextStartTime 决定取哪一天/openapi/spider_data?table=...&db_type=...&日期字段=...,返回 {status:200, count, results}brand_data_push_task,再 POST esb-broker,再回写成功/失败targetService-targetMethod 找订阅者,落 broker_message,异步 POST/sales-daily,返回 code=0 视为成功2.3 商品 Mapping 链路
report_job_task固定一条 MappingReportToHangao,nextStartTime 只是运行计数,不参与取数searchMapping全量分页,不过滤 status,默认按 updateTime desc, status desc, id descproductCode 为空的记录直接丢弃;每页组装成 {size, data:[...]}hangao_product-product_mappingffc-hangao_product_mapping → POST 汉高/product/mapping,按 id/skuId 做 upsertjobName=MappingReportToHangao 就知道是 Mapping,其余基本都是 POS。
3核心数据模型
这一章是维护的地基。改配置、查问题、写 SQL,都围绕这些表和集合。
3.1 mongo report_job_task(任务配置,最重要)
集合:thirdhub.report_job_task,_id 就是 jobName。共约 30 条配置。
| 字段 | 必填 | 作用 | 示例/注意 |
|---|---|---|---|
_id | 是 | 任务唯一标识,也是 xxl-job 参数里的 jobName | Jd108ReportToHangao |
jobInfo | 是 | 任务描述,会写入推送流水的 job_info | 汉高家清京东自营旗舰店==>hangao |
nextStartTime | 是 | 水位:取数用的业务日期,执行一次后 += intervalMinutes | 2026-10-16 16:00:00;只有日期部分有用 |
reportPath | POS 必填 | 上游取数地址 | http://10.0.1.216:9008/openapi/spider_data |
targetPath | 是 | esb-broker 投递地址(含 targetService/targetMethod) | 见 3.2 |
intervalMinutes | 是 | 每次执行水位前进多少分钟 | POS 固定 1440(1 天) |
compensationMinutes | 否 | 取数日期相对水位的补偿分钟数 | 现有配置均为 0 |
retryCount / retrySecond | 否 | 上游 HTTP 重试次数/间隔秒 | 3 / 10 |
pageSize | 是 | 上游每页条数 | 统一 50 |
pageSleep | 否 | 页间休眠毫秒 | 300 |
param | 是 | 上游静态查询参数(table/db_type/fields/店铺/品牌/period 等) | 见 4.4 |
timeFieldList | POS 必填 | 上游日期字段名列表,每个字段都塞同一个日期值 | 京东 ["time","start_date"];猫超 ["date"] |
timePattern | POS 必填 | 日期格式 | yyyy-MM-dd 或 yyyyMMdd |
successField / successValue | 是 | 上游成功标识 | status / 200 |
countField | POS 必填 | 上游总条数字段 | count |
dataListField | POS 必填 | 上游数据列表字段 | results |
version | 是 | Spring Data 乐观锁版本 | 新增写 0 |
timeFieldList 为 null,basicQuery() 会直接 NPE;Mapping 任务如果 nextStartTime 为 null,收尾 plusMinutes() 也会 NPE。手工插入配置时这两项必须给值。
3.2 esb-broker 路由配置
| 集合 | 作用 | 汉高相关文档 |
|---|---|---|
broker_subscriber | 订阅者:目标地址、绑定、成功码、重试开关 | hangao_report-tm_report_orderhangao_report-jd_report_orderhangao_report-wph_report_orderhangao_report-jd_pop_report_orderhangao_product-product_mapping |
broker_binding | RabbitMQ 绑定 | broker_topic@broker.basic@basic(POS)broker_topic@broker.basic@basic(Mapping 同) |
broker_queue | 队列定义 | broker.basic |
broker_listener | 监听器定义 | broker.basic,type=DELIVERY |
一条 POS 配置的 targetPath 样例:
http://isb-gateway.ikunchi.com/esb-broker-provider/message/send
?sourceService=report
&sourceMethod=jd-order
&targetService=hangao_report
&targetMethod=jd_report_order
Mapping 的 targetPath:
http://isb-gateway.ikunchi.com/esb-broker-provider/message/send
?sourceService=pipeline
&sourceMethod=mapping_publish
&targetService=hangao_product
&targetMethod=product_mapping
3.3 esb-broker 消息与日志
| 集合 | 关键字段 | 用途 |
|---|---|---|
broker_message | _id(消息ID)、subscriberId、targetUrl、reqBody、postBody、respBody、messageStatus、resultStatus、retryCount | 每条推送的完整记录,判断汉高是否成功看这里 |
broker_logging | messageId、reqTime、respTime、respCode、respBody、spend、exception | 每次 HTTP 调用的明细(含重试) |
状态字典:
messageStatus:PENDING(0)待投递 →SENDING(3)投递中 →ENDING(2)已结束。ENDING 不代表成功。resultStatus:OK(0)成功、ERROR(1)业务码不对、FAILURE(2)网络/超时等系统失败。
3.4 data-flow 模板配置
| 集合 | 作用 | 关键字段 |
|---|---|---|
data_flow_api | URL 路径 → 模板 ID | _id=路径、templateId |
data_flow_template | 模板内容与目标地址 | targetHost、targetPath、serviceId=hangao、template、expectField、expectValue、valid |
| 路径 | 模板 ID | 汉高接口 |
|---|---|---|
/message/template/receive/report/tm/hangao/order | tm_report-hangao_order | /sales-daily |
/message/template/receive/report/jd/hangao/order | jd_report-hangao_order | /sales-daily |
/message/template/receive/wph/hangao/report | wph_report-hangao_report | /sales-daily |
/message/template/receive/report/jdpop/hangao/order | jd_pop_report-hangao_order | /sales-daily |
/message/template/receive/ffc/hangao/productMapping | ffc-hangao_product_mapping | /product/mapping |
3.5 fms_fnd 业务表
| 表 | 作用 | 规模(参考) |
|---|---|---|
brand_platform_sku_mapping | 商品映射台账(核心) | 约 5,000 行 |
brand_data_push_task | 推送流水(POS 每条一行,Mapping 每页一行) | 约 229 万行 |
shop_config | 店铺名称 ↔ shopId(mapping 自动同步依赖) | 少量 |
brand_platform_sku_mapping 关键字段
| 字段 | 含义 | 注意 |
|---|---|---|
id | 主键 | 推送给汉高作为 id |
shop_id | 店铺 ID | 101/102/.../10231339 |
shop_name | 店铺名称 | 展示用,需与 shop_config 对应 |
platform_code | 平台商品编码 | 与 shop_id 组成业务唯一键 |
product_code | 鲲驰码/69 码 | 为空则不会推送汉高 |
product_name | 平台商品名称 | 截断 128 字符 |
sub_sku_mapping | 子品项 JSON | [{subSkuName,subBarCode,quantity,skuTag,shouldAlert}] |
type | 1 单品 / 2 套装 | 推送时转成“单品/套装” |
status | 0 禁用 / 1 启用 | 禁用也会推送,enableStates=0 |
source_type | 1 手工 / 2 系统自动同步 | 自动同步只覆盖京东系 |
version | 乐观锁 | 编辑必传 |
effective_time / expire_time | 生效/失效时间 | 默认 1970 / 9999 |
3.6 上游数仓表
这些表都在数仓里,数据来源是爬虫从各平台抓取的原始订单/退款/商品数据。我们作为使用方,只负责按日期取数、清洗、推送,不负责采集。
| 渠道 | 表 | 库类型 | 日期字段 |
|---|---|---|---|
| 猫超(2023/2025) | src_tmcs_merchandise_message_view | mysql | date(yyyyMMdd) |
| 猫超(老,2021) | src_tmcs1_market_daily_new | mysql | business_date_time |
| 京东自营 | src_ppzh_report_manage_pro | pg | time、start_date |
| 京东 POP | src_sz_product_list | pg | start_date |
| 汉高家清 POP | src_sz_store_sku | pg | start_date |
| 唯品会 | src_vph_mflp_detail | mysql | logDate、start_date |
4POS 推送实现
核心类:mall-pipeline-provider/src/main/java/com/kunchi/mall/pipeline/job/report/CommReportPublishJobHandler.java
4.1 执行流程(逐行对应代码)
- 读配置:
task(param)用{"jobName":"..."}查report_job_task;查不到返回 false。 - 生成批次号:
yyyyMMddHHmmssSSS-8位随机,贯穿本次所有推送流水。 - 拼上游 URL:
startTime = nextStartTime - compensationMinutes,按timePattern格式化,然后给timeFieldList每个字段都塞这个值,再拼param静态参数和limit/offset。 - 取总数:GET 一次,用
successField/successValue(status=200)判断成功,读countField=count。 - 无数据分支:
totalCount=0→ 记告警、建no_data=true的流水、抛异常。异常导致水位不推进,下次重试同一天。 - 逐页取数:读
dataListField=results,先累计 mapping 去重数据,再逐条sendMessage。 - 汇总 mapping:把本批次所有页的
(shopName, sku)去重后批量调 fms-fndaddMapping(每 1000 条一批)。只对含sku字段的行生效(京东系)。 - 推进水位:
nextStartTime += intervalMinutes,写回 mongo。
4.2 日期窗口与分页
nextStartTime 的日期部分,每次只取一天。日志里的“本次执行: xxx - yyy”只是打印,不参与查询。
分页参数固定写死:limit=pageSize(50)、offset=(pageIndex-1)*pageSize。第 1 页先取总数,再循环 1..totalPage。
4.3 单条推送与状态回写
createTask → fms-fnd /brandDataPushTask/v2/create (task_status=0)
markProcessing → /brandDataPushTask/v2/update (task_status=1)
HttpUtil.doPost(esb-broker /message/send)
└─ 响应 data 非空 → markSuccess (task_status=2)
└─ 否则 → markFail (task_status=3)
task_status=2 只代表 esb-broker 收下了消息,不代表汉高收到了。汉高真实结果在 broker_message.resultStatus。排查“汉高说没收到”时,不要只看 brand_data_push_task。
4.4 现有 POS 任务清单
以 mongo 实际配置为准(aiops 页面可查)。下表按渠道分组,帮助新人快速定位。
| 渠道 | jobName | 上游表 | 店铺条件 | period |
|---|---|---|---|---|
| 猫超 | TmSchwarzkopfReportToHangao2023 | src_tmcs_merchandise_message_view | brand_name=Schwarzkopf/施华蔻 | — |
TmSYOSSReportToHangao2023 | 同上 | brand_name=SYOSS/丝蕴 | — | |
TmSchwarzkopfProfessionalReportToHangao2025 | 同上 | brand_name=SCHWARZKOPF%20PROFESSIONAL/施华蔻专业 | — | |
| 京东自营 | Jd102ReportToHangao | src_ppzh_report_manage_pro | 施华蔻专业线京东自营旗舰店 | day |
Jd103ReportToHangao | 施华蔻京东自营旗舰店 | day | ||
Jd104ReportToHangao | 丝蕴京东自营旗舰店 | day | ||
Jd107ReportToHangao | 资生堂专业美发京东自营旗舰店 | day | ||
Jd108ReportToHangao | 汉高家清京东自营旗舰店 | day | ||
| 京东专区 | Jd103ReportToHangao_zhuanqu | 同上 | 美发造型京东自营专区 | day |
| 京东慧采 | Jd103ReportToHangao_huicai | 同上 | username=慧采-施华蔻 | day |
| 京东回流 | Jd102ReportToHangao_huiliu | 同上 | 施华蔻专业线京东自营旗舰店 | day_p1 |
Jd103ReportToHangao_huiliu | 施华蔻京东自营旗舰店 | day_p1 | ||
Jd104ReportToHangao_huiliu | 丝蕴京东自营旗舰店 | day_p1 | ||
Jd107ReportToHangao_huiliu | 资生堂专业美发京东自营官方旗舰店 | day_p1 | ||
Jd108ReportToHangao_huiliu | 汉高家清京东自营旗舰店 | day_p1 | ||
| 京东补抓 | Jd102ReportToHangao_retry | 同上 | 施华蔻专业线京东自营旗舰店 | day_p2 |
Jd103ReportToHangao_retry | 施华蔻京东自营旗舰店 | day_p2 | ||
Jd104ReportToHangao_retry | 丝蕴京东自营旗舰店 | day_p2 | ||
Jd107ReportToHangao_retry | 资生堂专业美发京东自营官方旗舰店 | day_p2 | ||
Jd108ReportToHangao_retry | 汉高家清京东自营旗舰店 | day_p2 | ||
| 京东 POP | Jd10231339ReportToHangao | src_sz_product_list | username=JD-POP-施华蔻_DEV | day |
| 汉高家清 POP | Jd109ReportToHangao | src_sz_store_sku | username=汉高家清旗舰店 | day |
| 唯品会 | Wph105ReportToHangao | src_vph_mflp_detail | brandName=丝蕴Syoss | day |
Wph106ReportToHangao | brandName=施华蔻Schwarzkopf | day | ||
Wph110ReportToHangao | brandName=资生堂专业美发SHISEIDO PROFESSIONAL(URL 编码) | day | ||
| 老猫超(已停/停滞) | TmSchwarzkopfReportToHangaoTmSYOSSReportToHangao | src_tmcs1_market_daily_new | — | — |
*_huiliu 不是每天跑,而是次月集中把上月 1 号到月底逐天重推一遍;日常每天跑的是不带后缀的常规任务(period=day)。
4.5 period 语义与京东回流(day_p1)
| period 值 | 业务含义 | 汉高报文 dataType |
|---|---|---|
day | 常规日销(每天跑) | 常规 |
day_p1 | 京东次月重推的上月完整数据(每月固定动作) | 回流 |
day_p2 | 临时补抓的某天数据 | 常规(模板只认 day_p1 为回流) |
Jd10x_retry 用的是 day_p2,模板里不匹配“回流”,所以推送出去是“常规”。如果业务要求补抓也标回流,需要同时改模板或改用 day_p1。
为什么京东要单独做“回流”
京东的 POS 数据有一个特点:历史数据会回溯变化。同一张订单/同一个 SKU,今天抓到的“10 月 1 日销量”过几天可能被平台修正。比如 10 月 1 日某个品当天看到总共卖了 10,000,到 10 月 5 日再抓同一天,可能已经变成 15,000。所以每天按 by-day 抓到的数据只是“当时的快照”,不是最终值。
和汉高约定:次月 7 号,把上个月 1 号到月底的 by-day 数据完整重抓一遍,数仓里标记为 period=day_p1,再完整推一次给汉高。汉高会同时保留“每天常规”和“次月回流”两份数据,两份都会看;回流用于修正/复核上个月的最终数。
技术上怎么实现
- 配置:mongo
report_job_task里每组京东店铺都有一条_huiliu任务(jobInfo带“(回流)”),param.period=day_p1,其余字段与常规任务一致。 - 取数:还是同一个
CommReportPublishJobHandler,只是把period=day_p1传给 spider_data,数仓返回回流版本的数据。 - 标记:data-flow 的京东模板判断
period == "day_p1",输出"dataType":"回流";否则输出“常规”。 - 节奏:handler 一次只处理一天(
nextStartTime每次 +1 天)。所以“重推一个月”= 把水位拨到上月 1 号,然后连续触发约 28~31 次,每次都推一天。xxl-job 上看到的是一批密集执行,不是一次请求。 - 实测:2026 年 10 月这批,资生堂/汉高家清在 10-08 09:07~09:25 跑完 9 月全月;施华蔻两家在 10-08 13:02~13:52 跑完,最后一天在 10-09 14:21 补上。实际日期以 xxl-job 调度为准。
执行/核对步骤
- 确认目标月份:例如 10 月要推 9 月,水位应设为
2026-09-01 00:00:00。 - 在 xxl-job 找到对应店铺的
*_huiliu任务,连续触发,直到水位走过2026-09-30(约 30 次)。 - 查
brand_data_push_task:job_info带“(回流)”的记录数应约等于“上月天数 × 每天常规条数”。 - 抽查
broker_message:subscriberId=hangao_report-jd_report_order,reqBody里应包含"period":"day_p1",time/start_date覆盖 09-01~09-30;respBody外层 201、内层code=0。 - 如果某天漏了:把水位拨回那一天,单独触发一次;不要重跑整月(会重复推送)。
_huiliu 用 day_p1,模板输出 回流,是每月固定动作;_retry 用 day_p2,模板输出 常规,是临时补抓。两者的业务含义和汉高侧口径不同,不要互相替代。
4.6 新增一个 POS 任务(两种方式)
方式 A:aiops-web 页面(推荐)
- 打开「汉高 → Report任务配置」→ 点「新增任务」。
- 按 7.4 的字段说明填写。注意
任务名称(ID)必须唯一,建议沿用{渠道}{店铺}ReportToHangao命名。 - 保存后到 xxl-job 新增一个调度:Handler=
CommReportPublishJobHandler,参数={"jobName":"你填的ID"},路由策略选「第一个」或「一致性哈希」,阻塞策略选「单机串行」。 - 手动触发一次(建议把
nextStartTime设为目标日期 00:00:00),观察日志与brand_data_push_task。
方式 B:直接插 mongo(批量/脚本)
db.report_job_task.insertOne({
"_id": "Jd110ReportToHangao",
"jobInfo": "xxx店==>hangao",
"nextStartTime": "2026-10-20 00:00:00",
"reportPath": "http://10.0.1.216:9008/openapi/spider_data",
"targetPath": "http://isb-gateway.ikunchi.com/esb-broker-provider/message/send?sourceService=report&sourceMethod=jd-order&targetService=hangao_report&targetMethod=jd_report_order",
"intervalMinutes": 1440,
"compensationMinutes": 0,
"retryCount": 3,
"retrySecond": 10,
"pageSize": 50,
"pageSleep": 300,
"param": {
"table": "src_ppzh_report_manage_pro",
"db_type": "pg",
"fields": "record_load_time,username,start_date,end_date,period,brand,time,pro_name,sku,first_category_name,second_category_name,third_category_name,shop_name,shop_type,pv,uv,avg_visit_num,avg_stay_time,deal_user,deal_rate,deal_num,deal_pro_num,deal_amt,deal_price_avg,to_cart_num,to_cart_rate",
"shop_name": "xxx店",
"period": "day"
},
"timeFieldList": ["time", "start_date"],
"timePattern": "yyyy-MM-dd",
"successField": "status",
"successValue": "200",
"countField": "count",
"dataListField": "results",
"createTime": new Date(),
"updateTime": new Date(),
"version": NumberLong(0)
})
4.7 补数(重跑某一天)
- 在 aiops 页面找到任务,点「改时间」,把
下次执行时间改为要补的日期(页面会强制成YYYY-MM-DD 00:00:00)。 - 到 xxl-job 手动触发一次该任务。
- 观察:
brand_data_push_task新增记录 →broker_message的resultStatus。 - 要补多天就重复 2~3 步;任务每次只前进一天。
shopId+skuId+salesDate 覆盖)。如果不确定,先与业务/汉高确认,避免重复计数。
5Mapping 推送实现
核心类:mall-pipeline-provider/src/main/java/com/kunchi/mall/pipeline/job/report/CommSkuMappingPublishJobHandler.java
5.1 数据从哪来
| 来源 | source_type | 入口 | 覆盖店铺 |
|---|---|---|---|
| 手工维护 | 1 | ffc-web 新增/编辑/Excel 导入 | 全部 |
| POS 自动累积 | 2 | 日报跑完后 addMapping | 仅京东系(102/103/104/107/108/专区) |
CommReportPublishJobHandler.accumulateUniqueMappingData() 只认字段名 sku。猫超是 sku_code/sku_id、唯品会是 goodsCode、京东 POP 是 pro_id,都会被 continue 跳过。所以这些渠道的新 SKU 必须手工导入。
5.2 全量推送流程
- 读
MappingReportToHangao配置(pageSize=50)。 - 调 fms-fnd
POST /brandPlatformSkuMapping/v2/searchMapping,请求体只有pageNo/pageSize(param为空),不传 status,即不过滤状态。 - 默认排序
updateTime desc, status desc, id desc。 - 逐页把 DB 字段转成汉高字段(见 5.3),
productCode为空的记录直接丢弃。 - 每页组装
{"size":N,"data":[...]},调pushOnce投 esb-broker。 - 页间休眠
pageSleep;全部完成后nextStartTime += intervalMinutes(这个值不参与取数)。
5.3 字段转换表
| 汉高字段 | 来源(fms-fnd) | 规则 |
|---|---|---|
id | id | 主键,汉高侧做幂等 |
shopId | shop_id | 原样 |
shopName | shop_name | 原样 |
skuId | platform_code | 原样 |
skuName | product_name | 原样 |
type | type | 2→“套装”,其余→“单品” |
barCode | product_code | 单品单码;套装多码 + 连接;为空不推 |
enableStates | status | 0/1,禁用也推 |
updatedTime / createdTime | update_time / create_time | 字符串 |
effectiveTime / expirationTime | effective_time / expire_time | 默认 1970 / 9999 |
subSkuMapping[] | sub_sku_mapping JSON | subSkuName/subBarCode/quantity/skuTag |
5.4 过滤、版本与幂等
- 空条码过滤:
productCode为空 → 不推送。当前约 36% 的映射因此不会到达汉高(这是设计上的过滤,不是 bug)。 - 空页:整页都被过滤时,data-flow 返回
201 + "无效数据",broker 记OK,监控上看不出来。 - 版本机制:编辑时如果
subSkuMapping有变化,后端会:- 把原记录置为
status=0、expire_time=昨天 23:59:59; - 新增一条
version=0、effective_time=今天 00:00:00、expire_time=9999的记录。
enableStates=0)和新记录都会推给汉高,由汉高按 id 去启用/禁用。 - 把原记录置为
- 自动同步幂等:
addMapping按(shopId, platformCode)判重,任意状态已存在就跳过,不会更新名称。
5.5 新增一个店铺的 Mapping
- 确认
shop_config已有该店铺(shop_id、shop_name、current_shop_name、is_deleted=0)。没有就找 fms-fnd 负责人加。 - 在 ffc-web「商品对照」用 Excel 导入初始映射(见 6.9)。
- 确认汉高模板里已有该
shopId分支(JD 模板是按shop_name/username映射的,新店铺可能要加分支)。 - 跑一次 Mapping 任务,检查
broker_message里shopId是否正确。
6前端操作:ffc-web 商品对照
入口:基础数据 → 商品对照,路由 /goods-comparison,面包屑「基础数据 / 商品码对照维护列表」。对应代码 ffc-web/src/views/baseData/goods-comparison.vue。
6.1 页面结构
| 区域 | 内容 |
|---|---|
| 顶部查询区 | 平台商品编码、店铺名称、条形码、操作人、状态;按钮「查询」「清空」 |
| 操作按钮区 | 新增、下载模板、导入、导出、批量禁用、批量启用、批量删除 |
| 数据表 | 主表 + 可展开的子品项表;每行有「编辑」「禁用/启用」 |
| 分页 | 每页 20 条(默认),可切页大小 |
6.2 查询
输入条件后点「查询」,实际请求:
POST /fms-fnd-provider/brandPlatformSkuMapping/v2/findByQoWithPage
{
"pageNo": 1,
"pageSize": 20,
"platformCode": "100142031852",
"shopName": "汉高家清京东自营旗舰店",
"productCode": "6920177948308",
"operator": "geyongqiang",
"status": 1
}
所有条件都是模糊匹配(Containing)。「清空」会重置表单并重新查询。
shop_config.shop_name 完全一致,否则查不到(模糊匹配也要有连续子串)。
6.3 列表字段含义
| 列 | 含义 | 关注点 |
|---|---|---|
| TP名称 | 代运营方,默认“鲲驰” | 一般不用改 |
| 店铺名称 | 平台店铺 | 需与 shop_config 对应 |
| 平台侧商品编码 | 京东 SKU / 猫超 sku_id / 唯品会 goodsCode | 与店铺组成唯一键 |
| 条形码 | 鲲驰码/69 码,套装为 + 拼接 | 为空则不会推送汉高 |
| 修改版本 | 0=初始版本,1/2...=编辑子表后生成的新版本 | 有多个版本时以 status=1 的为准 |
| 来源系统 | 手动上传 / 系统自动同步 | 自动同步只来自京东日报 |
| 平台商品名称 | 平台标题 | 截断 128 字符 |
| 类型 | 单品 / 套装 | 由子表推断 |
| 状态 | 启用 / 禁用 | 禁用也会推给汉高(enableStates=0) |
| 更新时间 / 操作人 | 最后修改信息 | 操作人可能是拼音账号 |
| 生效时间 / 失效时间 | 默认 1970 / 9999 | 编辑子表后旧记录失效时间为昨天 |
展开行可以看到子品项:商品名称、商品条形码、数量、是否告警、标签。
6.4 新增映射
- 点「新增」,弹窗标题「新增商品码对照」。
- 填写:
- 店铺名称(必填):必须与 shop_config 完全一致;
- 平台侧商品编码(必填):平台 SKU;
- 平台商品名称(必填);
- 条形码:新增时该字段不参与提交,由子表自动推导;
- TP名称默认“鲲驰”,状态默认启用,操作人自动取登录账号(只读)。
- 在子表点「增行」,填写子品项:
- 商品名称、商品条形码、数量;
- 是否告警:默认“是”,用于完整性告警;
- 标签:正装 / 赠品 / 促销品。
- 点「确定」,请求
POST /v2/save。
deriveProductCode():单品取第一个非空 subBarCode;套装按列表顺序用 + 拼接,每个条码重复 quantity 次。例:[111×1, 22×2] → 111+22+22。所以子表的条形码必须填对。
shop_config.shop_name 不一致。“已存在平台商品编码[xxx]的映射记录”:同店铺同平台编码已存在(含禁用),请改用「编辑」。
6.5 编辑映射(版本机制,重点)
- 点行内「编辑」,弹窗回填当前记录与子表。
- 可改:店铺名称、平台侧商品编码、平台商品名称、子表(名称/条码/数量/告警/标签)。主表「条形码」即使改了,也会被子表推导值覆盖。
- 点「确定」,请求
POST /v2/update(提交完整行对象 + 最新子表)。
| 改了什么 | 后端行为 | 结果 |
|---|---|---|
| 子表任意字段或条数变化 | 原记录 status=0、expire_time=昨天 23:59:59;新增一条新版本 | 列表多一条,旧记录禁用/失效,新记录启用 |
| 只改名称/操作人/状态等 | 原地更新(乐观锁 version) | 仍是一条 |
| 改身份字段(店铺/平台编码) | 先校验唯一性,再原地更新 | 冲突则返回 0(不报错但未更新) |
enableStates=0)和新记录(enableStates=1),按 id 区分。不要手工删除旧记录,否则影响历史追溯。
6.6 启用 / 禁用
- 行内「禁用」:
POST /v2/update,{"ids":[id],"status":0}。 - 行内「启用」:
{"ids":[id],"status":1};已失效(expire_time ≤ 现在)的记录不能启用,会被跳过。 - 批量禁用/启用:勾选多行后点顶部按钮,逻辑同上。
禁用只影响 enableStates,不影响是否推送;要停止推送只能删除或让 product_code 为空。
6.7 批量删除
勾选行 → 「批量删除」→ 请求 POST /v2/deleteBatch,物理删除,不可恢复。删除后汉高侧不会自动删除,只会停止后续推送。
6.8 导出
点「导出」,按当前查询条件请求 GET /v2/exportMapping,下载 Excel。导出不受分页限制(后端按 Qo 查询全量)。
shopCode 字段后端 Qo 里没有(Qo 是 shopId),所以它不生效;按店铺筛选用「店铺名称」。
6.9 导入(最常用,必须掌握)
步骤
- 点「下载模板」,得到
商品码对照.xlsx。 - 按模板填写,一次最多传 3 个文件(可多选)。
- 点「导入」,上传后返回形如
导入成功:X 条;重复/跳过:Y 条。 - 刷新列表核对。
模板列(必须与表头一致)
| 列 | 必填 | 规则 |
|---|---|---|
| TP名称 | 否 | 不填默认“鲲驰” |
| 店铺ID | 是 | 101/102/103/104/105/106/107/108/109/110/10231339/765276150 |
| 店铺名称 | 是 | 需能在 shop_config 中找到 |
| 商家产品编码 | 是 | 平台 SKU,与店铺 ID 组成唯一键 |
| 69条形码 | 否 | 单品可填;套装以子条码拼接结果为准 |
| 商家产品名称 | 是 | 截断 128 字符 |
| 启用状态 | 否 | 默认 1 |
| 类型 | 否 | 1=套装,其它=单品(与页面相反,注意) |
| 子品项名称 | 单品可空/套装必填 | |
| 子品项条形码 | 关键是它 | 用于推导 product_code |
| 数量 | 否 | 默认 1;套装拼接时按数量重复 |
| 子品项标签 | 否 | 正装/赠品/促销品 |
| 子品项是否告警 | 否 | 0 否 / 1 是,默认 1 |
导入规则
- 按
(店铺ID, 商家产品编码)分组聚合;同一组多行会合并子品项。 - 已存在(任意状态)的分组整组跳过,不更新。
product_code推导:套装 = 所有子条码按 quantity 重复拼接;单品 = 69 条形码或首个子条码。- 落库
source_type=1、version=0、status取模板值。 - 店铺 ID 不在允许列表 → 整行跳过。
“套装条码不对”:检查子品项数量;拼接会把条码按数量重复。
6.10 页面操作的副作用(务必知道)
| 操作 | 立即影响 | 对汉高的影响 |
|---|---|---|
| 新增/导入 | 台账新增,source_type=1 | 下次全量 Mapping 任务(次日)推送 |
| 编辑子表 | 旧记录禁用+失效,新增新版本 | 次日推送旧(禁用)+新(启用)两条 |
| 禁用 | status=0 | 次日推送 enableStates=0 |
| 删除 | 物理删除 | 汉高侧不会删除,只是不再推送 |
| 清空条形码 | product_code 可能变空 | 次日不再推送该条 |
7前端操作:aiops-web Report任务配置
入口:汉高 → Report任务配置,路由 /reportJobTask。对应代码 aiops-web/src/views/reportJobTask/。
7.1 页面结构
| 区域 | 内容 |
|---|---|
| 查询条件 | 任务名称(精确匹配)、任务描述(模糊搜索) |
| 列表 | 任务名称(ID)、任务描述、下次执行时间、目标推送地址、查询参数、操作 |
| 操作 | 改时间、改参数、删除;顶部「新增任务」 |
接口前缀:/mall-pipeline-provider/mongo/job/report/task,后端是 JobTaskController.java。
7.2 查询
POST /page,请求 {"jobName":"","jobInfo":"","pageNo":1,"pageSize":10}。
jobName:精确匹配(Mongo_id)。jobInfo:模糊匹配(正则,已转义)。- 列表只返回 5 个字段:
jobName、jobInfo、nextStartTime、targetPath、param。
reportPath、pageSize、timeFieldList 等字段,这是后端只 include 了 5 个字段,不是数据缺失。
7.3 列表字段
| 列 | 说明 |
|---|---|
| 任务名称(ID) | Mongo _id,xxl-job 参数要用它 |
| 任务描述 | 推送流水里的 job_info |
| 下次执行时间 | 水位,只显示日期部分 |
| 目标推送地址 | targetPath,鼠标悬停看完整 |
| 查询参数 | param 的键值对 |
7.4 新增任务(逐字段)
点「新增任务」,弹窗分四块:
基础信息
| 字段 | 必填 | 说明 |
|---|---|---|
| 任务名称(ID) | 是 | 唯一,不可重复;建议 {渠道}{店铺}ReportToHangao |
| 任务描述 | 否 | 会写入流水,建议写清「店铺==>hangao」 |
| 下次执行时间 | 否 | 提交时自动补 00:00:00 |
推送配置
| 字段 | 说明 |
|---|---|
| 数据查询路径 | reportPath,spider_data 地址 |
| 目标推送地址 | targetPath,esb-broker 地址,必须带 targetService/targetMethod |
执行参数
| 字段 | 建议值 | 说明 |
|---|---|---|
| 时间间隔(分钟) | 1440 | 每次水位前进 1 天 |
| 补偿时间(分钟) | 0 | 取数日期相对水位偏移 |
| 重试次数 | 3 | 上游 HTTP 重试 |
| 重试间隔(秒) | 10 | |
| 每页大小 | 50 | spider_data 分页 |
| 分页休眠(ms) | 300 | 页间休眠 |
查询与解析
| 字段 | 说明 | 京东示例 |
|---|---|---|
| param(键值对) | 上游静态参数 | table=src_ppzh_report_manage_pro、db_type=pg、fields=...、shop_name=...、period=day |
| 查询时间参数字段列表 | timeFieldList,回车添加多个 | time、start_date |
| 时间格式 | timePattern | yyyy-MM-dd |
| 成功标识字段 / 值 | successField/successValue | status / 200 |
| 数据总条数字段 | countField | count |
| 返回数据列表字段 | dataListField | results |
7.5 改时间(补数最常用)
行内「改时间」→ 选日期 → 确认。请求 POST /updateStartTime,参数 jobName、nextStartTime=YYYY-MM-DD 00:00:00。
00:00:00;改完立即生效,下一次 xxl-job 触发就会用新日期。不要把它当成“下次运行时刻”,它是“取哪一天的数据”。
7.6 改参数(只能改 4 个字段)
行内「改参数」→ 可修改:任务描述、下次执行时间、目标推送地址、查询参数(param)。其余字段保持原值。
请求 POST /updateV2,后端白名单:
jobInfo、nextStartTime、targetPath、param
reportPath、pageSize、timeFieldList、timePattern、countField 等。要改只能直接操作 mongo,或调旧的 /update 接口(会全量覆盖,慎用)。2)
param 清空不会生效:updateV2 会跳过空 Map。要清空 param 必须直接改 mongo。
7.7 删除
行内「删除」→ 二次确认 → POST /delete?jobName=xxx,物理删除,不可恢复。删除后 xxl-job 再触发会报「未配置任务」。
7.8 新增后还要做什么
CommReportPublishJobHandler,参数 {"jobName":"..."},阻塞策略建议「单机串行」brand_data_push_task.job_info 是否出现该任务broker_message 里 resultStatus=OK、respBody.data 内层 code=08后端配置(不走页面)
页面覆盖不到的地方:直接改 mongo、加模板、加路由。改之前先在测试环境验证。
8.1 新增一个汉高店铺(完整清单)
| 步骤 | 位置 | 操作 |
|---|---|---|
| 1 | fms_fnd shop_config | 插入 shop_id、shop_name、current_shop_name、is_deleted=0 |
| 2 | ffc-web 商品对照 | Excel 导入该店铺初始 mapping |
| 3 | mongo data_flow_template | 如果模板里没有该店铺的 shopId 分支,补一个 |
| 4 | aiops-web | 新增 POS 任务(或复用已有任务,若同一店铺多口径则加 _huiliu/_retry) |
| 5 | xxl-job | 新增调度并手动触发验证 |
| 6 | 核对 | broker_message 的 shopId、skuId、salesDate 是否正确 |
8.2 新增一个汉高接口模板
假设新增「退货」推送。需要两件事:
① 新增 API 路径映射
db.data_flow_api.insertOne({
"_id": "/message/template/receive/ffc/hangao/productReturn",
"templateId": "ffc-hangao_product_return",
"info": "汉高退货",
"createTime": new Date(),
"updateTime": new Date(),
"version": 1
})
② 新增模板
db.data_flow_template.insertOne({
"_id": "ffc-hangao_product_return",
"info": "汉高退货",
"targetHost": "https://dmeapi-prod.schwarzkopfclub.com.cn",
"targetPath": "/commodity/return",
"serviceId": "hangao",
"expectField": "code",
"expectValue": "0",
"template": "[{\"refundNum\":\"${requestBody.refundId}\",\"skuId\":\"${requestBody.skuId}\"}]",
"createTime": new Date(),
"updateTime": new Date(),
"version": 0
})
// 注释,唯品会模板就有这个历史问题)。2)
serviceId=hangao 才会走鉴权(HangaoTemplateFlow 加 X-Auth-Token)。3)
expectField/expectValue 用于判断汉高业务码,通常是 code=0。
8.3 新增一个 esb-broker 路由
db.broker_subscriber.insertOne({
"_id": "hangao_product-product_return",
"service": "hangao_product",
"method": "product_return",
"binding": "broker_topic@broker.basic@basic",
"targetHost": "http://data-flow-provider",
"targetPath": "/message/template/receive/ffc/hangao/productReturn",
"subscriberType": "HTTP",
"expectCode": "code",
"expectValue": "201",
"retryWhenError": true,
"retryWhenFailure": true,
"retryTtl": 300000,
"maxRetry": 3,
"description": "汉高退货"
})
绑定关系 broker_topic@broker.basic@basic 已存在(destination=broker.basic,routingKey=basic),不用新建 binding/queue/listener。
broker_subscriber 有 5 分钟 JetCache 缓存;新增后如果立即调用 /message/send 报「没有目标地址」,等 5 分钟或重启/清缓存。
8.4 xxl-job 配置约定
| 任务类型 | JobHandler | 参数 | 建议 |
|---|---|---|---|
| POS 日销 | CommReportPublishJobHandler | {"jobName":"Jd108ReportToHangao"} | 单机串行;失败重试 0(任务自身会因无数据失败并重试) |
| 商品 Mapping | CommSkuMappingPublishJobHandler | {"jobName":"MappingReportToHangao"} | 单机串行;每天 1 次 |
jobName 不要并发触发。两个实例同时跑会同时读写 nextStartTime,导致水位错乱或重复推送。
8.5 配置修改检查清单
- 新增 POS 任务:
_id唯一、timeFieldList非空、pageSize > 0、intervalMinutes > 0、targetPath的 targetMethod 与订阅者一致。 - 京东店铺要成对配置:常规
JdXXXReportToHangao(day)+ 回流JdXXXReportToHangao_huiliu(day_p1),回流任务按月集中触发。 - 新增店铺:
shop_config有记录、模板有 shopId 分支、mapping 已导入。 - 新增平台接口:
data_flow_api→data_flow_template→broker_subscriber三件套齐全。 - 改模板:先用「模板测试」接口
POST /template/test验证输出是合法 JSON。 - 改完必须手动触发一次并查
broker_message。
9日常巡检与排障
这一章是可以照着执行的操作手册。建议每天上午跑一遍 9.1。
9.1 每日巡检(5 分钟)
① 推送流水成功率
SELECT job_info,
COUNT(*) AS total,
SUM(task_status = 2) AS ok,
SUM(task_status = 3) AS fail,
MIN(create_time) AS first_time,
MAX(create_time) AS last_time
FROM fms_fnd.brand_data_push_task
WHERE create_time >= CURDATE() - INTERVAL 1 DAY
GROUP BY job_info
ORDER BY fail DESC, job_info;
关注:fail > 0;某任务 24 小时无记录(可能没调度或一直失败)。
② 水位是否停滞/滞后
db.report_job_task.find({},
{jobInfo:1, nextStartTime:1, updateTime:1})
.sort({updateTime:-1})
关注:nextStartTime 是否落后业务日期 > 2 天;updateTime 是否超过 24 小时没变。
③ 下游失败与汉高业务码
db.broker_message.aggregate([
{$match:{
createTime:{$gte:new Date(Date.now()-24*3600*1000)},
subscriberId:{$in:[
"hangao_report-tm_report_order",
"hangao_report-jd_report_order",
"hangao_report-wph_report_order",
"hangao_report-jd_pop_report_order",
"hangao_product-product_mapping"
]}
}},
{$group:{_id:{sub:"$subscriberId", st:"$resultStatus"}, cnt:{$sum:1}}}
])
关注:ERROR(汉高业务码不对/模板异常)、FAILURE(网络/超时)。
④ Mapping 缺口
SELECT shop_name,
COUNT(*) AS total,
SUM(product_code IS NULL OR product_code = '') AS blank_code
FROM fms_fnd.brand_platform_sku_mapping
GROUP BY shop_name
ORDER BY blank_code DESC;
关注:blank_code 增长(新增 SKU 未补条码,不会推给汉高)。
⑤ Mapping 是否每天跑了
SELECT DATE(create_time) AS d, COUNT(*) AS pages
FROM fms_fnd.brand_data_push_task
WHERE job_info = '全量Mapping==>hangao'
AND create_time >= CURDATE() - INTERVAL 7 DAY
GROUP BY DATE(create_time)
ORDER BY d DESC;
正常每天约 100 页(5,000 条 ÷ 50)。为 0 说明任务没跑或没数据。
⑥ 每月 7 号后:京东回流是否覆盖上月
SELECT job_info, COUNT(*) AS rows_cnt,
MIN(create_time) AS first_time, MAX(create_time) AS last_time
FROM fms_fnd.brand_data_push_task
WHERE job_info LIKE '%回流%'
AND create_time >= DATE_FORMAT(CURDATE(), '%Y-%m-01')
GROUP BY job_info;
记录数应约等于“上月天数 × 每天常规条数”。再抽查 mongo broker_message:reqBody 含 "period":"day_p1",日期覆盖上月 1 号到月底。
9.2 症状 → 排查路径
| 症状 | 先查 | 判断/处理 |
|---|---|---|
| aiops 列表看不到任务 | mongo report_job_task | 配置不存在或被删;按 4.6 新增 |
| 任务执行但 0 条 | xxl-job 日志 + spider_data 返回 | 上游当天无数据;任务会抛“未查询到数据” |
nextStartTime 不动 | xxl-job 执行日志 | 大概率 totalCount=0 抛异常,水位未推进 |
| 汉高说没收到 | broker_message.resultStatus | OK=已送达;ERROR/FAILURE 看 respBody |
| 汉高返回业务错误 | respBody.data(内层 JSON) | 内层 code≠0,看 msg |
| mapping 缺某商品 | ffc-web 查 platform_code | 不存在→新增;存在但条码空→补条码 |
| mapping 有两条 | 列表按 updateTime 排序 | 编辑子表产生的新版本,正常;旧记录 status=0 |
| POS 数量/金额不对 | broker_message.postBody | 对比模板字段映射与上游原值 |
| 重复推送 | nextStartTime 是否回退/重跑 | 补数会重复;确认汉高幂等 |
| 模板转换异常 | respBody + data-flow 日志 | 模板语法/字段为空导致 JSON 非法 |
9.3 全链路追踪(一次推送的完整证据链)
生成批次号 batchNo:{...},拿到批次号brand_data_push_taskWHERE batch_no='...',看 esb_id、task_status、esb_respbroker_message_id = esb_id,看 messageStatus/resultStatus/respBodybroker_loggingmessageId = esb_id,看每次 HTTP 调用的耗时、响应、异常respBody.subMessage 里的 traceId(形如 [prod][时间][traceId])respBody.data 是字符串,解析后看 code/msgdb.broker_message.findOne({_id:"你的-esb-id"})
db.broker_logging.find({messageId:"你的-esb-id"}).sort({reqTime:1})
9.4 补数 / 重推
POS 补数
- aiops 页面「改时间」→ 目标日期。
- xxl-job 手动触发该任务。
- 查
brand_data_push_task与broker_message。 - 多天则重复;每次只补一天。
Mapping 重推
- mapping 是每天全量,通常不需要单独补;改完数据等次日 03:00 即可。
- 急用:xxl-job 手动触发
MappingReportToHangao(不改任何参数)。
京东回流补推(次月)
- 把对应店铺的
*_huiliu任务水位改到目标月 1 号(如2026-09-01 00:00:00)。 - 连续触发,直到水位走过月底;漏哪天就单独把水位拨到那天再触发一次。
- 核对
broker_message的period=day_p1与日期覆盖。
单条消息重推(esb-broker)
POST /esb-broker-provider/message/sendById?id={messageId}
9.5 已知问题与规避(接手必读)
| # | 问题 | 影响 | 规避/建议 |
|---|---|---|---|
| 1 | POS task_status=2 不代表汉高收到 | 误判“已成功” | 以 broker_message.resultStatus 为准 |
| 2 | HttpUtil.doGet(url) 未设置超时 | 上游卡住时 job 线程挂死 | 巡检看任务耗时;后续修复加 timeout |
| 3 | totalCount=0 抛异常且不推进水位 | 任务永久卡在某天 | 查上游是否有数;必要时人工改 nextStartTime |
| 4 | mapping 自动累积只认 sku 字段 | 猫超/唯品会/POP 新 SKU 不进台账 | 这些渠道手工导入 |
| 5 | 约 36% mapping 的 product_code 为空 | 不会推给汉高 | 用 incompleteMapping / 告警补条码 |
| 6 | 唯品会模板含 // 注释行 | 输出非严格 JSON,靠汉高宽容解析 | 改模板时一并清理 |
| 7 | 猫超模板同时输出两套字段 | 重复 key,依赖“后者覆盖” | 改模板时只保留一套 |
| 8 | broker 重试判断内层只看 retryWhenFailure | retryWhenError 可能不生效 | 汉高订阅者两开关都 true,暂不受影响 |
| 9 | broker_message 无 TTL,约 2,500 万条 | 持续增长 | 建议加 TTL 索引(如 90 天) |
| 10 | RetryJob 默认不覆盖 report/pipeline | POS/Mapping 失败无定时兜底 | 需要时在 xxl-job 参数里显式传 sourceServiceList |
| 11 | aiops updateV2 清空 param 不生效 | 无法通过页面清空参数 | 直接改 mongo |
| 12 | Mapping 的 nextStartTime 不参与取数 | 可能跑到未来日期 | 忽略即可,保持非空 |
10变更与发布
改哪里、要不要发版、发布顺序,一张表说清。
10.1 变更类型与发布方式
| 变更内容 | 改哪里 | 是否发版 | 注意 |
|---|---|---|---|
| 新增/修改 POS 任务 | aiops 页面 / mongo | 否 | 同步配 xxl-job |
| 新增/修改 mapping 数据 | ffc-web | 否 | 次日全量生效 |
| 修改汉高模板 | mongo data_flow_template | 否 | 先 /template/test 验证 JSON |
| 新增汉高接口路由 | data_flow_api + broker_subscriber | 否 | 注意 subscriber 缓存 5 分钟 |
| 修改 pipeline 推送逻辑 | pipeline 代码 | 是 | 走正常分支/合并/发布流程 |
| 修改 fms-fnd 映射规则 | fms-fnd 代码 | 是 | 影响面大,需回归 ffc-web 全部操作 |
| 修改前端页面 | ffc-web / aiops-web | 是 | 只影响操作,不影响数据 |
10.2 代码入口索引
| 功能 | 文件 |
|---|---|
| POS 调度 | mall-pipeline-provider/.../job/report/CommReportPublishJobHandler.java |
| Mapping 调度 | mall-pipeline-provider/.../job/report/CommSkuMappingPublishJobHandler.java |
| 推送流水 | mall-pipeline-provider/.../service/BrandDataPushTaskService.java |
| 映射累积 | mall-pipeline-provider/.../service/BrandPlatformSkuMappingService.java |
| 任务配置后台 | mall-pipeline-provider/.../provider/controller/task/JobTaskController.java |
| 映射 Controller | fms-fnd-provider/.../controller/BrandPlatformSkuMappingController.java |
| 映射 Service | fms-fnd-logic/.../service/impl/BrandPlatformSkuMappingServiceImpl.java |
| 模板分发 | data-flow-provider/.../support/RequestTemplateSupport.java |
| 汉高鉴权 | data-flow-provider/.../service/hangao/impl/HangaoServiceImpl.java |
| 汉高推送 | data-flow-provider/.../flow/template/impl/hangao/HangaoTemplateFlow.java |
| ESB 发送入口 | esb-broker-provider/.../provider/controller/MessageController.java |
| ESB 投递 | esb-broker-provider/.../provider/support/DeliveryMessageListener.java |
| 商品对照页 | ffc-web/src/views/baseData/goods-comparison.vue |
| Report 任务页 | aiops-web/src/views/reportJobTask/index.tsx |
10.3 发布顺序建议
- 先发布 fms-fnd(如果改了映射规则/接口)。
- 再发布 pipeline(依赖 fms-fnd 接口)。
- 再发布 data-flow(如果改了模板加载/鉴权逻辑;只改 mongo 模板不用发版)。
- 最后发布前端页面。
11附录
11.1 接口清单
| 系统 | 方法 | 路径 | 用途 |
|---|---|---|---|
| fms-fnd | POST | /brandPlatformSkuMapping/v2/findByQoWithPage | 商品对照页查询 |
| fms-fnd | POST | /brandPlatformSkuMapping/v2/save | 新增映射 |
| fms-fnd | POST | /brandPlatformSkuMapping/v2/update | 编辑/批量状态 |
| fms-fnd | POST | /brandPlatformSkuMapping/v2/deleteBatch | 批量删除 |
| fms-fnd | POST | /brandPlatformSkuMapping/v2/uploadMapping | Excel 导入 |
| fms-fnd | GET | /brandPlatformSkuMapping/v2/exportMapping | 导出 |
| fms-fnd | POST | /brandPlatformSkuMapping/v2/searchMapping | 对外分页查询(Mapping 任务用) |
| fms-fnd | POST | /brandPlatformSkuMapping/v2/addMapping | 系统自动新增(POS 累积) |
| fms-fnd | GET | /brandPlatformSkuMapping/v2/incompleteMapping | 查缺条码映射 |
| fms-fnd | POST | /brandPlatformSkuMapping/v2/sendAlert | 完整性告警 |
| fms-fnd | POST | /brandDataPushTask/v2/create | 建推送流水 |
| fms-fnd | POST | /brandDataPushTask/v2/update | 更新推送流水 |
| pipeline | POST | /mongo/job/report/task/page | 任务分页 |
| pipeline | POST | /mongo/job/report/task/updateStartTime | 改下次执行时间 |
| pipeline | POST | /mongo/job/report/task/updateV2 | 改参数(白名单) |
| pipeline | POST | /mongo/job/report/task/update | 全量覆盖(慎用) |
| pipeline | POST | /mongo/job/report/task/delete | 删除任务 |
| esb-broker | POST | /message/send | 发消息(pipeline 用) |
| esb-broker | POST | /message/sendById | 按消息 ID 重发 |
| esb-broker | GET | /message/findById | 查消息 |
| esb-broker | GET | /logging/findByMessageId | 查调用日志 |
| esb-broker | POST | /retry/handle | 批量重试 |
| data-flow | POST | /message/template/receive/** | 模板转发入口 |
| data-flow | POST | /template/test | 模板测试 |
11.2 表/集合清单
| 存储 | 名称 | 用途 |
|---|---|---|
| Mongo thirdhub | report_job_task | 任务配置与水位 |
| Mongo thirdhub | broker_subscriber | ESB 订阅者 |
| Mongo thirdhub | broker_binding | ESB 绑定 |
| Mongo thirdhub | broker_queue / broker_listener | ESB 队列/监听 |
| Mongo thirdhub | broker_message | 消息与下游结果 |
| Mongo thirdhub | broker_logging | HTTP 调用明细 |
| Mongo thirdhub | data_flow_api / data_flow_template | 模板路由与内容 |
| MySQL fms_fnd | brand_platform_sku_mapping | 映射台账 |
| MySQL fms_fnd | brand_data_push_task | 推送流水 |
| MySQL fms_fnd | shop_config | 店铺配置 |
11.3 枚举字典
| 字段 | 值 | 含义 |
|---|---|---|
brand_data_push_task.task_status | 0 | 未开始 |
| 1 | 处理中 | |
| 2 | 推送成功(broker 受理) | |
| 3 | 推送失败 | |
broker_message.messageStatus | PENDING | 待投递 |
| SENDING | 投递中 | |
| ENDING | 已结束(不代表成功) | |
| RETRYING | 重试中 | |
broker_message.resultStatus | OK | 成功 |
| ERROR | 业务码不符/模板异常 | |
| FAILURE | 网络/超时/连接失败 | |
brand_platform_sku_mapping.type | 1 | 单品 |
| 2 | 套装 | |
brand_platform_sku_mapping.source_type | 1 | 手动上传 |
| 2 | 系统自动同步 | |
status | 0 | 禁用 |
| 1 | 启用 | |
period | day | 常规 |
| day_p1 | 回流 | |
| day_p2 | 补抓(模板按常规) |
11.4 店铺 ID 对照
| shopId | 店铺名称 | 渠道 |
|---|---|---|
| 101 | 汉高施华蔻丝蕴 | 猫超 |
| 102 | 施华蔻专业线京东自营旗舰店 | 京东自营 |
| 103 | 施华蔻京东自营官方旗舰店 / 施华蔻京东自营旗舰店 / 美发造型京东自营专区 | 京东自营 |
| 104 | 丝蕴京东自营旗舰店 | 京东自营 |
| 105 | 唯品会丝蕴 | 唯品会 |
| 106 | 唯品会施华蔻 | 唯品会 |
| 107 | 资生堂专业美发京东自营官方旗舰店 | 京东自营 |
| 108 | 汉高家清京东自营旗舰店 | 京东自营 |
| 109 | 汉高家清旗舰店(POP) | 京东 POP |
| 110 | 唯品会资生堂专业美发 | 唯品会 |
| 10231339 | JD-POP-施华蔻官方旗舰店 | 京东 POP |
| 765276150 | 丝蕴官方旗舰店 | 天猫 |
SHOP_ID_NAME_MAP 里,"765276150 " 的 key 末尾多了一个空格。如果导入时提示店铺不存在,先按这个原因排查。
12FAQ 20 问
1. 为什么 aiops 列表只有 5 个字段?
后端分页接口只 include 了 jobInfo/nextStartTime/targetPath/param(加上 _id),不是数据缺失。要看完整配置只能查 mongo。
2. 为什么“改参数”改不了 pageSize、timeFieldList?
updateV2 只允许改 jobInfo/nextStartTime/targetPath/param。这是为了防误操作。其他字段请直接改 mongo。
3. 为什么“新增任务”没有 reportPath?
新增模式下有「数据查询路径」,编辑模式下隐藏(因为不允许改)。
4. 为什么编辑 mapping 后多了一条记录?
只要子表(subSkuMapping)有变化,后端就会把旧记录禁用+失效,并新增一条新版本记录。这是设计行为,用于保留历史版本。
5. 为什么导入成功但列表查不到?
常见原因:店铺 ID/名称不在允许列表(整行跳过)、同 (店铺ID, 平台编码) 已存在(整组跳过)。看导入返回的“重复/跳过”数量。
6. 为什么禁用了,汉高还在用?
禁用只是把 status=0,下次全量 Mapping 推送会带 enableStates=0,由汉高侧决定是否停用。如果汉高没处理,需要与对方确认。
7. 为什么改了条形码没生效?
检查是否改了子表的「子品项条形码」。product_code 是从子表推导的,直接改主表条形码会被推导值覆盖。
8. 为什么 POS 任务一直卡在同一天?
当天 totalCount=0,任务抛“未查询到数据”异常,水位不推进。确认数仓当天是否有数据;如果是永久空缺,需要人工把 nextStartTime 往后调。
9. 为什么流水显示成功,汉高说没收到?
task_status=2 只代表 esb-broker 受理。查 broker_message.resultStatus 和 respBody;如果 broker 显示 OK 但汉高说没有,拿 respBody.data 里的内层响应与汉高对账。
10. 为什么 mapping 每天全量推?
当前设计就是全量快照,每天约 100 页(5,000 条)。汉高按 id/skuId 做 upsert。好处是不会漏;代价是消息量大。
11. 补数要改哪里?
aiops「改时间」改 nextStartTime,然后 xxl-job 手动触发。一次只补一天,多天重复。
12. 如何新增一个店铺?
按 8.1 的六步:shop_config → 导入 mapping → 模板 shopId 分支 → 新增 POS 任务 → xxl-job → 核对。
13. 如何新增一个平台接口?
按 8.2/8.3:data_flow_api + data_flow_template + broker_subscriber 三件套,然后 pipeline 里配置 targetPath。
14. 如何查看汉高原样返回?
broker_message.respBody 是 data-flow 的返回;其中 data 字段是字符串,里面才是汉高原样响应。
15. 模板改完要发版吗?
不用。模板存在 mongo,改完立即生效(下次请求)。但建议先用 POST /template/test 验证。
16. 操作人为什么是拼音?
新增时取登录账号(可能是拼音);后端保存时会尝试通过 aic-billing 转中文姓名,查不到就保留拼音。
17. 为什么有的 mapping 没有条形码?
子品项条码没填,推导不出 product_code。这类记录不会推给汉高,会进入完整性告警。
18. 为什么同一店铺有两条同名映射?
编辑子表产生的新版本。旧记录 status=0、失效时间为昨天;新记录启用。以启用那条为准。
19. 为什么唯品会/猫超的新 SKU 不自动进 mapping?
自动累积只认字段名 sku,这两个渠道字段是 goodsCode/sku_id。需要手工导入。
20. 出问题找谁?
按链路分段:任务配置/调度找 pipeline 负责人;映射数据找 fms-fnd 负责人;模板/汉高鉴权找 data-flow 负责人;消息投递找 esb-broker 负责人;页面问题找对应前端负责人。
文档结束。建议把本文件放在团队知识库,并在下列场景更新:新增店铺、新增汉高接口、模板变更、xxl-job 调度调整、表结构变更。