Rustatic——一个小巧快速的文件服务器!

首先是性能对比:

大约提升了41%的性能,考虑到cache buffer预热之后,属于纯内存拷贝操作,符合预期。

为什么做这个

之前做了一个纯静态的网站,因为上面放的是自己摄影的作品,想要一个保存图片的功能,于是想着自己做一个小图床,但是后来觉得既然做,就索性追求性能好了。

设计

考虑到主要的功能都是静态文件操作,所以想要提升性能,就要从"不必要的操作"下手。毕竟在磁盘性能固定,带宽都一样拉的情况下,减少服务端的活就成了近乎唯一的选择,当然客户端也需要,但收益就小了很多。

在服务端想做到静态文件上传,似乎没什么好的做法,就是纯粹的读取,写入,无非设置buffer大小这种炼丹级别的做法。后来也有调查过Linux文件预分配,之后使用mmap进行减少拷贝,考虑到上传是一次操作,所以为了减少开发难度,决定暂时搁置。

但是文件下载则是一个值得考究的问题,因为有零拷贝zero-copy技术可以用。

在文件下载的选择上,有mmapsplicesendfile三种选择。

首先是mmap,对用户空间和内核空间映射,减少一次内核到用户的拷贝。

之后是splice,直接建立文件FD与SocketFD之间的管道,减少内核到用户,cache buffer到Socket buffer两次拷贝。

最后是我们选择的sendfile。它可以减少一次内核到用户的拷贝,如果DMA支持的话,甚至可以减少内核之间的拷贝(cache buffer -> socker buffer)。

为什么不选择mmap呢?因为会引入多一次的系统调用,在mmap之后,还需要调用write进行写入。其次呢,mmap更加复杂,有更多的参数需要设置。

mmap更适合内存共享,而sendfile天然适合文件传输,尤其是大文件。

至于splice,首先是不方便,然后是不如sendfile稳定,这点在网上可以找到Linus的回复,并且StackOverflow有一些论证,表明它是不建议使用的。

为什么不用io_uring

因为不方便。在Rust中使用io_uring首先就是库不成熟,各大运行时都有自己的实现,但更多像打补丁似的兼容实现,性能是个问题。但是更重要的是,io_uring的文件操作并不全是类似IOCP那种全异步的实现,内部也是线程池实现,介于此(复杂的使用和并不完美的文件操作),最终决定放弃。

既然确定了技术方案,剩下的就是搭建了。

首先使用两个TCP连接去处理,一个当作控制连接,一个数据连接,为什么不用UDP?是因为sendfile需要文件FD作为目标,而UDP无连接的特性不支持。

其次两个连接方便分别处理,隔离出来专门的数据路和请求路。

在监控Socket读写之后,需要把实际的文件读写放到线程处理,因为阻塞Reactor会导致后续所有其他连接被阻塞。目前Rust异步运行时均为此模型,所以就引入了线程池的使用。

整体逻辑为:

  • 双连接建立,控制连接生成标识符,用户发送标识符到数据连接,进行二者的配对。
  • 用户请求控制连接,产生的数据或者需要接收的数据通过数据连接发送和接收。

既然需要使用线程池去处理数据连接产生的文件读写,选择一个或者设计一个线程池就显得很有必要了。

其中Automatic是为了此项目设计的线程池,Unblocking则是smol旗下的,还有经典的Threadpool以及Rayon。

第一张图是对于固定耗时5微秒的任务执行情况,第二张图则是纯粹的调度对比。

均为1024个异步Task,每个10次调用,可以看到Automatic还是很强劲的。

其内部使用了ThreadLocal技术,外加TaskStealing进行合理的任务分配。

有了上述设计,便可以设计用户交互的接口了。

UI设计

这里采用终端交互的形式,包括登陆,注册,上传,下载,列表等操作。

项目地址

相关推荐
星栈11 小时前
10 分钟跑起第一个 Dioxus 应用:`dx` CLI、`rsx!` 和热更新好不好用
前端·rust·前端框架
望眼欲穿的程序猿17 小时前
读取芯片内部温度传感器
嵌入式硬件·rust
望眼欲穿的程序猿17 小时前
ADC 模拟电压采集
嵌入式硬件·rust
codexu_46122918717 小时前
NoteGen 里一条记录如何变成 Markdown
前端·笔记·rust·tauri
Rust研习社18 小时前
Rust 错误处理的黄金搭档:一个定义错误,一个传播错误
后端·rust·编程语言
techdashen18 小时前
绕过系统 ICMP:用 rawsock、Npcap 和 WMI 找到默认网卡
开发语言·arm开发·rust
小二·18 小时前
Rust 后端实战:高性能 Web 服务开发全链路
开发语言·前端·rust
island131419 小时前
【开源软件移植】把 RustDesk 的 Rust 核心搬到 HarmonyOS PC:一次 Native HAR 迁移实战记录
开发语言·rust·harmonyos
小二·19 小时前
Rust 爬虫与数据处理实战:大规模并发抓取 + 流式处理
开发语言·爬虫·rust
techdashen19 小时前
绕过 WMI:用 Rust 绑定 Win32 变长结构体和 UTF-16 字符串
开发语言·后端·rust