我的又一个 fuse 客户端——upyunfs

我写 fuse 客户端可能有点上瘾,是因为我觉得对于在线存储类的服务,能够映射到本地存储,对用户来说是路径最短,学习成本最低、体验最友好的方式。而要实现类似的效果,据我所知要么用 fuse 把远端的存储挂载到本地(如 sshfs、amazon s3fs),要么写个后台服务实现本地和远端的双向同步(同步远端可以轮询或用某种 push 技术,同步本地可以用 inotify,典型案例是 dropbox)。而我之所以倾向前者,是因为 fuse 的实现成本要小很多,对于个人开发者来说性价比完胜。

有了上述前提,什么专门的 GUI 管理工具啦,专门的 shell 啦,在我看来都比较无聊——当远端的文件系统已经变成本地的一部分时,用户可以使用任意自己熟悉的文件管理工具(无论 GUI 还是 CLI),可以使用任意自己熟悉的 shell 环境(包括相应的各种工具),来完成对远端的文件管理任务。比如将 dropbox 同步到 upyun,在我看来只需要这样就可以了:
upyunfs -b lyman_foo ~/cloud/upyun # 挂载 upyunfs
rsync -avh ~/cloud/dropbox/ ~/cloud/upyun/ # 用 rsync 同步两个文件夹
所以看到 upyun 搞了开发者比赛的时候,我实在是忍不住,便写了这个 upyunfs

对实现细节不感兴趣的同学可以忽略下面的文字了,不过还是希望各位能给 upyunfs 投个票:到项目页面里找到 upyunfs-for-UPYUN,点击「投票」按钮即可。

接下来大概分析一下 upyunfs(以及类似存储系统)的实现要点。

一、技术选择

fuse 有各种语言的 binding,从执行效率角度考虑首选当然是 c/c++。但是如 upyun 这样提供 RESTful 接口的服务,用到字符串操作的地方不少,所以用脚本写起来更方便。python 的 binding 我试过一次,问题不少文档不多,所以我一直用 perl。

二、roadmap

  1. 基本功能
    这个阶段基本上只要做好 fuse 回调和 RESTful api 的映射就好了。具体一点,在线存储系统基本上必不可少的 upload/download/list 操作,大抵就可以对应到 fuse 的 read/write/getdir 上。此时如果有合手的 sdk,完成第一阶段会格外快。即使没有 sdk(这年头能直接提供 perl sdk 的公司实在是不多),用 libwww 实现一个也不复杂——像 upyun 官方的 python sdk 那样只包装了签名认证的,写一个也就个把小时。

    这一阶段的难点是 api 映射。因为 fuse 的回调基本上是标准的 unix 风格,文件需要先 open,read/write 之后再 release。了解 fuse 各个回调的语义及调用时机至关重要。如 upyun 并不支持带 offset、length  header 的 GET 操作(至少文档上没说),而 fuse read 每次被调用只读取 4k-128k 的片段,因此有必要将下载的远端内容缓存起来(阿里云的 oss 就可以无需如此)。同理,write 每次调用也是写一个片段,需要将写入远端的文件缓存起来,然后再一次性上传到远端。

    这一阶段完成后,基本的文件操作就都可以支持了。在网络条件很好的情况下也不会有太大的问题。
  2. 完善的功能
    这个阶段一是简化用户的使用,比如支持通过配置文件来读取用户名/密码/bucket;二是支持在线存储独有的功能,比如 upyun 对图片文件就可以通过配置一系列 x_gmkerl header 来改变上传行为。
  3. 优化
    这是个无底洞。根据使用场景不同,会有很多不同的策略和实现途径。

    比如在多数家庭网络条件下(adsl,下行带宽>>上行带宽),在 release 时的同步上传就会让 release block 颇久。而 gnome 3.12 在这种情况下是会死锁的。于是,对于使用 adsl 的 gnome 用户来说,release 就需要优化——比如通过线程来异步完成上传操作,而异步的引入会令数据一致性的维持变得复杂起来(目前 upyunfs 已经实现到这里)。

    再进一步,upyunfs 在第一次 read 文件的时候,就需要把整个文件从远端下载到内存中,如果用户的网络还要差,或者文件比较大,这会导致第一次 read 也 block 很久。那么是不是应该优化下载过程,把原来一句简单的 $respond = $ua->request($req) 替换成其它实现,可以不用等到整个文件下载完成才返回?

    再进一步,如果用户的内存不太够,是不是应该支持用户把读写 cache 设置成本地文件系统的一个临时目录?

    还有,对 fuse 回调实现,需要其行为多大程度上跟其 unix 同名 api 的语义一致?如 open、read 的时候是否需要参考诸如 O_TRUNC/O_NONBLOCK 这样的 flag?

    如上所述,这个阶段有太多的如果,而且每个点都不可避免的导致设计复杂或者代码激增,从而需要更多的投入。但不能否认,这些细节才是 upyunfs 是否成熟的标志。
ps. 给阿里云 oss 写的 ossfs 已经 outdated 了,测试用例挂了一堆,有空我会看下是不是 oss 有啥改动。

评论

e0mvkz8vv0说…
3D modeling can also be|can be} used in the field of commercial design, whereby merchandise are 3D modeled earlier than representing them to the clients. In media and event industries, 3D modeling is utilized in stage and set design. A wide variety of 3D software program are additionally utilized in constructing digital illustration of mechanical models or components earlier than they are actually manufactured. CAD- and CAM-related best rated zippered compression stockings software program is utilized in such fields, and with this software program, not only capable to} construct the components, but in addition assemble them, and observe their functionality.