文件接口至今仍是最优解的原因
一句话总结
文件集成之所以仍然存在,是因为它适合大批量、边界清晰、容易重处理;代价则是必须亲自处理位置即含义的定长格式,以及文件尚未写完就被取走的问题。
为什么现在还用文件
已经有 REST 和消息队列,为什么还要通过文件交换?理由很明确。
- 适合大批量。 一百万条逐笔调用可能要数小时,一个文件只需几分钟。
- 边界清晰。 “8 月 1 日销售文件”对业务人员来说是自然的工作单位,记录数和金额合计也容易准确对账。
- 容易重处理。 重新放入文件即可,比消息队列重放更直观。
- 对方只支持文件。 运行 20 年的系统、外部机构、银行 EDI,不会接受“请改成 REST”。
因此,文件集成在 SI 现场并未消失,仍是夜间批处理的重要组成部分。
定长报文——位置就是含义
20260801HONG 0000012500Y
| || || ||
1-8 9-28 29-38 39
일자 고객명(20) 금액(10) 여부(1)
布局定义书中必须写明起始位置、长度、类型、对齐方式和填充字符。
| 项目 | 惯例 |
|---|---|
| 字符字段 | 左对齐,右侧补空格 |
| 数字字段 | 右对齐,左侧补 0 |
| 金额 | 不带小数点,以整数表示,并在定义书中注明位数 |
| 负数 | 在末位叠加符号,或另设符号字段 |
| 日期 | YYYYMMDD,8 位 |
出现韩文时,问题就开始了。 “长度 20”究竟是 20 字节还是 20 个字符,会生成完全不同的文件。EUC-KR 中一个韩文字符占 2 字节,UTF-8 中占 3 字节;而定长格式只要错位一个字节,后面所有字段都会损坏。
因此,在韩国的外部系统集成中,EUC-KR(或 CP949)至今仍然存在。一个韩文字符正好 2 字节,容易计算字段宽度。收到的文件显示乱码时,应先怀疑编码并尝试转换。
iconv -f EUC-KR -t UTF-8 SALES_20260801.dat > SALES_utf8.dat
头记录与尾记录——文件的自校验
设计良好的文件接口会包含头记录和尾记录。
H20260801SALES 0001 ← 헤더: 구분, 일자, 업무, 파일순번
D20260801HONG 0000012500 ← 데이터
D20260801KIM 0000030000
T0000000002000000042500 ← 트레일러: 건수, 금액 합계
尾记录只有一个目的:让文件自行证明是否完整到达。
- 数据记录数是否等于尾记录中的记录数
- 数据金额合计是否等于尾记录中的合计值
文件在传输中被截断、丢失一行或在编码转换中损坏,都会被这项检查发现。不做验证,就可能把只到了一半的文件当成正常文件处理。 最后要到月末结算时,才以“数字对不上”的形式暴露。
尾记录验证必须在处理之前完成。处理中才验证,意味着已有一半数据被写入。
完成标志——文件没写完就被取走的问题
批处理在 FTP 文件上传过程中把它取走,会发生什么?系统会处理半个文件。有尾记录验证时还能发现,没有就会直接入库。
标准约定是使用完成标志文件。
SALES_20260801.dat ← 데이터 (전송 중일 수 있음)
SALES_20260801.dat.ok ← 이 파일이 생겨야 처리 대상
发送方传完数据后,再创建一个空的 .ok 文件;接收方只处理存在 .ok 的数据文件。这种方式简单,却非常有效。
必须写进接口定义书。 如果“标志文件约定”只存在于一方,对方只会上载数据文件,我们的批处理则会永远不处理任何内容,而且不会报错。静默地什么都不做,通常最晚才被发现。
文件名规则也是接口
<업무코드>_<기준일자>_<순번>.<확장자>
SALES_20260801_001.dat
- 文件名必须包含基准日期,才能准确找到需要重处理的文件
- 必须包含序号,才能区分同一天多次到达的文件
- 没有命名规则时,
sales.txt每天都会被覆盖,昨天的文件再也找不到
处理后归档
处理过的文件不要删除,应归档保存。
/data/if/archive/20260801/SALES_20260801_001.dat.gz
- 按日期目录拆分,避免一个目录堆积几十万个文件
- 进行压缩,文本文件通常可减少 80~90%
- 在定义书中注明保留期限,无限保留最终会导致磁盘耗尽事故
需要归档,是为了重处理与争议处理。面对“那天我们明明发送了 12,000 条”的说法,只有保存原始文件才能回答。
对账——文件集成的最后一步
文件处理完并不代表结束,还必须确认双方数字是否一致。
| 对账项目 | 方法 |
|---|---|
| 记录数 | 发送记录数 == 接收成功数 + 错误数 |
| 金额合计 | 发送合计 == 接收合计 |
| 键集合 | 发送键列表 - 接收键列表 = 空集 |
只核对记录数和合计容易产生虚假的安心:少一条记录、另一条重复一次时,记录数仍然相同。 因此要同时检查金额合计;对准确性要求高的接口,还要比较键集合。
对账结果应保存为文件,出现不一致时还要自动通知负责人。依赖人工每天打开查看,忙碌时就会跳过,而问题偏偏可能出现在跳过的那一天。
在实际项目中
文件集成事故的类型通常是固定的。
- 处理了半个文件。 对方还在写,我们就取走了。因此要同时使用完成标志(
.ok),并只处理带标志的文件。没有这条规则,“有些天记录数会变少”就会成为无法复现的缺陷。 - 编码发生变化。 一直以 EUC-KR 到达的文件,某天突然变成 UTF-8。定长格式中,韩文字符的字节长度会变化,导致后续所有字段整体错位。页面上的姓名会乱码,金额则会写成完全错误的值。
- 没有检查尾记录。 文件本身已经携带记录数和合计值,如果不核对,即使文件在传输中被截断,也可能照常装载而无人察觉。
三种事故的共同原因,都是缺少读取文件前先验证文件是否可信的流程。因此,文件集成的第一步不是解析,而是验证。