guilded dir drive v4.22.08.04

到现在guilded drive已经来到了第三代,它第一代就是个单纯的管道玩意,第二代加上了临时文件和多线程上传,第三代加上了检验checksum的功能🤔

那么问题来了:有没有可能在不产生临时文件的情况下实现第二代那样的多线程上传功能?🤔

我今天大致折腾了下,它是可以的,但需要一套相对复杂又相对比第二代简单的方法:

  • 首先,和前几代一样,需要将一个每分块大小*线程数这么大的数据流分片用split --filter传送进临时脚本1🤔

  • 和第二代不同,在临时脚本1里,接收的数据流并没有暂存到某个文件里,而是接着用split --filter传送进临时脚本2,此时大小被设置为上述的每分块大小🤔

  • 而临时脚本2并不是负责上传的脚本,它只不过将数据流照原样传送进临时脚本3,但在之后加了一个&,所以它是临时脚本3实现多线程上传的关键🤔

  • 临时脚本3才是真正的上传脚本🤔

和第二代一样,这一代多线程上传脚本也需要在上传完成后标记上传的部分属于哪一个线程🤔但考虑到这么多的split --filter的subshell特性,我最后决定将partno这一玩意用文件的形式传送进临时脚本3:

  • 在临时脚本1的开始,将0写入/tmp/counter这个文件🤔

  • 然后在临时脚本2的开始,从这个文件里读出值,将其加1,然后再次写入这个文件,再将加了之后的值传送进临时脚本3🤔

  • 这样,临时脚本3接收到的partno参数肯定是正确的partno参数,证明过程略(🤔

  • 在临时脚本1的split后面加上sort这一坨玩意,将多线程上传的结果进行排序和去除partno🤔

通过这种方式,我们再也不用什么head什么tail来切割临时文件了,整个代码的可读性直接提升了114514倍(迫真🤔

不过我好奇代码写成这样,它还能做流式上传不?比如我现在开了16个线程,每个线程200MB分片,这玩意是要占用3.2GB内存空间,还是不占用?🤔如果curl被我配置成了自动重试,那么当它重试时,是从什么地方读取要上传的内容呢?还是curl会把这部分数据流缓存进它的内存空间?🤔

还有一个问题:既然它现在是流式(迫真)上传了,那么checksum和上传基本上是没什么可能兼得了(恼🤔以前我们可以通过将临时文件读两遍来同时做checksum和上传,现在怎么搞,把管道也拆成两份?等等,stdout这玩意支持塞进两个程序里吗🤔

thonkeqing

另外我之前发现某个片子下载后tar提示数据流有错误,排查发现有一个包完全没有上传上来🤔而且我这次测试脚本的时候也发生了一次这种现象🤔

考虑到我上个月初可是拿这玩意备份了所有的vultr快照,现在好了,我慌的一批(迫真🤔

那么在流式上传过程中,有没有办法像传统读文件上传那样设置重试功能?🤔我的意思是除了在curl里面加重试之外的方法,比如经典检查guilded返回值外层套while法🤔cat -能重复cat很多遍吗?🤔

实测cat -并不能重复很多遍,只有第一遍能接收塞进脚本里的数据流,后面都是空的🤔看来它的确是流式传输啊(确信🤔

发表评论