大文件的传输方案(scp以及文件切割)
大文件的传输方案(scp以及文件切割)首先,我们需要明确什么样的文件算是大文件。通常情况下是以4G容量作为文件是否为大文件为标准,其原因为U盘有很多还是fat32格式的分区,fat32格式的U盘仅支持4G以下的文件。相信很多同学有过在做U盘启动盘的时候并不能够制作成功win7或者win10这样的启动盘,原因在于系统安装ISO文件大于4G,而U盘为fat32格式分区,不能够将ISO文件写入U盘导致的
大文件的传输方案(scp以及文件切割)
首先,我们需要明确什么样的文件算是大文件。通常情况下是以4G容量作为文件是否为大文件为标准,其原因为U盘有很多还是fat32格式的分区,fat32格式的U盘仅支持4G以下的文件。相信很多同学有过在做U盘启动盘的时候并不能够制作成功win7或者win10这样的启动盘,原因在于系统安装ISO文件大于4G,而U盘为fat32格式分区,不能够将ISO文件写入U盘导致的。
其次,影响并决定文件的传输成功与否与三个因素密不可分,一是内存,二是网络带宽,也可以理解为网速,三是CPU性能,其形式一般为点对点的文件传输。
以上所说只是一个大的概念,具体的实务操作是更复杂的一个过程,通常的,分为网络间的文件传输和一个操作系统内不同磁盘之间文件传输。
网络间的文件传输:
网络内的文件传输会使用到upd或者tcp网络协议进行文件的读取,复制等等过程。
比如,最直接的方法:从网络请求中找出文件在磁盘中的路径后,如果这个文件比较大,假设有 320MB,可以在内存中分配 32KB 的缓冲区,再把文件分成一万份,每份只有 32KB,这样,从文件的起始位置读入 32KB 到缓冲区,再通过网络 API 把这 32KB 发送到客户端。接着重复一万次,直到把完整的文件都发送完毕。
那么,这一过程所经历的详细操作如下:
上下文切换:
首先,它至少经历了 4 万次用户态与内核态的上下文切换。因为每处理 32KB 的消息,就需要一次 read 调用和一次 write 调用,每次系统调用都得先从用户态切换到内核态,等内核完成任务后,再从内核态切换回用户态。可见,每处理 32KB,就有 4 次上下文切换,重复 1 万次后就有 4 万次切换。
上下文切换的成本并不小,虽然一次切换仅消耗几十纳秒到几微秒,但高并发服务会放大这类时间的消耗。(CPU的性能可能成为瓶颈)
内存拷贝:
其次,这个方案做了 4 万次内存拷贝,对 320MB 文件拷贝的字节数也翻了 4 倍,到了 1280MB。很显然,过多的内存拷贝无谓地消耗了 CPU 资源,降低了系统的并发处理能力。(内存的大小可能成为瓶颈)
我们可以得出一个结论,网络间的文件传输,对两端的服务器的内存和CPU都是一个考验,同时对两端的网卡也是一个考验。(如果有兴趣,你可以试试观察网络传输时的网卡灯,会疯狂的闪烁哦。)
操作系统内不同磁盘或者分区之间的文件传输:
这里的不同磁盘通常指的是操作系统比如windows和另一个独立的文件系统比如U盘,这里的传输和网络间文件传输不同在于没使用网络传输协议,完全是系统内核对文件的调度。因为没有协议的限制,因此,网络带宽不是决定性的考量,而是CPU和内存的性能了。
1.复制的原理是将文件的副本拷贝到内存的一块缓冲区中,也就是我们说的剪贴板。缓冲区容量有限,遇到大文件会分批进行拷贝 ,只不过我们不会察觉。同时不断将缓冲区内的数据写入到目标位置。即完成文件复制。剪切比其多一个步骤,就是在复制完成后将源文件删除,即在文件分配表中为源文件标上删除标记。
2.视文件数量而定。剪切一般比复制慢那么一点点,就是慢了个删除源文件的时间,当然,源文件数量越多,剪切就比复制越慢。此处只是普通删除,删除速度和文件大小没关系,只和文件数量有关系。
上面是跨分区。下面是对同分区的一点解释
4.因为在同一分区,所以剪切是直接改变文件分配表中的内容,将数据链接到另一个文件名上,所以很快。而同分区复制不是很快的,跟跨分区复制一样。
以上其实提到了一个文件流的概念,如果有过编程经历我想会十分容易理解。也就是说,有两个概念,一个是文件流,一个是内存缓存。因此,我们如果是使用古老的winme这样的系统会体会到蓝屏的痛苦,原因是以往的操作系统是将文件整个的全部读取到内存缓存,而并不会智能的自动切割,因此常常会将操作系统内存撑爆。所幸,社会一直在进步,操作系统也在不断的进步中。
其实,不管是哪种文件传输,都是使用的分而治之的方案,也就是先将一个文件在源文件端分割成一个合适的大小,然后在目标端重新组装起来一个完整的文件。
多说一句,文件的传输过程是一个很复杂的过程,和cpu,CPU的一二级缓存,内存,内存的缓冲区,文件系统(指的是xfs,ext3,ext4,fat,fat32,ntfs,hdfs等等各类文件系统)的各自不同特点,网卡的吞吐量,交换机的性能等等各种因素都有密切的关系,如果硬要说明白,那么,可能需要写一本书。只需要记住,只要是传输,那么,离不开分而治之的思想。
以上,是一些比较抽象的概念性的东西,来点实际的吧。第一个问题,如果实现高效,快速,安全的文件传输?
有这么几种方案,第一,小文件合并成一个整体文件,也就是打包文件,打包的同时进行合适的压缩。第二,网络传输时使用tcp协议进行传输。第三,大文件打散成小文件,也就是切割成小文件,降低磁盘容量,有效利用网络带宽。简单的说,就是压缩和切割。
关于压缩工具的选择,Windows一般使用winRAR基本就够用了,Linux下的选择比较多,比如常用的tar,bzip2,gzip,这里推荐一个压缩神器,超高压缩比的软件,具体见博客:https://blog.csdn.net/alwaysbefine/article/details/110424989
关于切割大文件工具的选择,Windows推荐使用神器hjsplit 这个软件,Linux下使用rar,下载链接为:https://pan.baidu.com/s/1kIj9diSEorAr0pT70434ag ,提取码:rara,包含hjsplit和Linux的rar。
在Linux下常用的切割大文件软件为split,该软件为系统自带的软件,十分的人性化哦。
在源端将文件切割后传送到目标端后,当然需要合并了,这里大略的举几个例子:
windows源----》Linux目标 使用hjsplit在Windows端切割后,Linux 使用cat 命令重定向后合并文件
这个文件14k,如果按2k大小切割会是切割成7个文件
切割完毕后,上传到Linux服务器, cat Oracle* > oracle.sql,可以看到完整的文件又回来啦!!!
Linux系统下的切割文件:
在Linux服务器上,我有一个文件,内容是mailx的帮助文档,文件大小是140k,计划切割成50k的三个文件?如何切?
[root@centos7 ~]# split -b 50k -d --verbose mail.man mail.txt
creating file ‘mail.txt00’
creating file ‘mail.txt01’
creating file ‘mail.txt02’
以上命令为 -b 按文件大小切割,每个文件50k,-d指定按数字递增命名切割出来的文件, --verbose 显示详细过程, 要切割的文件,切割后的文件名称。
[root@centos7 ~]# ll
total 296
-rw-------. 1 root root 1587 Jan 23 22:17 anaconda-ks.cfg
-rw------- 1 root root 631 Feb 16 09:27 dead.letter
-rw-r--r-- 1 root root 1635 Jan 23 23:05 initial-setup-ks.cfg
-rw-r--r-- 1 root root 143091 Feb 16 10:22 mail.man
-rw-r--r-- 1 root root 51200 Feb 21 00:37 mail.txt00
-rw-r--r-- 1 root root 51200 Feb 21 00:37 mail.txt01
-rw-r--r-- 1 root root 40691 Feb 21 00:37 mail.txt02
可以看到,00和01文件是50k大小,原始文件不够的部分分配到02这个文件了。那么,现在把原始文件 mail.man删除了,在合并呢?(原文件是2199行,现在删除后,合并前面切割出的文件,看看还是2199行吗???)
[root@centos7 ~]# cat mail.man |wc -l
2199
[root@centos7 ~]# cat mail.txt0* > mail.bak
[root@centos7 ~]# cat mail.bak |wc -l
2199
合并后命名为mail.bak ,查看内容和行数与最原始文件一致。
Linux就是这么强大!!!!!!!!!!!
如果源文件或者源文件夹所在操作系统为Linux,目标操作系统也是Linux,那么,方便快捷的scp命令就可以闪亮登场了,仅仅需要知道目标操作系统的IP地址,ssh连接所开放的端口号就可以了,(一般是默认的,如果不是默认的端口号,指定目标操作系统的端口即可)。
如果是默认的端口,省略-P 参数,指定加端口号,如果源是文件夹,-r参数就会递归的传输文件了。
例:将a机器的/etc 目录复制到远程的b机器的 /mnt 目录下,那么,命令将为在a机器上执行:
scp -r /etc/ b机器的ip:/mnt/,如果b机器ssh所开放的端口为11111,那么命令为在a机器上执行:
scp -r -P 11111 /etc/ b机器的IP:/mnt/ ,命令执行后,将会要求输入目标机器也就是b机器的root密码(默认是root用户登录,因为root用户权限最大,不会引起权限问题,从而造成scp失败,如果要使用b机器的普通用户,命令如此:scp -r -P 11111 /etc/ 普通用户名@b机器的IP:/mnt/)。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)