ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

FastDFS在Ubuntu 24.04上的完整部署:从源码编译到Java客户端对接

FastDFS在Ubuntu 24.04上的完整部署:从源码编译到Java客户端对接 做中小规模文件服务选型的时候我碰到最多的问题不是“该不该用分布式”而是“到底用哪个”。如果目标是存图片、附件、音视频这类静态文件吞吐要求没到海量级别又不想背上 Hadoop 那套重型组件的运维负担我的第一选择通常是 FastDFS。它是阿里巴巴开源的轻量级分布式文件系统核心只有 Tracker 和 Storage 两个角色部署链路极短配合 Nginx 提供 HTTP 下载再用 Java 客户端做上传管理就能搭出一套最小化但完整的分布式文件服务。这篇文章基于 Ubuntu 24.04 完整走一遍从源码编译、Tracker/Storage 配置、Nginx 接入到 Java 客户端对接参数、命令、踩坑点一次讲清楚。适合手里有文件存储需求但还没到必须上 HDFS、对象存储级别的团队参考。1. 整体链路拆解FastDFS 为什么适合“最小化”1.1 Tracker 与 Storage 的分工关系FastDFS 的架构在分布式文件系统里算非常清爽的。它没有独立元数据库Tracker 只负责调度把所有集群状态放在内存里Storage 负责实际文件存储按组划分组内多台机器互为副本。客户端上传文件时流程是先连 Tracker 问“我该把文件传到哪台 Storage”Tracker 根据剩余空间、组内负载返回一个可用的 Storage 地址客户端再直连这台 Storage 完成数据写入。整个过程中 Tracker 不碰文件内容所以并发压力很小512MB 内存的机器就能跑得很舒服。我用一个生活化类比帮助理解Tracker 是前台调度员只负责告诉你在哪个仓库有货架、走哪个门进Storage 是真正的仓库管理员文件由他亲手放到货架上。同一个车间的多台仓库同一个 group会互相复制保证一台挂了另一台还有货。这种“调度与存储分离”的设计让 FastDFS 的横向扩容非常直观加 Storage 进组、加新组、调整 Tracker 就能完成。1.2 为什么不是 HDFS、MinIO 或 Ceph很多人一听到“分布式文件系统”就想到 HDFS但我一般会劝他们先别急着上。HDFS 在设计上是为大数据离线批处理服务的NameNode 内存吃紧、小文件存储效率低、在线随机读性能一般而且依赖 ZooKeeper 和完整运维体系。Ceph 强大但部署和运维复杂度对一个小团队来说完全是另一种量级。MinIO 适合需要 S3 接口的云原生场景如果只是内网附件存储它偏重了。我整理了一个简单的选型对比方案核心定位优点明显的坑部署成本HDFS大数据离线分析底座海量吞吐、生态完善小文件弱、运维重、内存占用高高Ceph统一存储平台块/文件/对象全覆盖组件多、调优复杂高MinIO对象存储S3 兼容、云原生友好功能多但相对重中FastDFS轻量分布式文件系统部署简单、性能足够、成本低不支持随机修改、断点续传低如果你的需求就是“存文件、取文件、删除文件”对一致性要求没有强到金融级事务那么夸张FastDFS 的性价比非常突出。这也是我坚持在中小项目里推荐它的原因你不需要为了存几张图片就去维护一堆守护进程。1.3 最小化部署拓扑单机验证、生产两机器起步本文搭建的环境是一台 Ubuntu 24.04 服务器Tracker 和 Storage 部署在同一台机器上只建一个 group。这样一个最小化系统验证完所有链路后可以直接复制到生产环境做横向扩展。生产上我更推荐两台机器起步Tracker 单独放在一台配置很低的机器上Storage 和 Nginx 放在同一台机器。之所以让 Nginx 和 Storage 同机是因为 fastdfs-nginx-module 在下载文件时会直接读 Storage 本地磁盘避免跨机转发如果 Nginx 在另一台机器还需要额外做一层网络传输性能会打折扣还引入新的故障点。单机部署的好处是排查问题省事日志、端口、文件路径全在一台机器上适合第一次接触这套技术栈的人建立完整认知。等你想清楚扩容方向后再拆开也不迟。2. 安装前准备编译 FastDFS 前需要处理的环境问题2.1 安装基础依赖FastDFS 和 fastdfs-nginx-module 都是 C 写的Nginx 编译也需要一些基础库。先把依赖装齐免得编译到一半才发现缺东西sudo apt update sudo apt install -y build-essential libtool libpcre3-dev libssl-dev zlib1g-dev其中 build-essential 提供 gcc、make 等编译工具libpcre3-dev 是 Nginx 解析正则需要的libssl-dev 和 zlib1g-dev 留给 Nginx 的 SSL 和 gzip 模块。虽然最小化部署不一定马上用 HTTPS但预留编译参数会方便很多。提示如果使用的是最小化安装的 Ubuntu先确认 curl、wget、netstat 这些常用工具存在后面排查问题都会用到。2.2 编译 libfastcommonlibfastcommon 是 FastDFS 的基础依赖库必须先装好。下载 release 包编译安装cd /usr/local/src wget https://github.com/happyfish100/libfastcommon/releases/download/V1.0.43/libfastcommon-1.0.43.tar.gz tar -zxvf libfastcommon-1.0.43.tar.gz cd libfastcommon-1.0.43 ./make.sh sudo ./make.sh install编译安装结束后确认共享库是否已经放在系统库路径下。Ubuntu 上一般会装到/usr/lib个别版本可能装到/usr/local/lib。如果后面启动 FastDFS 报找不到libfastcommon.so执行sudo ldconfig刷新缓存或者临时加export LD_LIBRARY_PATH/usr/lib:/usr/local/lib看看能不能解决。2.3 编译安装 FastDFS 本体FastDFS 源码包同样从 GitHub Releases 下载。我用的是 V6.06 版本建议至少用 V6.x 之后的版本旧版本在 Ubuntu 24.04 的高版本 GCC 下编译容易报类型错误cd /usr/local/src wget https://github.com/happyfish100/fastdfs/releases/download/V6.06/fastdfs-6.06.tar.gz tar -zxvf fastdfs-6.06.tar.gz cd fastdfs-6.06 ./make.sh sudo ./make.sh install编译过程会输出不少 warning只要没有 Error一般没影响。安装完成后检查这些二进制是否生成/usr/bin/fdfs_trackerdTracker 启动程序/usr/bin/fdfs_storagedStorage 启动程序/usr/bin/fdfs_upload_file命令行上传工具/usr/bin/fdfs_monitor集群状态监控工具同时conf/目录下有 tracker.conf、storage.conf、client.conf 三个模板文件这是后面配置的基础。2.4 Ubuntu 24.04 编译报错的避坑方向Ubuntu 24.04 默认 GCC 编译器版本比较高老的 FastDFS 源码在编译时经常出现 incompatible pointer type 这类类型不匹配错误。这本质上是老代码没有适配新编译器不是你的操作失误。最省事的解决办法是换用较新的 release 版本源码而不是去一点点改源码。如果实在只能用旧版本再去搜索社区补丁。我的经验是凡是编译环节出问题先检查版本组合不要急着怀疑环境。3. 核心配置实战Tracker 与 Storage 的参数解析与启动验证3.1 把模板配置文件放到 /etc/fdfsFastDFS 默认从/etc/fdfs读取配置先把模板复制过去sudo mkdir -p /etc/fdfs sudo cp /usr/local/src/fastdfs-6.06/conf/tracker.conf /etc/fdfs/ sudo cp /usr/local/src/fastdfs-6.06/conf/storage.conf /etc/fdfs/ sudo cp /usr/local/src/fastdfs-6.06/conf/client.conf /etc/fdfs/client.conf 在这条链路里不是给业务客户端用的而是给 fdfs_upload_file、fdfs_monitor 这些命令工具用的。后面验证集群状态和上传文件都离不开它。3.2 Tracker 配置base_path 和 store_lookup 是重点打开 tracker.conf核心参数如下参数推荐值说明port22122Tracker 监听端口客户端和 Storage 都通过它寻址base_path/data/fastdfs/trackerTracker 日志和数据存放目录必须提前创建connect_timeout30连接超时秒network_timeout60网络超时秒传大文件建议调大store_lookup2选择 group 的策略0 轮询、1 按指定组、2 剩余空间优先store_groupgroup1store_lookup 为 1 时可指定组名reserve_storage_space10%Storage 预留空间比例防止磁盘被写满http.server_port8080Tracker 自带 HTTP 端口本文用不到这里最容易忽略的是base_path需要手动创建。FastDFS 启动时不会自动 mkdir目录不存在时进程很容易启动失败而且日志不够显眼。提前建好sudo mkdir -p /data/fastdfs/tracker启动并检查sudo fdfs_trackerd /etc/fdfs/tracker.conf start netstat -tlnp | grep 22122如果端口没起来打开/data/fastdfs/tracker/logs/trackerd.log看报错。绝大多数启动失败都能在日志里找到直接原因。3.3 Storage 配置真正落盘的地方是 store_path0打开 storage.conf关键参数如下参数推荐值说明group_namegroup1存储组名同组内互为副本port23000Storage 监听端口base_path/data/fastdfs/storageStorage 的日志目录需提前创建store_path_count1存储路径数量store_path0/data/fastdfs/storage_data文件实际存储根目录tracker_server127.0.0.1:22122向哪个 Tracker 注册http.server_port8888Storage 自带 HTTP 端口本次用不到有一个概念必须理解store_path0下会自动生成data目录真正的文件会落在data/00/00/这种两级哈希子目录下。所以上传返回的group1/M00/00/00/xxx.jpg中M00对应的就是data目录。这个映射关系到后面配 Nginx 非常关键。创建目录并启动sudo mkdir -p /data/fastdfs/storage /data/fastdfs/storage_data sudo fdfs_storaged /etc/fdfs/storage.conf start启动后看/data/fastdfs/storage/logs/storaged.log确认 Storage 已经向 Tracker 成功注册。3.4 检查集群状态fdfs_monitor 是核心体检工具编辑 client.conftracker_server127.0.0.1:22122 base_path/data/fastdfs/client创建目录后运行sudo mkdir -p /data/fastdfs/client fdfs_monitor /etc/fdfs/client.conf输出里重点关注 Storage 状态是否为 ACTIVE、存储容量和可用空间是否正确。看到 Storage 数量为 1 且状态正常说明 Tracker 和 Storage 之间的通信已经通了。这个工具在后续排查问题时是第一个要看的比乱猜日志高效得多。一个小技巧配合 watch 实时刷新状态方便观察文件同步进度watch -n 2 fdfs_monitor /etc/fdfs/client.conf | grep -A 5 Storage 13.5 命令行上传文件走通第一个最小闭环准备一个测试文件执行fdfs_upload_file /etc/fdfs/client.conf /tmp/test.png正常会返回类似group1/M00/00/00/wKi8xGZfpfWAT7zTAAAAANFm17A123.png这时去/data/fastdfs/storage_data/data/00/00/下面能看到实际文件。返回的这一串group1/M00/...是文件的唯一标识后面 Nginx 的访问地址和 Java 客户端存储的都是它。注意如果上传时提示tracker_query_storage_store fail, error code: 2基本可以断定 Storage 没有成功注册到 Tracker优先检查 storaged.log 和 fdfs_monitor 输出而不是怀疑 client.conf。4. Nginx 集成把文件存储映射成 HTTP 访问4.1 为什么加了 FastDFS 还需要 NginxFastDFS 本身带了简单的 HTTP 能力Tracker 和 Storage 都有 http.server_port 配置但生产环境没人直接用它的内置 HTTP 服务。原因很现实功能太弱没有缓存、没有鉴权、没法上 HTTPS、并发性能也就那样。主流做法是在 Storage 所在机器部署 Nginx加载 fastdfs-nginx-module让请求进来后由模块直接映射到本地磁盘文件并返回。这样 Nginx 的高性能能力、HTTPS、限速、防盗链都可以顺手用上。有一点需要提前理解fastdfs-nginx-module 不是 apt 包而是 Nginx 的第三方模块必须编译进 Nginx所以这节的整个流程核心就是“编译一个带模块的 Nginx”。4.2 获取并调整 fastdfs-nginx-module从 GitHub 获取源码cd /usr/local/src git clone https://github.com/happyfish100/fastdfs-nginx-module.git模块编译前要调整它的 config 文件否则 Nginx configure 阶段会找不到 FastDFS 的头文件。进入模块的 src 目录把 config 文件里所有%FIRST_PATH%替换成/usr/local/include/fastdfscd fastdfs-nginx-module/src sed -i s#%FIRST_PATH%#/usr/local/include/fastdfs#g config前提是/usr/local/include/fastdfs下面确实有 FastDFS 安装后生成的头文件。如果编译 libfastcommon 和 FastDFS 时安装路径不一样这里要按实际路径调整。4.3 编译安装 Nginx这里我强烈建议用 Nginx 1.20.x 系列。fastdfs-nginx-module 的更新节奏跟不上 Nginx 新版本的节奏用最新版 Nginx 去编译老模块经常碰到源码兼容问题换成 1.20.2 基本能绕开cd /usr/local/src wget https://nginx.org/download/nginx-1.20.2.tar.gz tar -zxvf nginx-1.20.2.tar.gz cd nginx-1.20.2 ./configure --prefix/usr/local/nginx --add-module/usr/local/src/fastdfs-nginx-module/src --with-http_ssl_module make -j4 sudo make install编译过程中如果出现类型不匹配之类的报错先确认自己用的是不是 1.20.x绝大多数版本兼容问题都可以通过固定这个 Nginx 版本解决不要想着去给模块源码打补丁那样反而浪费时间。4.4 配置 mod_fastdfs.conf 与 Nginx server 块模块编译完成后把模块自带的配置模板复制到 /etc/fdfssudo cp /usr/local/src/fastdfs-nginx-module/src/mod_fastdfs.conf /etc/fdfs/关键参数如下参数推荐值说明connect_timeout10连接 Tracker 的超时时间tracker_server127.0.0.1:22122指向 Trackerstorage_server_port23000模块回源到 Storage 的端口必须和 storage.conf 保持一致group_namegroup1当前 Storage 所在组url_have_group_nametrueURL 中是否包含 group1 前缀store_path_count1与 storage.conf 对应store_path0/data/fastdfs/storage_data与 storage.conf 对应修改 nginx.conf在 server 块中加入location /group1/M00 { ngx_fastdfs_module; }网上很多教程会在 location 里写 alias实际跑下来这条 alias 完全可以不写因为 ngx_fastdfs_module 在收到请求后会根据 group_name、url_have_group_name、store_path0 自行换算物理路径。如果你照抄带 alias 的配置反而出现 404删掉 alias只保留模块指令就行。启动并测试sudo /usr/local/nginx/sbin/nginx -t sudo /usr/local/nginx/sbin/nginx curl http://127.0.0.1/group1/M00/00/00/xxx.png能正常输出文件内容说明 Nginx 下载通道已经打通。4.5 内置 HTTP 与 Nginx 模块怎么选再回答一个反复被问的问题storage.conf 里不已经有 http.server_port 吗为什么还要 Nginx方式优点缺点Storage 自带 HTTP零配置就能用无缓存、无鉴权、性能一般Nginx fastdfs-nginx-module高性能、可扩展 HTTPS/限速/防盗链需要编译安装结论很明确除非只是做技术验证生产环境一律用 Nginx 模块。编译一次的成本很低后面扩展 HTTPS、加代理、做缓存都方便何必把自己的文件通道绑死在最简单的内置 HTTP 上。5. Java 客户端对接上传下载删除的完整实操5.1 客户端选型与依赖引入Java 侧有两类常见的 FastDFS 客户端一类是官方 fastdfs-client-javaAPI 贴近 FastDFS 原生概念适合任何框架不在 Spring 体系内也能用另一类是社区封装版 fastdfs-client核心优势是集成 Spring Boot 方便自带连接池和自动配置。如果你使用 Maven推荐先用社区封装版快速跑通dependency groupIdcom.github.tobato/groupId artifactIdfastdfs-client/artifactId version1.27.2/version /dependency如果更想贴近原生 API可以用官方仓库自己构建一次git clone https://github.com/happyfish100/fastdfs-client-java.git cd fastdfs-client-java mvn install -DskipTests下面代码我基于官方客户端来写因为它的 API 最能表达 FastDFS 本身的上传流程。5.2 初始化客户端与属性文件创建 fdfs_client.properties放在 classpath 根目录tracker_server127.0.0.1:22122 base_path/data/fastdfs/client代码里初始化ClientGlobal.initByProperties(fdfs_client.properties);这里有个很容易踩的问题base_path 在 Java 进程运行的服务器上必须真实存在否则初始化直接抛 IOException。很多新手把 base_path 当成一个随便写写的逻辑路径服务端没建目录结果一启动就报错。5.3 上传文件的完整代码示例上传流程分三步连接 Tracker 获取连接、拿 Storage 客户端、上传得到文件 ID。import org.csource.fastdfs.*; public class FastDFSUploader { public static void main(String[] args) throws Exception { ClientGlobal.initByProperties(fdfs_client.properties); TrackerClient trackerClient new TrackerClient(); TrackerServer trackerServer trackerClient.getConnection(); if (trackerServer null) { throw new RuntimeException(get tracker server connection failed); } StorageServer storageServer null; StorageClient1 storageClient new StorageClient1(trackerServer, storageServer); String localFile /tmp/test.png; String fileExt png; String fileId storageClient.upload_file1(localFile, fileExt, null); System.out.println(upload success, fileId fileId); trackerServer.close(); } }upload_file1返回的 fileId 其实就是 Nginx 访问 URL 的后半段比如group1/M00/00/00/xxx.png。业务数据库只需要存这一个字符串下载时拼上 Nginx 域名就能访问。这是 FastDFS 使用体验里非常舒服的一点文件标识就是一条短字符串没有复杂的目录树对象。5.4 下载、查询与删除的代码套路拿到 fileId 后其他操作都很直观// 下载文件返回字节数组 byte[] content storageClient.download_file1(fileId); // 查询文件信息拿到大小、时间、CRC FileInfo fileInfo storageClient.get_file_info1(fileId); // 删除文件返回 0 表示成功 int result storageClient.delete_file1(fileId);需要说明的是这些方法签名来自官方客户端社区封装版 API 名可能不同但核心逻辑完全一样你手里只要有 fileId就能做下载、查询、删除三件事。下载时注意如果文件比较大download_file1一次性把整个文件装进 byte[] 会占内存生产级实现应该用流式方式下载或者干脆让前端直接指向 Nginx 下载应用层只做鉴权和重定向。5.5 Java 端生产经验几个实践下来很重要的经验TrackerServer 连接用完必须 close。官方客户端没有自动放回池子的概念不 close 会导致连接泄漏最终把 Tracker 的连接数吃满。多 Tracker 场景下属性文件里的 tracker_server 可以用逗号分隔多个地址客户端会自动做故障切换。上传前先处理文件尤其是图片压缩后再传。FastDFS 擅长存静态文件不代表适合当无限容量的对象存储用。下载路径优先让浏览器直接请求 Nginx不要在 Java 应用里把文件流再转一次否则大文件下载会把应用内存打爆。6. 常见问题排查与避坑实录6.1 安装与编译阶段的典型问题编译安装阶段的报错90% 出在依赖和版本组合上现象原因处理./make.sh 提示找不到 gccbuild-essential 未安装sudo apt install build-essential编译 FastDFS 时找不到 libfastcommon依赖库没装好或路径不对重新编译安装 libfastcommonldconfig 刷新编译 Nginx 时报类型不匹配fastdfs-nginx-module 与 Nginx 版本不兼容换 Nginx 1.20.2configure 提示找不到 pcre/ssl依赖缺包安装 libpcre3-dev、libssl-dev编译阶段的坑最不值得花时间深挖基本都能通过换版本解决不要和源码死磕。6.2 Tracker 与 Storage 启动注册阶段服务起不来的最常见原因就是目录和端口现象原因处理启动后进程秒退base_path 目录不存在mkdir -p 对应目录再看日志日志写权限不足/data 目录属主不对chown 或 chmod 调整Storage 一直 OFFLINEtracker_server 地址写错、端口不通核对 storage.conf测试 22122 连通性fdfs_monitor 看不到 StorageStorage 启动失败看 storaged.log 日志上传返回 error code 2Tracker 没有可用 Storage回到上一步排查 Storage 注册这里想强调一个排查思路FastDFS 的日志其实写得很清楚问题是你愿不愿意去看。很多人上来就改配置、重启反复试了几次毫无头绪其实打开/data/fastdfs/storage/logs/storaged.log一眼就能看出原因。6.3 Nginx HTTP 访问阶段HTTP 访问 404 是出现频率最高的问题我总结下来主要两个原因第一URL 里有没有 group 前缀和url_have_group_name配置不一致第二location 里画蛇添足写了 alias。前者改配置后者删 alias。现象原因处理curl 404URL 前缀与配置不一致确认是否带 /group1核对 url_have_group_namenginx: [emerg] unknown directive ngx_fastdfs_module模块没有编译进 Nginx重新 configure 并 make install下载时返回错误mod_fastdfs.conf 里的 store_path0 与 storage.conf 不一致统一 store_path0 路径总之HTTP 这层只要记住“模块负责解析路径映射”这一条很多困惑都会消失。6.4 Java 客户端对接阶段Java 端的问题大多不是代码问题而是环境没通现象原因处理ClientGlobal.init 找不到配置文件路径写错或文件没在 classpath使用绝对路径确认文件名connect to tracker server fail22122 端口不通先 curl 测试再查防火墙上传报“没有可用 Storage”Storage 离线先用 fdfs_monitor 确认集群状态上传后文件访问不了fileId 拼错或 Nginx 未配好单独 curl 测试 fileIdJava 端排查有个原则先用命令行工具验证服务端是好的再去怀疑代码。如果你 fdfs_upload_file 能传、curl 能下载那 Java 端的问题基本就是配置路径或连接管理的问题。6.5 用 systemd 管住进程避免重启后手工拉起手动start方式在服务器重启后会失效生产环境要用 systemd 管理。创建/etc/systemd/system/fdfs-tracker.service[Unit] DescriptionFastDFS Tracker Server Afternetwork.target [Service] Typeforking ExecStart/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf start ExecStop/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf stop Restarton-failure RestartSec5 [Install] WantedBymulti-user.targetStorage 同理把二进制换成 fdfs_storaged、配置换成 storage.conf然后sudo systemctl daemon-reload sudo systemctl enable fdfs-tracker fdfs-storage sudo systemctl start fdfs-tracker fdfs-storage这样重启机器后服务自动拉起不用再手动敲命令。最后说两个我反复栽过的细节。第一所有 base_path 和 storage_path 目录一定要在启动前手工建好FastDFS 不会替你 mkdir目录不存在的时候它可能看起来是“启动成功”实际进程已经退出日志又不显眼排查起来最耗时间。第二版本别追求新FastDFS 本体、fastdfs-nginx-module、Nginx 三者之间没有严格的官方兼容矩阵但经过大量生产验证的组合就是 FastDFS 6.x、fastdfs-nginx-module 1.2x、Nginx 1.20.x这套组合我在多台机器上跑过编译和运行都很稳。要做最小化系统照着这条链路一步步来基本一次就能通。
返回列表