国产色图分卷解压rclone直传方案

大类
Util
技术标签
云服务-白嫖
优先级
Medium
开始日期
Jul 24, 2022
状态
Maintaining
Public
Public
最后更新
Aug 4, 2022

起因

很多国产的色图通过百度云分卷压缩+加密得到,要想查看则必须要完整下载所有分卷,查看不便
希望能转到onedrive中进行查看
 

整体数据流动分析

  • 数据流:分卷加密压缩文件【百度云】 - 解压后文件【OD】
  • 数据流入(从百度云下载)
    • 百度云解析较为困难,难以直接挂载解压
    • 解压时常常需要随机读写多个文件,速度堪忧
    • 使用一个大盘鸡作为中转
  • 数据流出(OneDrive)
    • 大盘鸡磁盘io性能差,难以解决解压、小文件的困难
    • 尝试使用rclone挂载OD,直接让大盘鸡解压到OD
 

v1.0:单层7z加密分卷包,Rclone mount+直接7z

基本思路

  • 直接rclone mount之后,7z x解压到文件夹
  • 压缩包中内容为大量小文件

Rclone挂载参数调优

为了能让数据流持续流动,保持高性能,需要让rclone持续上传文件,并作一定缓存
实际中,rclone实现有大量隐形bug,导致解压经常卡顿
调优历程:
  • vfs-cache-mode:OD因为上传时必须已知大小,故必须选择writes以上
  • 尝试启用所有缓存(metadata、kernel、attr等)的过期时间调优:--write-back-cache --attr-timeout 1m
  • 启用webgui、rc、debug输出等便于调试:--rc --rc-addr 0.0.0.0:5572 --rc-no-auth --rc-web-gui --rc-web-gui-update -vvP
  • vfs缓存路径:大盘鸡机械硬盘性能有限,故尝试使用tmpfs内存盘存储文件,减小磁盘io压力
    • sudo mount -t tmpfs -o size=1024m tmpfs /tmp/rclone_memcache
    • 每次启动前清空cachedir:rm -rf /tmp/rclone_memcache/*;
    • --cache-dir /tmp/rclone_memcache
  • vfs缓存大小管理:--vfs-cache-max-size 600m --vfs-cache-max-age 1s --vfs-cache-poll-interval 10s
    • 由于tmpfs空间有限,必须让cache尽可能快的被清空,故选择了较小的max size,最短的max age和很快的clean interval
  • 传输参数调优:--transfers 20 --timeout 30s --tpslimit 4.0 --tpslimit-burst 8 --checkers 250
    • 限制最大传输线程、HTTP请求速度,避免OD 429
    • 限制timeout,避免OD上传卡死
  • --no-modtime:如果开启modtime,则由于7z会在写入完成后修改modtime,造成modtime变化,导致错误
  • --vfs-write-back 0s:这个参数默认为5s,用于在写入结束后延迟上传,其中实现有bug,会造成rclone死锁
    • 死锁表现为vfs的cache clean timer并没有触发(类似这样的:vfs cache: cleaned: objects 13 (was 27) in use 12, to upload 0, uploading 0, total size 62.625Mi (was 125.848Mi))
    • 暂未进一步调查
总命令:
rm -rf /tmp/rclone_memcache/*; sudo umount /boxdata/downloads/onedrive-loliloli-e5; rclone mount onedrive-loliloli-e5: /boxdata/downloads/onedrive-loliloli-e5 \ --transfers 20 --timeout 30s --tpslimit 4.0 --tpslimit-burst 8 --checkers 250 \ --vfs-cache-mode writes --write-back-cache --attr-timeout 1m \ --no-modtime \ --vfs-write-back 0s \ --vfs-cache-max-size 600m --vfs-cache-max-age 1s --vfs-cache-poll-interval 10s --cache-dir /tmp/rclone_memcache \ --rc --rc-addr 0.0.0.0:5572 --rc-no-auth --rc-web-gui --rc-web-gui-update \ -vvP 2>&1 | tee rclone_mount_debug_log.log \ | grep INFO
 

v2.0 tar+7z加密压缩包,tar mount后解压到rclone mount

(方案整体失败)基本思路

  • 使用ratarmount挂载tar,随后使用7z x解压
  • 压缩包中为少量大文件

Rclone mount调优

  • 如果使用writes cache mode,那么文件解压后会全部存储在cache dir中
    • 若cachedir为tmpfs,则内存占用会很大
    • 若cachedir为硬盘,那么iowait也会很大
    • 尝试修改rclone在写入cache dir报空间满时停止,发现会经常死锁,无法使用
  • 如果使用minimal cache mode,由于7z并不是顺序写入而是会在小范围内抖动seek后写入, 会导致rclone失败
    • 尝试修改对应逻辑,rclone实现高度同步,没有插入等待代码的空间,难以实现

失败原因:rclone mount架构灵活性不足,对cache依赖太大

 

v2.1 tar+7z加密压缩包,tar mount后7z mount,再使用rclone copy

(方案整体失败)基本思路

  • 类似于v2.0,但使用rclone copy规避掉7zip的小范围随机读写和cache问题
  • 使用ratarmount后,再将7zmount上,然后rclone copy
 

Fuse 7z的方案的选择

1. fuse-archive: libarchive + fuse

libarchive支持7zip,但是不支持加密的7zip,更不支持加密文件头的7zip,巧合的是前两天刚有人说自己要试着implement一下
 

2. fuse-7z-ng: lib7zip + fuse

lib7zip是直接用的p7zip / 7-zip本身的dll COM接口,非常难看,但是功能也是最全的,支持加密、加密文件名、分卷,相当于7z命令行的c++版本
fuse-7z-ng两个版本,一个是merge最新那个人PR的版本(新版),一个是之前内置了lib7zip的版本(旧版——
  • 编译:两个版本都可以编译
    • 新版:cmake设置lib7zip_binDir等变量即可链接
    • 旧版:autogen后configure随后make同样也可成功
  • 加密支持:原版均不支持加密,添加密码参数后可支持加密
    • 新版:支持加密文件名
    • 旧版:无法支持加密文件名
  • 问题:
    • fuse-7z-ng并不支持随机读写,fuse的原理是当用户open一个文件后将文件内容全部读出,保存在buffer中以备后用
    • 无法支持多个大文件读取

失败原因:fuse-7z-ng不支持流式读写

 

v3.0 tar+7z加密分卷压缩包,tar mount后直接用lib7zip传至rclone

基本思路

  • 跨过mount,直接让7z和rclone进行沟通
    • 为了方便管理、支持端口复用,rclone方新增一个rc方法,将rcatsize导出
    • 使用程序从fifo将7z解压数据传出
  • 编写 wrapper script,自动探测多层压缩包的结构
    • 目前遇到的情况:
      • 7z分卷(7z.001) 加密
      • tar分卷(tar.001) 7z分卷(7z.001) 加密
      • tar单独一个包 7z单独一个包 加密
    • 识别文件的后缀名,将00X后缀的文件组成一组,随后对每组文件进行分析
      • 通过7z l 判断压缩包中文件的列表,决定是否需要mount

解压实现思路

  • lib7zip是c++的,c++和其他设施的可操作性基本为0,要想和rclone打交道肯定是Python或者Golang比较好
    • Python有py7zr,测试后可以读取加密文件名的archive
    • Golang一番搜索后发现有sevenzip-go,可以用
    • 权衡之后认为lib7zip使用的是7z本身的库,兼容性、格式支持都会更好
  • 使用Golang+sevenzip-go,在extract callback中调用rclone rcatsize
    • sevenzip-go不支持加密、不支持分卷,需要魔改
    • rclone不支持远程调用rcatsize
      • 每次spawn一个rclone开销太大,无法共用HTTP连接池,而待解压文件往往为小文件
      • 新增一个rc接口operations/rcatsize,接收fifo路径、大小、修改时间,从而实现远程读写
    • sevenzip-go不支持修改时间读取,魔改一波
  • 运行十分完美