数据同步服务-语音
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

11 KiB

语音数据FTP同步服务

基于淮南 yydc-tb-server 老代码改造的 Spring Boot 服务 用于从FTP服务器读取录音数据,上传至OSS并入库到人大金仓数据库

项目简介

本服务定时从FTP服务器读取通话记录txt文件,下载对应的mp3录音文件,上传到OSS对象存储,并将通话记录保存到人大金仓数据库。每个地市单独部署一份服务

参考老代码(淮南):src/main/java/淮南/MineService.java(已废弃,新代码基于其重写)

技术栈

技术 版本
Spring Boot 2.6.13
MyBatis 2.3.1
数据库 人大金仓 (KingbaseES)
工具库 Apache Commons Net (FTP)
JDK 1.8+

目录结构

dataservice-yy/
├── src/main/java/com/threecloud/dataserviceyy/
│   ├── DataserviceYyApplication.java      # 启动类
│   ├── config/
│   │   ├── DataSourceConfig.java          # 数据源配置
│   │   └── FtpSyncProperties.java         # FTP配置
│   ├── entity/
│   │   └── MidVoiceCallRecord.java        # 通话记录实体
│   ├── mapper/
│   │   └── MidVoiceCallRecordMapper.java  # MyBatis Mapper
│   ├── service/
│   │   └── FtpSyncService.java            # 核心同步服务
│   └── util/
│       ├── FilePathUtil.java              # 路径工具
│       ├── FileUploadUtil.java            # OSS上传工具
│       ├── FtpUtil.java                   # FTP工具
│       └── DateUtil.java                  # 日期工具
├── src/main/resources/
│   ├── application.yml                    # 内部配置
│   ├── logback-spring.xml                 # 日志配置
│   └── mapper/
│       └── MidVoiceCallRecordMapper.xml   # SQL映射
├── config/
│   └── application-external.yml           # 外部配置(部署时修改)
├── sql/
│   └── mid_voice_call_record.sql          # 建表SQL
├── pom.xml                                # Maven配置
└── README.md                              # 本文档

数据流程

┌──────────────┐    1.连接     ┌──────────────┐
│   本服务     │◀───────────▶│  FTP服务器   │
│              │    2.下载txt │  (录音盒)    │
│              │    3.下载mp3 │              │
└──────┬───────┘              └──────────────┘
       │
       │ 4.上传
       ▼
┌──────────────┐
│   OSS存储    │  http://oss地址/voice/合肥/340100/20240101/xxx.mp3
└──────────────┘
       │
       │ 5.入库
       ▼
┌──────────────┐
│  人大金仓     │  mid_voice_call_record 表
└──────────────┘

数据库表

mid_voice_call_record(通话记录表)

CREATE TABLE "mid_voice"."mid_voice_call_record" (
    "id" int8 NOT NULL GENERATED ALWAYS AS IDENTITY,
    "city_code" varchar(20),
    "city_name" varchar(100),
    "call_record_id" varchar(100) NOT NULL,    -- 唯一标识,建议加唯一索引
    "call_tel" varchar(50) NOT NULL,            -- 主叫
    "called_tel" varchar(200) NOT NULL,         -- 被叫
    "call_start_time" timestamp(6) NOT NULL,
    "call_end_time" timestamp(6) NOT NULL,
    "call_duration" int4 NOT NULL,              -- 秒
    "call_direction" varchar(50) NOT NULL,      -- 1呼入/2呼出
    "device_no" varchar(100) NOT NULL,          -- 设备编码(FTP_地市编码)
    "business_scenario" varchar(100),
    "recording_file_name" varchar(200) NOT NULL,
    "recording_file_path" varchar(500) NOT NULL, -- OSS URL
    "recording_file_size" int4,
    "call_status" varchar(20),                  -- 1正常/2未接通
    "fail_reason" text,
    "remarks" text,
    "sync_time" timestamp(6) DEFAULT CURRENT_TIMESTAMP,
    "create_time" timestamp(6) DEFAULT CURRENT_TIMESTAMP,
    "org_code" varchar(64),
    PRIMARY KEY ("id")
)
PARTITION BY LIST ("city_code");

建议加唯一索引(防重最后一道防线):

CREATE UNIQUE INDEX idx_call_record_id_unique 
ON mid_voice.mid_voice_call_record (call_record_id);

部署说明

1. 准备JAR包

cd /Users/wang/sanduoyun/developspace/dataservice-yy
mvn clean package -DskipTests

产物:target/dataservice-yy-0.0.1-SNAPSHOT.jar

2. 部署目录结构

每台服务器(每地市):

/opt/dataservice-yy/
├── dataservice-yy-0.0.1-SNAPSHOT.jar
├── config/
│   └── application-external.yml        # 修改此文件配置FTP
├── vaa-ftp-temp/                       # 自动创建(临时文件)
└── logs/                               # 自动创建(运行日志)
    └── app.log

3. 修改外部配置

编辑 config/application-external.yml

spring:
  datasource:
    url: jdbc:kingbase8://你的数据库IP:54321/kingbase?currentSchema=mid_voice
    username: dcms_dev
    password: 你的密码

ftp-sync:
  cities:
    - city-code: "340100"               # 你的地市编码
      city-name: "合肥"
      ftp-host: 10.126.129.7            # FTP服务器
      ftp-port: 9979
      ftp-username: ftpuser
      ftp-password: ftppass
      ftp-source-dir: /record/   # txt目录
      ftp-record-dir: /recordfile/  # mp3目录
      ftp-archive-dir: /processed/  # 归档目录

vaa-sync:
  oss:
    base-url: http://你的OSS地址:9090
    upload-url: http://你的OSS地址:9090/apiOss/oss/noAuthFileUploadSingle
    appcode: dataservice-yy
    appid: 你的appid
    appsecret: 你的appsecret

4. 启动服务

cd /opt/dataservice-yy
nohup java -jar dataservice-yy-0.0.1-SNAPSHOT.jar > /dev/null 2>&1 &

5. 验证启动

tail -f logs/app.log

看到如下日志说明启动成功:

【项目启动】开始执行首次FTP录音同步
【项目启动】首次同步完成,后续将在每2小时自动执行

配置项说明

数据库配置(spring.datasource)

配置项 必填 说明
url JDBC URL(人大金仓:jdbc:kingbase8://IP:port/db)
username 数据库用户
password 数据库密码
driver-class-name com.kingbase8.Driver

FTP配置(ftp-sync.cities[])

配置项 必填 说明
city-code 地市编码(如340100),与数据库分区对应
city-name 地市名称(用于OSS路径)
ftp-host FTP服务器IP
ftp-port FTP端口
ftp-username FTP用户名
ftp-password FTP密码
ftp-source-dir txt源目录(处理后归档)
ftp-record-dir mp3/wav文件目录
ftp-archive-dir 处理完的txt移动到此目录

FTP全局配置(ftp-sync.*)

配置项 默认值 说明
enabled true 是否启用FTP同步
sync-interval-cron 0 0 0/2 * * ? 定时任务(每2小时)
temp-path ./vaa-ftp-temp 本地临时文件目录
retain-days 10 临时文件保留天数
txt-encoding GBK txt文件编码(老系统用GBK)
field-separator 字段分隔符(老系统用※)

OSS配置(vaa-sync.oss)

配置项 必填 说明
base-url OSS访问基础URL
upload-url OSS上传接口URL
appcode 应用编码
appid 应用ID
appsecret 应用密钥

txt文件格式

编码:GBK 分隔符:※ 字段顺序

kssj※jssj※hjls※hjzls※zjhm※bjhm※thsc※...※thfx
序号 字段 说明 示例
1 kssj 开始时间 20240101120000
2 jssj 结束时间 20240101120030
3 hjls 呼叫流水 12345
4 hjzls 呼叫主/被叫流水 67890
5 zjhm 主叫号码 055312345678
6 bjhm 被叫号码 12345678
7 thsc 通话时长(秒) 30
... ... 中间字段 ...
10 thfx 通话方向 1=呼入/0=呼出

录音文件{ftpRecordDir}/{yyyyMMdd}/{hjls}_{hjzls}.mp3

防重复机制

层级 方式 说明
1 FTP归档 处理完的txt移到 archive/
2 数据库前缀查重 call_record_id LIKE '340100_FTP_%'
3 内存Set去重 同批内不重复
4 数据库唯一索引 建议在 call_record_id 上加

定时任务

默认 0 0 0/2 * * ?(每2小时执行一次)。

可在 application-external.yml 中修改:

ftp-sync:
  sync-interval-cron: "0 0 0/2 * * ?"

常用 Cron 表达式

  • 每分钟:0 0/1 * * * ?
  • 每30分钟:0 0/30 * * * ?
  • 每小时:0 0 * * * ?
  • 每2小时:0 0 0/2 * * ?
  • 每天凌晨2点:0 0 2 * * ?

日志

日志位置

logs/app.log(按天滚动,保留30天)

日志前缀

前缀 含义
【FTP定时】 定时任务开始/结束
【FTP主流程】 同步主流程
【FTP地市】 单地市处理
【FTP文件】 单txt文件处理
【FTP行】 单行记录处理
【FTP防重】 数据库防重查询
【异常】 错误信息

常用查看命令

# 实时日志
tail -f logs/app.log

# 只看错误
grep "【异常】" logs/app.log

# 只看单地市
grep "【FTP地市】" logs/app.log | grep "合肥"

# 同步成功数
grep "保存成功" logs/app.log | wc -l

常见问题

Q1: 数据库连接失败

检查 application-external.ymlspring.datasource.* 配置,确保:

  • IP和端口正确
  • 用户名密码正确
  • 数据库服务已启动

Q2: FTP连接失败

检查 ftp-sync.cities[0].ftp-* 配置:

  • FTP服务可达:telnet 10.126.129.7 9979
  • 用户名密码正确
  • 目录路径有读写权限

Q3: 录音文件下载失败

检查 FTP 上是否存在对应路径的文件:

  • 路径格式:{ftp-record-dir}/{yyyyMMdd}/{hjls}_{hjzls}.mp3
  • 文件名大小写是否一致

Q4: OSS上传失败

检查 vaa-sync.oss.* 配置:

  • upload-url 接口是否可达
  • appid / appsecret 是否正确

Q5: 数据没有入库

检查:

  • 数据库 mid_voice_call_record 表是否存在
  • 日志中是否有 保存成功 字样
  • 数据库表分区是否覆盖了该地市编码

与老代码(淮南 yydc-tb-server)的差异

老代码 新代码
数据源 Oracle 人大金仓
配置 Spring XML application.yml
同步方式 手动运行 定时任务
mp3处理 只存URL 下载+上传OSS
防重 不防重 数据库+FTP双层防重
部署 单机单实例 多地市独立部署
状态 已废弃 当前生产

维护

频率
检查日志 每天
清理磁盘 自动(保留10天)
数据库备份 由DBA负责
配置文件变更 部署时修改外部配置

联系

  • 项目维护:xxx
  • 内部文档:xxx