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.
|
|
3 weeks ago | |
|---|---|---|
| config | 1 month ago | |
| logs | 2 months ago | |
| sql | 3 weeks ago | |
| src | 3 weeks ago | |
| .DS_Store | 2 months ago | |
| .gitignore | 2 months ago | |
| README.md | 1 month ago | |
| VAA_SYNC_README.md | 2 months ago | |
| pom.xml | 1 month ago | |
README.md
语音数据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.yml 的 spring.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