FastDFS 启动与使用详解:分布式文件系统的快速入门

FastDFS 是一款开源的分布式文件系统,它主要解决了大文件的存储与负载均衡问题,非常适合用于海量文件的存储需求。本文将详细介绍如何启动和使用 FastDFS,包括启动追踪器、存储节点、客户端,以及如何进行文件上传下载与状态检测。

1. FastDFS 组件介绍

FastDFS 系统由三个核心组件组成:

  • Tracker Server(追踪器服务器):管理和调度客户端请求,负责任务分发和负载均衡。
  • Storage Server(存储服务器):负责文件的存储、同步和访问。
  • Client(客户端):通过追踪器和存储服务器进行文件的上传、下载等操作。

2. 启动 FastDFS 组件

2.1 启动 Tracker Server(追踪器服务器)

Tracker Server 是 FastDFS 系统的调度中心,必须首先启动。以下命令用于启动、关闭和重启追踪器服务器:

# 启动 Tracker Server
fdfs_trackerd /etc/fdfs/tracker.conf

# 关闭 Tracker Server
fdfs_trackerd /etc/fdfs/tracker.conf stop

# 重启 Tracker Server
fdfs_trackerd /etc/fdfs/tracker.conf restart

可以使用以下命令检查 Tracker Server 是否正常运行:

ps aux | grep fdfs_*
2.2 启动 Storage Server(存储服务器)

存储服务器是文件存储的核心组件,需在追踪器服务器启动后启动。以下是相关命令:

# 启动 Storage Server
fdfs_storaged /etc/fdfs/storage.conf

# 关闭 Storage Server
fdfs_storaged /etc/fdfs/storage.conf stop

# 重启 Storage Server
fdfs_storaged /etc/fdfs/storage.conf restart
2.3 启动 Client(客户端)

客户端用于与 FastDFS 系统进行交互,主要执行文件的上传和下载操作。以下是基本的上传和下载命令:

# 上传文件
fdfs_upload_file /etc/fdfs/client.conf <file_to_upload>

# 下载文件
fdfs_download_file /etc/fdfs/client.conf <file_id>

例如,上传文件后得到的字符串可能为:group1/M00/00/00/wKj3h1vC-PuAJ09iAAAHT1YnUNE31352.c,该字符串即为 file_id,用于后续的下载操作。

3. FastDFS 状态检测

为了确保系统的稳定性,定期监控 FastDFS 的状态是非常重要的。可以使用以下命令来监测系统的状态:

fdfs_monitor /etc/fdfs/client.conf

监测命令会显示 Storage Server 的状态信息,常见的状态包括:

  • INIT:初始化,尚未找到同步源服务器。
  • WAIT_SYNC:等待同步,已找到同步源服务器。
  • SYNCING:同步中。
  • DELETED:已删除,服务器已从集群中移除。
  • OFFLINE:离线状态。
  • ONLINE:在线状态,但尚不能提供服务。
  • ACTIVE:在线状态,已准备好提供服务。

了解这些状态可以帮助你快速诊断和处理系统问题。

4. File ID 详解

FastDFS 在上传文件后,会生成一个 file_id,该 file_id 包含了文件所在的组、虚拟目录和文件名等信息。

  • Group1:文件所属的存储组。如果系统中存在多个组,file_id 中的组名会动态变化。
  • M00:虚拟目录,与存储节点的实际路径相映射。
  • 00/00:文件在存储节点中的实际路径,这部分路径是可变的。
  • wKhS_VlrEfOAdIZyAAAJTOwCGr43848.md:文件名部分,采用 Base64 编码,包含源存储服务器 IP 地址、文件创建时间、文件大小、CRC32 校验码和随机数。

5. 文件上传与下载的代码实现

5.1 使用多进程方式实现

通过多进程和 exec 系列函数,可以在代码中实现文件的上传与下载。以下是简单的实现思路:

  1. 使用 pipe 函数创建管道,父进程和子进程之间通过管道通信。
  2. 在子进程中调用 execlp 函数执行 fdfs_upload_file 命令,并通过管道将结果传递给父进程。
  3. 父进程从管道中读取上传结果,并将其写入数据库或进行其他操作。
5.2 使用 FastDFS API 实现

另一种方法是直接使用 FastDFS 提供的 API 进行文件的上传和下载。通过编写 fdfs_upload_file.c 文件,调用 FastDFS 的接口,实现更灵活的文件操作。

/**
* Copyright (C) 2008 Happy Fish / YuQing
*
* FastDFS may be copied only under the terms of the GNU General
* Public License V3, which may be found in the FastDFS source kit.
* Please visit the FastDFS Home Page http://www.csource.org/ for more detail.
**/
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <errno.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "fdfs_client.h"
// #include "logger.h"
 
 
//加上const 明显就知道了这是一个传入的文件  fileID 是一个传出n参数
int upload_file(const char *confFile,const char *myFile,char *fileID)
{
	char group_name[FDFS_GROUP_NAME_MAX_LEN + 1];
	ConnectionInfo *pTrackerServer;
	int result;
	int store_path_index;
	ConnectionInfo storageServer;
	
	
	 
	if ((result=fdfs_client_init(confFile)) != 0)
	{
		return result;
	}
	pTrackerServer = tracker_get_connection();
	if (pTrackerServer == NULL)
	{
		fdfs_client_destroy();
		return errno != 0 ? errno : ECONNREFUSED;
	}
 
	*group_name = '\0';
	 
 	 if ((result=tracker_query_storage_store(pTrackerServer, \
	                &storageServer, group_name, &store_path_index)) != 0)
	{
		fdfs_client_destroy();
		fprintf(stderr, "tracker_query_storage fail, " \
			"error no: %d, error info: %s\n", \
			result, STRERROR(result));
		return result;
	}
 
	result = storage_upload_by_filename1(pTrackerServer, \
			&storageServer, store_path_index, \
			myFile, NULL, \
			NULL, 0, group_name, fileID);
	if (result == 0)
	{
		printf("%s\n", fileID);
	}
	else
	{
		fprintf(stderr, "upload file fail, " \
			"error no: %d, error info: %s\n", \
			result, STRERROR(result));
	}
 
	tracker_disconnect_server_ex(pTrackerServer, true);
	fdfs_client_destroy();
 
	return result;
}
 
 
 
//size fileID 对长度的描述 
int upload_file1(const char *confFlie,const char *uploadFile,char *fileID,int size)
{
 
     //创建管道
     int fd[2];
   int ret=pipe(fd);
 
   if(ret==-1){
     perror("pipe error");
     exit(0);
   }
 
   //创建子进程
   pid_t pid=fork();
 
 
     //子进程
   if(pid==0){
 
     //将new 重定向号old  将标准输出重定向到管道写的一段
     dup2(fd[1],STDOUT_FILENO);
 
     //关闭u读的a一顿
     close(fd[0]);
 
     execlp("fdfs_upload_file","xxx",confFlie,uploadFile,NULL);
     perror("execlp error");
 
   }
 
   else{
 
     //父进程 读ao管道 关闭写端
 
     close(fd[1]);
 
     char buf[1024];
     read(fd[0],fileID,size);
     
     //回收pid
     wait(NULL);
 
 
 
 
 
   }
 
 
  return 0;
}

main.c

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include <sys/types.h>
#include<string.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include<ctype.h>
#include<sys/stat.h>
#include "fdfs_upload_file.h"
 
 
int main(int argc,const char *argv[])
{
 
     char fileID[1024]={0};
     upload_file("/etc/fdfs/client.conf","main.c",fileID);
     printf("fileId:%s\n",fileID);
     printf("=================================\n");
     upload_file1("/etc/fdfs/client.conf","main.c",fileID,sizeof(fileID));
     printf("fileID: %s\n",fileID);
 
  return 0;
}
posted @ 2024-08-14 13:36  daligh  阅读(1130)  评论(0)    收藏  举报