fastdfs分布式文件系统之与dubbo整合实现分布式服务接口

fastdfs是开源的轻量级分布式文件系统,它提供了java版本的client api。通过client API可以实现对文件的上传、追加、下载、删除等功能。

为了避免每个应用都配置fasdtfs参数、读取配置文件、调用client api获取trackerServer和StorageServer进行上传、下载、删除等操作及返回结果的

处理。所以采用与dubbo整合,提供分布式服务接口,来简化其它服务和应用的文件操作处理,同时提高代码的复用性。

1.总体结构

如图,总共分为fastdfs-api、fastdfs-consumer、fastdfs-provider三个工程。

fastdfs-api:对外提供的接口、dto的定义;

fastdfs-provider:调用fastdfs java client api对外提供的上传、下载、删除等接口实现以及对外暴露dubbo接口;

fastdfs-consumer:调用远程接口,测试上传、下载、删除功能;

其中fastdfs-consumer、fastdfs-provider需要依赖fastdfs-api的jar包。

2.fastdfs-api

对外提供的接口、dto的定义,下图是代码结构图:

从图中我们可以看到resultDto、UploadFileDto等dto。其中resultDto是上传、删除、下载返回结果dto,里面包含了结果状态、错误信息及文件地址等等信息

UploadFileDto是上传文件时需传入的dto里面包含了文件的字节数组、文件后缀名、文件访问类型等等信息。

在enums包里面的LinkType是一个枚举类,定义连接类型。里面定义了内网访问和外网访问两个类型。

在exception包里面的AppException,内部异常类定义。

service包里面的CommonUploadFileService接口,里面定义了上传和删除功能的接口,代码如下:

/**
 *
 * @ClassName: CommonUploadFileService
 * @Description: 公共文件上传业务逻辑层接口
 * @author mr_smile [email protected]
 *
 */
public interface CommonUploadFileService {
	/**
	 * 上传文件
	 *
	 * @param uploadFileDto
	 *            上传文件dto
	 * @return
	 */
	public ResultDto uploadFile(UploadFileDto uploadFileDto)
			throws AppException;

	/**
	 * 删除远程文件
	 *
	 * @param filePath
	 *            文件远程地址
	 * @return
	 */
	public void deleteFile(String filePath) throws AppException;

}

3.fastdfs-provider

调用fastdfs java client api对外提供的上传、下载、删除等接口实现以及对外暴露dubbo接口,在该工程中需要导入fastdfs-api的包。

代码结构如下图所示:

图中我们看到有exception、pool和impl等包及相关的配置文件。

包代码介绍:

在exception中,ERRORS枚举类主要是对在调用接口时可能出现的错误的定义,代码如下:

public enum ERRORS {

	PARAMETER_IS_NULL("21001", "必填参数为空", "必填参数为空"),

	FASTDFS_CONNECTION_FAIL("21002", "连接fastdfs服务器失败", "文件上传异常,请重试"),

	WAIT_IDLECONNECTION_TIMEOUT("21003", "等待空闲连接超时", "连接超时,请重试"),

	NOT_EXIST_GROUP("21004", "文件组不存在", "文件组不存在"),

	UPLOAD_RESULT_ERROR("21005", "fastdfs文件系统上传返回结果错误", "文件上传异常,请重试"),

	NOT_EXIST_PORTURL("21006", "未找到对应的端口和访问地址", "文件上传异常,请重试"),

	SYS_ERROR("21007", "系统错误", "系统错误"),

	FILE_PATH_ERROR("2108", "文件访问地址格式不对","文件访问地址格式不对"),

	DELETE_RESULT_ERROR("21009", "fastdfs文件系统删除文件返回结果错误", "文件删除异常,请重试"),

	NOT_EXIST_FILE("21010", "文件不存在", "文件不存在");

	/** 错误码 */
	String code;

	/** 错误信息,用于日志输出,便于问题定位 */
	String message;

	/** 错误提示,用于客户端提示 */
	String descreption;

	ERRORS(String code, String message) {
		this.message = message;
		this.code = code;
	}

	ERRORS(String code, String message, String descreption) {
		this.message = message;
		this.code = code;
		this.descreption = descreption;
	}

	public AppException ERROR() {
		return new AppException("FASTDFS", this.code, this.message,
				this.descreption);
	}

	public AppException ERROR(String descreption) {
		return new AppException("FASTDFS", this.code, this.message,
				descreption);
	}
}

pool包中的类主要实现连接池,提高程序的性能,在之前的代码中有所介绍。

impl包中的CommonUploadFileServiceImpl类上传和删除功能的接口的实现,代码如下:

/**
 * 公共上传文件服务接口实现类
 *
 * @author mr_smile
 *
 */
@Service("commonUploadFileService")
public class CommonUploadFileServiceImpl implements CommonUploadFileService {

	/** 日志 */
	private final Logger log = Logger
			.getLogger(CommonUploadFileServiceImpl.class);

	/** fastdfs工具类 */
	@Autowired
	private FastDfsUtil fastDfsUtil;

	/**
	 * 上传文件
	 *
	 * @param uploadFileDto
	 *            上传文件dto
	 * @return
	 */
	@Override
	public ResultDto uploadFile(UploadFileDto uploadFileDto)
			throws AppException {

		/** 日志标识 */
		String logId = UUID.randomUUID().toString();
		log.info("[上传文件(uploadFile)][" + logId + "][prams:uploadFileDto="
				+ uploadFileDto.toString() + "]");

		try {

			/** 判断参数是否为空 */
			vlidParamIsNull(uploadFileDto, logId);

			/** 调用工具类上传 */
			ResultDto result = fastDfsUtil.upload(uploadFileDto);

			log.info("[上传文件(uploadFile)-返回结果][" + logId
					+ "][results:resultDto=" + result.toString() + "]");

			return result;

		} catch (AppException e) {

			log.error("[上传文件(uploadFile)][" + logId + "][异常:" + e + "]");
			throw e;

		}

	}

	/**
	 * 删除fastdfs服务器中文件
	 *
	 * @param filePath
	 *            文件远程地址
	 * @return
	 */
	public void deleteFile(String filePath) throws AppException {

		/** 日志标识 */
		String logId = UUID.randomUUID().toString();
		log.info("[ 删除文件(deleteFile)][" + logId + "][parms:filePath="
				+ filePath + "]");
		try {
			if (StringUtils.isBlank(filePath)) {
				throw ERRORS.PARAMETER_IS_NULL.ERROR();
			}

			/** 解析文件路径 */
			String[] results = CommonUtils.parseFilePath(filePath, logId);

			/** 删除文件 */
			fastDfsUtil.deleteFile(results[0], results[1]);

		} catch (AppException e) {
			log.error("[ 删除文件(deleteFile)][" + logId + "][异常:" + e + "]");
			throw e;

		}
	}

	/**
	 *
	 * @Description: 验证上传方法参数是否为空
	 * @param uploadFileDto
	 * @param logId
	 *
	 */
	public void vlidParamIsNull(UploadFileDto uploadFileDto, String logId)
			throws AppException {

		log.info("[验证上传方法参数是否为空(vlidParamIsNull)][" + logId
				+ "][prams:uploadFileDto=" + uploadFileDto.toString() + "]");

		if (null == uploadFileDto || uploadFileDto.getFileBytes() == null
				|| null == uploadFileDto.getFileExtName()) {
			throw ERRORS.PARAMETER_IS_NULL.ERROR();
		}

	}
}

ServiceMainTest类设置dubbo参数及加载spring容器,代码如下:

/**
 *
 * @ClassName: ServiceMainTest
 * @Description: TODO(这里用一句话描述这个类的作用)
 * @author mr_smile [email protected]
 *
 */
public class ServiceMainTest {

	public static void main(String[] args) throws Exception {
		// 设在dubbo参数
		System.setProperty("dubbo.application.name", "payment-fastdfs");
		System.setProperty("dubbo.registry.address",
				"zookeeper://192.168.6.41:2181");
		System.setProperty("dubbo.protocol.port", "8080");
		// 加载spring容器
		@SuppressWarnings("resource")
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
				"classpath:applicationContext-provider.xml");
		context.start();
		System.out.println("Press any key to exit.");
		System.in.read();
	}

}

配置文件介绍:

applicationContext-provider.xml:对外暴露接口

<import resource="classpath*:applicationContext.xml"/>
    <dubbo:protocol name="hessian"/>
	<dubbo:service ref="commonUploadFileService" interface="com.fastdfs.service.CommonUploadFileService" timeout="1200000"/>
	applicationContext.xml:对bean、参数文件的定义:
	<bean id="propertyConfigurer"
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<list>
				<value>classpath:property.properties</value>
			</list>
		</property>
	</bean>
	<bean name="connectionPool" class="com.fastdfs.pool.FastDfsUtil" init-method="init">
		<property name="minPoolSize" value="${minPoolSize}" />
		<property name="maxPoolSize" value="${maxPoolSize}" />
		<property name="waitTimes" value="${waitTimes}" />
	</bean>
	<!-- 具体的实现bean -->
	<context:annotation-config />
	<context:component-scan base-package="com.fastdfs.*" />

fastdfs_client.conf对fastdfs所需参数的定义:

connect_timeout = 10
	network_timeout = 30
	charset = UTF-8
	http.anti_steal_token = no
	tracker_server = ip1:22122,ip2:22122
	secret_key="";

property.properties对组、端口、访问地址、连接池等相关配置:

	#内网组名
INTRANET_GROUP=group2
#外网组名
OUTERNET_GROUP=group1
#虚拟访问地址
LINEK_URL=http://www.xxx.com
#内网端口
LINKE_INTRANET_PORT=800
#外网端口
LINKE_OUTERNET_PORT=801
#连接池最大连接数
maxPoolSize=30
#等待时间(单位:秒)
waitTimes=400
#连接池最小连接数
minPoolSize=20

4.fastdfs-consumer

调用远程接口,测试上传、下载、删除功能。

MainTest类测试调用远程dubbo接口进行上传,上传成功后,线程睡眠2秒后执行删除操作。代码如下:

public static void main(String[] args) {
		try {
			ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
					new String[] { "applicationConsumer.xml" });
			CommonUploadFileService commonUploadFileService = (CommonUploadFileService) context
					.getBean("commonUploadFileService");
			File file = new File("D:\\data\\1.jpg");
			UploadFileDto udto = new UploadFileDto();
			try {
				byte[] bytes = MainTest.getByte(file);
				udto.setFileBytes(bytes);
				udto.setFileExtName("jpg");
				udto.setLinkType(LinkType.INTRANET);
				//上传文件
				ResultDto dto = commonUploadFileService.uploadFile(udto);
				System.out.println("上传:filePath:" + dto.getFilePath());
				Thread.sleep(2000);
				//删除文件
				commonUploadFileService.deleteFile(dto.getFilePath());

			} catch (AppException e) {
				System.out.println(e.toString());
			} catch (Exception e) {
				e.printStackTrace();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	public static byte[] getByte(File file) throws Exception {
		byte[] bytes = null;
		if (file != null) {
			InputStream is = new FileInputStream(file);
			int length = (int) file.length();
			if (length > Integer.MAX_VALUE) // 当文件的长度超过了int的最大值
			{
				System.out.println("this file is max ");
				return null;
			}
			bytes = new byte[length];
			int offset = 0;
			int numRead = 0;
			while (offset < bytes.length
					&& (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
				offset += numRead;
			}
			// 如果得到的字节长度和file实际的长度不一致就可能出错了
			if (offset < bytes.length) {
				System.out.println("file length is error");
				return null;
			}
			is.close();
		}
		return bytes;
	}
}

配置文件applicationConsumer.xml,需调用的远程接口bean的定义。配置如下:

  <dubbo:application name="consumer-of-helloworld-app" />
      <!-- 使用multicast广播注册中心暴露发现服务地址    -->

    <dubbo:registry protocol="hessian" address="zookeeper://192.168.6.41:2181" timeout="60000" /> 

      <!-- 生成远程服务代理,可以和本地bean一样使用demoService -->   

    <dubbo:reference id="commonUploadFileService" interface="com.fastdfs.service.CommonUploadFileService" retries="0" timeout="100000"/>
    <dubbo:reference id="commonDowenloadFileService" interface="com.fastdfs.service.CommonDownloadFileService" retries="0" timeout="60000"/>      

    </beans> 

在dubbo中默认使用的protocol为dubbo,在这种方式下,只能上传2M以内的文件,为了能解决传输大文件,那么需改为使用hessian协议。

上面的demo是全部是拷贝所有的jar包放入到工程里面的,在实际的开发中建议采用maven。hessian的依赖配置如下:

<dependency>
			<groupId>com.caucho</groupId>
			<artifactId>hessian</artifactId>
			<version>4.0.7</version>
		</dependency>
		<dependency>
			<groupId>org.mortbay.jetty</groupId>
			<artifactId>jetty</artifactId>
			<version>6.1.22</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.mortbay.jetty</groupId>
			<artifactId>jsp-2.1-jetty</artifactId>
			<version>6.1.22</version>
			<scope>provided</scope>
		</dependency>

注:所有代码已打包上传到我的资源库,有需要的可以前往下载。地址:http://download.csdn.net/detail/mr_smile2014/9629476

---------------------------------------------------------------------------版权声明-----------------------------------------------------------------------------------------------

版权声明:本文为博主原创文章,未经博主允许不得转载。本文地址:http://blog.csdn.net/mr_smile2014/article/details/52526065

时间: 2024-12-28 00:39:46

fastdfs分布式文件系统之与dubbo整合实现分布式服务接口的相关文章

一些流行的分布式文件系统(Hadoop、Lustre、MogileFS、FreeNAS、FastDFS、GoogleFS)

1.故事的起源 时间过的很快,距离上一次项目的大规模升级和调整虽然已经过去了几年,但是总感觉就发生在昨天,但是系统已经再次需要进行扩展.数据规模的扩大化,运行条件的复杂化,运维保障体系的升级化,原来有不少内容都需要调整,使用一种合适的分布式文件系统已经进入我们的视野. 在网上找了一些资料,也请了一些业内的专家座谈和调研,我们最终选择的是分布式文件系统是Hadoop,顺便也把一些其他的调研的系统也记录下,将来要使用也可以作为一个参考. 当前比较流行的分布式文件系统包括:Hadoop.Lustre.

当下流行的分布式文件系统阅览

当下流行的分布式文件系统阅览 对数种分布式文件系统的简单介绍 本文对目前数种分布式文件系统进行简单的介绍.当前比较流行的分布式文件系统包括:Lustre.Hadoop.MogileFS.FreeNAS.FastDFS.NFS.OpenAFS.MooseFS.pNFS.以及GoogleFS. Lustre(www.lustre.org) lustre是一个大规模的.安全可靠的,具备高可用性的集群文件系统,它是由SUN公司开发和维护.该项目主要的目的就是开发下一代的集群文件系统,可以支持超过1000

常见分布式文件系统

常见的分布式文件系统有,GFS.HDFS.Lustre .Ceph .GridFS .mogileFS.TFS.FastDFS等.各自适用于不同的领域.它们都不是系统级的分布式文件系统,而是应用级的分布式文件存储服务. Google学术论文,这是众多分布式文件系统的起源==================================Google File System(大规模分散文件系统)MapReduce (大规模分散FrameWork)BigTable(大规模分散数据库)Chubby(分

各种分布式文件系统简介

from:http://elf8848.iteye.com/blog/1724382 常见的分布式文件系统有,GFS.HDFS.Lustre .Ceph .GridFS .mogileFS.TFS.FastDFS等.各自适用于不同的领域.它们都不是系统级的分布式文件系统,而是应用级的分布式文件存储服务. Google学术论文,这是众多分布式文件系统的起源 ================================== Google File System(大规模分散文件系统) MapRed

当下流行的分布式文件系统大阅兵

摘自http://www.lupaworld.com/portal.php?mod=view&aid=205722&page=all 本文对目前数种分布式文件系统进行简单的介绍.当前比较流行的分布式文件系统包括:Lustre.Hadoop.MogileFS.FreeNAS.FastDFS.NFS.OpenAFS.MooseFS.pNFS.以及GoogleFS. Lustre(www.lustre.org) lustre是一个大规模的.安全可靠的,具备高可用性的集群文件系统,它是由SUN公司

分布式文件系统元数据服务模型[转]

随着非结构化数据的爆炸,分布式文件系统进入了发展的黄金时期,从高性能计算到数据中心,从数据共享到互联网应用,已经渗透到数据应用的各方各面.对于大多数分布式文件系统(或集群文件系统,或并行文件系统)而言,通常将元数据与数据两者独立开来,即控制流与数据流进行分离,从而获得更高的系统扩展性和I/O并发性.因而,元数据管理模型显得至关重要,直接影响到系统的扩展性.性能.可靠性和稳定性等.存储系统要具有很高的Scale-Out特性,最大的挑战之一就是记录数据逻辑与物理位置的映像关系即数据元数据,还包括诸如

分布式文件系统:原理、问题与方法

本地文件系统如ext3,reiserfs等(这里不讨论基于内存的文件系统),它们管理本地的磁盘存储资源.提供文件到存储位置的映射,并抽象出一套文件访问接口供用户使用.但随着互联网企业的高速发展,这些企业对数据存储的要求越来越高,而且模式各异,如淘宝主站的大量商品图片,其特点是文件较小,但数量巨大:而类似于youtube,优酷这样的视频服务网站,其后台存储着大量的视频文件,尺寸大多在数十兆到数吉字节不等.这些应用场景都是传统文件系统不能解决的.分布式文件系统将数据存储在物理上分散的多个存储节点上,

【整理学习Hadoop】H D F S 一个分布式文件系统

Hadoop分布式文件系统(HDFS)被设计成适合运行在通用硬件(commodity hardware)上的分布式文件系统.它和现有的分布式文件系统有很多共同点.但同时,它和其他的分布式文件系统的区别也是很明显的.HDFS是一个高度容错性的系统,适合部署在廉价的机器上.HDFS能提供高吞吐量的数据访问,非常适合大规模数据集上的应用.HDFS放宽了一部分POSIX约束,来实现流式读取文件系统数据的目的.HDFS在最开始是作为Apache Nutch搜索引擎项目的基础架构而开发的.HDFS是Apac

【整理学习HDFS】Hadoop Distributed File System 一个分布式文件系统

Hadoop分布式文件系统(HDFS)被设计成适合运行在通用硬件(commodity hardware)上的分布式文件系统.它和现有的分布式文件系统有很多共同点.但同时,它和其他的分布式文件系统的区别也是很明显的.HDFS是一个高度容错性的系统,适合部署在廉价的机器上.HDFS能提供高吞吐量的数据访问,非常适合大规模数据集上的应用.HDFS放宽了一部分POSIX约束,来实现流式读取文件系统数据的目的.HDFS在最开始是作为Apache Nutch搜索引擎项目的基础架构而开发的.HDFS是Apac