设计企业级通用文件传输功能需要注意的几点问题
阅读引导:
1、当前很多企业之间系统交互,涉及到对账文件、影像文件,以及一些较大的文件时,仍然需要非HTTP的文件传输功能
2、文件传输功能,对于网络、IP、内存、硬盘消耗都较大,需要充分考虑。
3、目前文件传输平台多种多样,需要考虑此种功能的扩展支持模式。
当前系统交互的主流模式,是通过HTTPS字节流方式通讯。
但是,在某些特定场景下,直接传输文件(异步/同步)还是有需要。
尤其是在企业间交互,很多情况下文件传输是必不可少的功能。
简单例子:在某个企业向银行申请融资功能时,一般需要上传营业执照影像件、合同协议影像件等内容,而企业客户的用户数量又比较大,文件也需要展示,所以非常需要异步文件传输。
1
文件的通用存储模式&常见传输模式
文件方式传输,基本的传递方式,或者说文件流动方式,就是将文件从A放到B。
A——>B
那么我们首先就要了解一下,当前存储文件的方式有哪几种,本文不做底层介绍,只从应用层视角来介绍。
文件存储方式
-
本地文件存储
也就是说,客户直接把文件存储在应用本地,这种情况现在比较少见了,基本上可以排除不用考虑。
-
文件系统
传统的文件服务器有FTP服务器、SFTP服务器,也是实施起来成本低、难度较低的文件存储方式。一般企业,除非对文件有大批次高频率的需求,否则一般都是选择SFTP服务器。
-
对象存储
就是把文件作为一个对象,使用键值对的方式进行存储,较为少用。
-
分布式文件存储
如同阿里提供的HDFS(Hadoop Distributed File System),提供了完善的SDK、高可用等机制,但是企业搭建成本高、难度大,一般采购外部服务的话也需要成本,反而很少人用。
-
其它平台
例如,腾讯的OSS
文件获取通讯方式
实际上,对方的文件是如何存储的,对于应用层来说,我们并不关心,文件系统不管怎么发展演化,最终对外提供服务,脱离不了几种通用通讯范畴。
-
FTP/SFTP
比较常见的模式,FTP由于其安全性并不推荐,一般建议使用SFTP服务。
对于Java来说,很多开源的FTP/SFTP实现,例如支持ftp的ftp4j,支持SFTP的jcraft开发的jsch。
当然,还有很多开源组件直接提供了FTP服务,例如camel,需要辨别分析是不是符合要求。
-
HTTP/HTTPS分段传输
一些外部平台类系统,都是通过封装这种方式,进行的文件传输,当然对于特殊需求的客户,也需要自己实现。
所以,这里包含两个点,一个是平台对外提供的标准分段传输接口。
另外一个点,有可能需要去适配各个外部平台,这样的话尤其需要注意设计的程序架构的灵活扩展性。
2
文件传输策略模式
上文我们说道,除了通用的FTP/SFTP协议,以及平台提供的HTTP/HTTPS通用标准协议模式,还需要支持个性化的客户需求。
外部平台千奇百怪,所以在使用文件传输功能的时候,需要充分考虑各种通讯方式的扩展。
换一种说法,文件传输功能需要支持各种传输模式的扩展。
同一种通讯模式,各个厂商平台能玩出花来……标准肯定是不统一的。
所以,客户A的文件传输模式是S1,客户B的策略可能是S2……
最适合这种模式的,当然是策略模式。
毕竟,每个客户的文件传输模式各异,但是一般都会明确一种,正是策略模式的适用场景。
策略模式详情本文不再赘述。
尤其注意的一点,如果是做在网关等通用服务平台上,需要考虑的两边都需要配置成策略模式,因为一次文件传输有两次交互。
源文件方<——>网关平台<——>目标文件方。
3
文件传输的基本流程
一般情况下,对于通用的文件传输功能,是类似于网关等平台提供的通用服务,不需要产品系统去处理。
所以,文件传输功能的一般处理流程如下,以sftp服务为例:
接收文件传输请求——>异步/同步发起传输任务——>去源文件方sftp服务器获取文件——>下载到网关本地——>上传到目标方SFTP服务器——>通知源文件方/目的文件方文件传输结果。
这是几个大的节点,在设计的时候,要支持重复执行,也要设计好重复执行的策略,例如第一次失败后5分钟后重试,第二次15分钟后重试……一般要覆盖24小时,以每次间隔递增的方式制定策略。
下面,我们从每个流程步骤说明要注意的点。
接收文件传输请求
一般作为网关,是响应式处理,不会主动发起轮询去传送文件,所以需要消费者(目的文件接收方)或者生产者(源文件方)发起调用,然后将文件传输任务落库。
注意,对于文件传输一般不推荐进行同步传输。
异步发起传输任务
异步发起任务,可以通过Quartz等定时任务处理框架发起。
需要注意的点是,一般网关等系统都是多活,非单实例的。
这就需要考虑任务的争抢问题,避免重复调用。
最粗糙的办法,是使用MySQL行级锁,进行竞争。
或者,使用Redis等中间件构建任务队列。
去源文件方sftp服务器获取文件
这一步,需要支持策略模式,因为我们虽然以SFTP为例,但是可能有别的传输方式,甚至SFTP也有不同的处理方式。
例如SFTP支持用户名、密码登录,也支持密钥登录。
下载到网关本地
这一步的时候,需要考虑不同的商户、时间、文件名称等要素,以作为区分,防止文件覆盖。甚至一个物理服务器部署了多个实例的话,也需要区分,防止出现覆盖问题。
另外,还要考虑应用文件系统的容量。
下载完成文件之后,需要及时删除。
文件完整性校验、安全、加解密
下载文件后第一件事一定要做完整性校验。
首先当然是防止文件传输过程中发生了传输不完整的情况。
还有一个主要问题是,经常会出现客户的文件本地生成了,但是上传其FTP服务器失败,结果拿到文件再进行解密、验签的时候,就会报错,这种问题比较难查。
所以,拿到文件后第一步一定是进行MD5完整性校验。
剩下的解密、验签等操作,就不再赘述。
上传FTP服务器的路径创建问题
在多并发情况下,可能有多个文件传输任务在执行。
假设,生产者的文件拿到消费者服务器,约定目录是:/yyyyMMdd/
也就是说有一个日期文件夹,需要程序每天第一次上传文件时创建。
如果,多个任务同时执行,有可能同时在创建文件夹的时候,报错。
所以,对于创建文件目录的逻辑,需要做以下处理,伪代码:
创建文件夹。
如果发生异常,监测文件夹是否已经存在,如果已经存在则继续进入,否则再次尝试创建。
如果再次失败,则退出,等待下次任务重新触发执行。
重试机制
文件传输由于各种原因,会发生传输失败的情况。
最多的原因是网络发生变动,或者异常。
由于执行传输任务的线程数量是有限制的,所以需要考虑及时终止,以及重新触发机制。
一般情况下,失败重试间隔时间设置为:5min、15min、30min、60min、3h、6h……
上面是程序自动重试,还有一点就是,在后台管理台一定要做好重新触发功能。
如果业务不敏感,有时候发现报错会是几天以后了,需要支持重新触发任务。
大文件问题,大小限制问题
在进行文件传输的时候,一定要考虑文件的大小、频率,从而估算带宽(尤其是专线)、IO,以及执行文件传输的线程数量。
超时问题
如果发生大批量的文件传输,或者网络抖动等因素导致的网络带宽不足,FTP的传输会导致非常耗时,一般在30分钟都用可能无法完成任务。
这样就会导致此线程一直被占用。
这时,应该结合网络的监控,对带宽进行告警。
文件通知
生产者文件,传输到目标服务器后,可以支持通知功能。
一个任务,应该可以同时支持通知生产者、消费者。
避免消费者开启线程,定时扫描文件服务器,减少资源耗费。
另外,作为网关平台,还需要考虑,如果一个生产者对应多个消费者,也就是说可能上传到多个服务器路径怎么处理?需要根据不同的业务逻辑通知不同的消费者怎么处理?
4
其它
对于网关来说,提供了通用的文件传输功能,很多消费者就会找上门来。
发生了任何问题,很多人都不考虑就直接来咨询,对于支持的工作量大增。
并且,如果文件传输任务数量大增,而线程池数量有限,那么异步传输需要执行较长时间。
这样,对于某些业务场景需要依赖文件,需要知道当前文件传输的状态。
一定要提供任务查询接口供相关方调用,减少沟通支持工作量。