- 分布式文件系统
- 对象存储
- 存储
【免费下载链接】seaweedfs
SeaweedFS is a distributed storage system for object storage (S3), file systems, and Iceberg tables, designed to handle billions of files with O(1) disk access and effortless horizontal scaling.
导读
本文围绕仓库内 test/samba/README.md 及其配套脚本,系统讲解如何在 SeaweedFS FUSE 挂载点之上,通过 Sambasmbd导出 SMB 共享,并用smbclient驱动的两套测试脚本验证 SMB 文件操作与数据一致性。读完本文,你将掌握该集成测试套件的完整脉络——本地免 sudo 运行、Docker 容器化运行、功能测试与分布式锁/并发测试的执行逻辑,以及背后的-dlm(分布式锁管理)、FUSE 挂载、Samba 配置等关键机制。
测试目标与整体架构
该测试的核心思路是:把 SeaweedFS 的 FUSE 挂载当作普通本地目录,由 Sambasmbd将其导出为 SMB 共享,再用smbclient以 SMB 协议访问该共享,从而验证两条关键链路:
- SMB 文件操作(上传、下载、建目录、重命名、删除等)在 FUSE 挂载之上能否正确执行;
- 跨协议数据一致性——经 SMB 写入的文件能在 FUSE 挂载上读到完全一致的内容,反之亦然。
从源码结构看,测试目录 test/samba 下共有 9 个文件,职责划分如下:
| 文件 | 用途 |
|---|---|
| smb_tests.sh | SMB 功能测试套件,本地运行与容器运行共享 |
| lock_tests.sh | SMB 锁定/并发测试套件,本地运行与容器运行共享 |
| smb.conf.template | Samba 配置模板,运行时通过sed填充占位符 |
| run.sh | 本地运行器:weed mini+ 两个-dlm挂载 +smbd+ 两套测试,全部以当前用户身份运行在非特权端口 |
| entrypoint.sh | 容器入口:启动两个-dlmFUSE 挂载并运行smbd |
| run_inside_container.sh | 在容器内针对本地smbd运行两套测试 |
| Dockerfile | 在chrislusf/seaweedfs:e2e镜像之上添加 Samba |
| docker-compose.yml | master + volume + filer + samba 四个服务编排 |
整个套件由三份 bash 脚本构成运行主线,这里先给出全局流程概览:
本地: weed mini(单进程 master+volume+filer) ↓ weed mount -dlm → /mnt/seaweedfs(导出为 SMB 共享) weed mount -dlm → /mnt/seaweedfs2(仅用于分布式锁竞争) ↓ smbd 以非特权端口 4450 导出 mount/share ↓ smbclient 驱动 smb_tests.sh(功能) + lock_tests.sh(锁/并发)两个挂载点使用相同的 filer 路径(-filer.path=/),因此.../share在两端看到的是同一份数据;第二个挂载的唯一目的,就是在分布式锁测试中与 smbd 背后的挂载竞争同一文件。
Samba 配置:屏蔽不相关表面,聚焦数据完整性
smb.conf.template 是整个测试正确性的关键。它以占位符形式定义了运行时参数,run.sh 与 entrypoint.sh 分别用sed将其替换为实际路径:
| 占位符 | 含义 | 本地(run.sh) | 容器(entrypoint.sh) |
|---|---|---|---|
@SHARE_PATH@ | SMB 共享对应的文件系统路径 | ${MOUNT_DIR}/share(挂载点子目录) | /mnt/seaweedfs/share |
@STATE_DIR@ | Samba 自包含状态目录 | ${WORK_DIR}/samba | /var/lib/samba-test |
@SMB_PORT@ | smbd 监听端口 | 4450(非特权) | 445 |
@FORCE_USER@ | 共享强制用户 | 当前用户 | root |
配置中几个值得注意的设计点:
- 禁用 DOS 属性/xattr 映射与 oplocks:
ea support = no、store dos attributes = no、map archive/hidden/system/readonly = no,以及oplocks = no、level2 oplocks = no、kernel oplocks = no、posix locking = no。注释明确指出:SeaweedFS FUSE 挂载未实现 Samba 默认依赖的完整 xattr/DOS 属性面,开启会产生与数据完整性无关的NT_STATUS_NOT_SUPPORTED/EOPNOTSUPP错误; - 关闭打印子系统:
load printers = no、printing = bsd、printcap name = /dev/null、disable spoolss = yes,这是纯文件服务器测试的标准瘦身; - 自包含状态目录:private/state/cache/lock/pid/ncalrpc 全部指向测试工作目录,使 smbd 可以无 root 运行且退出后不留残留;
- 协议下限设为 SMB2:
server min protocol = SMB2,客户端则以-m SMB3连接(见下文smb()函数)。
功能测试套件:smb_tests.sh 的八步验证
smb_tests.sh 通过一个统一的smb()辅助函数执行smbclient命令:
smbclient "//${SMB_HOST}/${SMB_SHARE}" -p "${SMB_PORT}" \ -U "${SMB_USER}%${SMB_PASS}" -m SMB3 -c "$1"环境变量设计如下(均带默认值,SMB_USER/SMB_PASS必填):
| 变量 | 默认值 | 说明 |
|---|---|---|
SMB_HOST | 127.0.0.1 | Samba 主机 |
SMB_SHARE | seaweedfs | 共享名 |
SMB_PORT | 445 | smbd 端口 |
SMB_USER/SMB_PASS | 无(必填) | Samba 凭据 |
SHARE_FS_PATH | 空 | 共享在 FUSE 挂载上对应的目录;设置后额外执行跨协议一致性检查 |
测试分 8 步,每步输出[PASS]/[FAIL]并计数,最终汇总PASS/FAIL并以其退出码反映成败:
1. 连接与根目录列出:smb "ls"验证 SMB3 连接与共享枚举。
2. 1 MiB 上传/下载往返:head -c 1048576 /dev/urandom生成随机数据,put上传后用get下载,以md5sum比对两端内容;若设置了SHARE_FS_PATH,还会直接检查 FUSE 挂载上的roundtrip.bin与源文件 MD5 一致——即 SMB 写入在 FUSE 侧可见且内容相同。
3. 子目录操作:一条命令串mkdir docs; cd docs; put src nested.bin; ls完成建目录、进入、写入嵌套文件,并验证docs/nested.bin出现在 FUSE 挂载上。
4. 重命名:rename roundtrip.bin renamed.bin后重新get并校验内容;跨协议侧验证renamed.bin存在而旧名roundtrip.bin已消失。
5. 64 MiB 大文件往返:这一步是 SeaweedFS 特有的——64 MiB 会触发挂载端的 chunk 切分。从源码看,挂载的 chunk 上限由chunkSizeLimitMB控制,weed/command/mount.go 中其默认值为 2 MiB(“local write buffer size, also chunk large files”)。因此 64 MiB 文件必然跨越多个 chunk,往返校验同时验证了 chunk 切分、落盘与重组读取的正确性。
6. 递归上传目录树:构造tree/a/b/f3.txt三层目录结构,通过recurse ON; prompt OFF; mput tree递归上传,验证 FUSE 侧最深层的tree/a/b/f3.txt存在。
7. 跨协议反向读取:直接在 FUSE 挂载上写入from_fuse.txt,再用 SMBget取回并grep校验内容——验证 FUSE 侧写入对 SMB 客户端可读。
8. 删除:del/deltree清理文件与目录树,随后在 FUSE 侧断言全部消失(无SHARE_FS_PATH时退化为验证get已取不到被删文件)。
锁与并发测试套件:lock_tests.sh 的四个难题
lock_tests.sh 面向网络文件系统后端最难处理的锁定与并发场景,覆盖四组断言。
1. POSIX fcntl 字节区间锁(FUSE 挂载的 SetLk/GetLk):脚本内嵌一段 python3 程序,通过fcntl.lockf发出真实 POSIX 锁,用fork()建立父子进程竞争:
- 子进程持有
[0,100)独占锁期间,父进程尝试加冲突的独占锁必须被拒绝; - 非重叠区间
[200,300)必须可以被授予; - 子进程释放后,父进程重新获取
[0,100)必须成功。
这三个断言直接验证挂载对 FUSESetLk/GetLk操作的正确实现。
2. 跨挂载写协调(-dlm阻塞与交接):这是整个套件最精巧的部分。mount 2 通过 bash 的文件描述符exec 9>"file"保持一个文件处于打开写状态——即持有 DLM 锁;随后后台启动对该文件的 SMBput(走 mount 1)。要点在于:
- smbclient 显式使用长客户端超时
-t 120,以确保测试的是锁交接本身,而非 smbclient 默认约 20 秒的客户端超时; - 后台子 shell 必须
9>&-关闭继承的 fd 9,否则 SMB 写入进程会因自己继承的描述符持有 DLM 锁而自锁死锁,无法验证本应测试的交接过程。
断言顺序:sleep 4后put尚未返回 → 证明跨挂载写被阻塞;exec 9>&-释放后,20 秒有界轮询等待put完成 → 证明阻塞解除;最后get校验磁盘内容恰为 SMB 写者的载荷 → 证明正确交接。
3. 并发同文件写的数据完整性:一个 SMB 写者(mount 1,1 MiB 随机载荷)与一个直接写者(mount 2,文本载荷)并发竞争同一文件。DLM 将它们串行化,因此最终结果必须是两者之一的完整载荷,绝不能出现 torn mix(撕裂混合)。
4. 并发不同文件写:6 个 SMBput并发写入 6 个不同文件,全部完成后逐一get并以 MD5 校验,验证并发写不同文件全部成功且内容完整。
关于 DLM 语义,README 有一段重要说明值得原文保留:-dlm协调的是“写访问”——同一时刻只有一个挂载写一个文件,并保证写入不被撕裂。它并不保证哪个并发写者获胜,也不保证跨挂载读的即时收敛——持有者缓冲的数据在 close 时刷新,异步于锁的释放。当持有者关闭文件后,另一挂载的写者在约 1 秒内获得释放的锁并完成写入。
从实现侧佐证,weed/command/mount_common.go 将EnableDistributedLock与-dlm选项绑定,而 weed/command/mount.go 对-dlm的官方定义为:“跨挂载协调写入(同一时刻仅一个挂载写一个文件),并通过路由到持有者 filer 的方式在挂载间遵守 POSIX 咨询锁(flock/fcntl)”。这正是上面四组断言所验证的能力。
本地运行:免 sudo 的 weed mini 流水线
run.sh 将整个环境收敛为一个自包含流水线,全部进程以当前用户身份运行在非特权端口,无sudo需求。前置依赖为:weed在$PATH、fusermount3,以及 Samba 的smbd/smbclient/smbpasswd(Debian/Ubuntu 安装命令:apt-get install samba smbclient)。
test/samba/run.sh流水线四步及关键参数:
weed mini单进程集群:-dir数据目录、-filer.port=28888,显式关闭 S3、WebDAV 与 admin UI(-s3=false -webdav=false -admin.ui=false),启动后以/dev/tcp/127.0.0.1/28888探测端口就绪(60 次 × 0.5s 有界等待);- 两个
-dlmFUSE 挂载:核心参数为-filer=127.0.0.1:28888 -filer.path=/ -dirAutoCreate -dlm,以mountpoint -q探测挂载就绪(同有界等待);目录share创建在 mount 1 上,作为 SMB 共享的物理路径; - 启动 smbd:以
sed填充模板生成smb.conf,smbpasswd -a -s建立 SMB 用户(默认当前用户名 / 密码seaweedfs),smbd -F --no-process-group前台运行于端口 4450; - 顺序执行两套测试:功能套件传入
SHARE_FS_PATH=${SHARE_DIR}启用跨协议校验,锁套件传入MOUNT_SHARE与MOUNT2_SHARE两个挂载路径;任一失败都会记录返回码,最终以非零退出。
清理路径同样完备:trap cleanup EXIT INT TERM依次终止 smbd、两个挂载进程,fusermount3 -u卸载,终止weed mini,并把日志复制到固定路径/tmp/seaweedfs-samba-logs供 CI 上传为 artifacts。可通过环境变量覆盖关键参数:WEED_BIN、WORK_DIR、MOUNT_DIR、MOUNT2_DIR、DATA_DIR、LOG_DIR、FILER_PORT、SMB_PORT、SMB_USER、SMB_PASS等。
Docker 运行:与 CI 对齐的容器化方案
容器方案镜像了 CI 作业,需要/dev/fuse设备与SYS_ADMIN能力(compose 文件已提供)。docker-compose.yml 编排四个服务:master(-raftBootstrap)、volume、filer(三者基于chrislusf/seaweedfs:e2e镜像并通过 healthcheck 串联启动顺序),以及 samba 服务(基于 Dockerfile 在 e2e 镜像之上追加samba、smbclient、python3-minimal构建)。samba 服务授予SYS_ADMIN、挂载/dev/fuse、设置apparmor:unconfined,并以“两个挂载点就绪 + smbclient 可列出共享”作为健康检查。
# 先从仓库的 docker/ 目录构建基础 e2e 镜像 docker compose -f test/samba/docker-compose.yml up --wait docker compose -f test/samba/docker-compose.yml exec -T samba /run_inside_container.sh docker compose -f test/samba/docker-compose.yml down -v容器内行为与本地有两点差异,均由 entrypoint.sh 体现:
- 挂载参数多了
-allowOthers:smbd 以 root 运行(root 拥有挂载点),需允许其他用户访问挂载,对应模板中的force user = root; - SMB 用户为
smbtest(密码同),端口为默认 445。
run_inside_container.sh 则导出全部所需环境变量(SHARE_FS_PATH=/mnt/seaweedfs/share、MOUNT_SHARE/MOUNT2_SHARE分别指向两个挂载的 share 目录)后依次执行两套测试。
CI 触发规则与日志收集
CI 工作流.github/workflows/samba-integration.yml在以下路径变更时触发:weed/mount/**、weed/filer/**、test/samba/**。触发后执行:构建 e2e 镜像 → 在其上构建 Samba 测试镜像 → 拉起集群 → 运行测试套件 → 将服务器日志作为 artifacts 上传。这一触发范围也印证了该套件关注的核心面正是 FUSE 挂载层与 filer 元数据层。
关键机制总结与可复现要点
- 共享路径设计:共享指向挂载点的子目录(
.../share)而非挂载根,使运行器可以直接在 FUSE 侧验证 SMB 侧操作的结果,这是跨协议一致性断言成立的前提; - 两挂载点架构:第二挂载仅用于与 smbd 后端挂载竞争,两者经同一 filer 路径看到同一数据;
-dlm能力边界:协调写访问、防撕裂,但不保证胜者确定性与跨挂载读即时收敛;锁释放后约 1 秒内完成交接;- 测试面完整闭环:功能测试覆盖 SMB 基础操作与跨协议一致性,锁测试覆盖 POSIX 区间锁、跨挂载写协调、同文件并发完整性、异文件并发成功,全面覆盖网络文件系统后端的典型难点。
如需在本地复现,请确保weed可执行文件与 Samba 工具链就绪,直接运行 test/samba/run.sh;若要复现 CI 行为,则按上文 Docker 流程操作,并留意/dev/fuse与SYS_ADMIN两个硬性前置条件。
- 分布式文件系统
- 对象存储
- 存储
【免费下载链接】seaweedfs
SeaweedFS is a distributed storage system for object storage (S3), file systems, and Iceberg tables, designed to handle billions of files with O(1) disk access and effortless horizontal scaling.
相关推荐
AllData文件服务:分布式存储与管理
AllData文件服务:分布式存储与管理 引言:大数据时代的文件管理挑战 在当今数据爆炸的时代,企业每天产生海量的非结构化数据——文档、图片、视频、日志文件等。
大数据数据工程数据集成数据治理数据可视化后端前端FanControl 完全教程:一条温度曲线,让 Windows 电脑风扇从呼呼响到安静
FanControl 完全教程:一条温度曲线,让 Windows 电脑风扇从呼呼响到安静 FanControl 是一款免费开源的 Windows 风扇控制软件:
桌面应用智能硬件LaVague微服务集成测试:分布式系统的自动化验证
LaVague微服务集成测试:分布式系统的自动化验证 引言:微服务测试的痛点与解决方案 在当今分布式系统架构中,微服务(Microservices)以其独立部署
AI AgentGUI 自动化AI 应用大模型RAG
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考