一条数据的HBase之旅,简明HBase入门教程-开篇
741
2022-05-30
FastDFS概念
FastDFS是开源的轻量级分布式文件系统,实现文件管理, 主要功能:
文件存储
文件同步
文件访问(文件上传,文件下载)
解决了大容量存储和负载均衡的问题,特别适合以文件为载体的在线服务:相册网站,视频网站
FastDFS为互联网量身定制,充分考虑了冗余备份,负载均衡,线性扩容等机制,并注重高可用,高性能等指标,使用FastDFS可以很方便地搭建一套高性能的文件服务器集群提供文件上传,下载等服务
FastDFS文件系统架构
FastDFS服务端有两个角色:
-(tracker): 主要做调度工作,在访问上起负载均衡作用
-和存储节点都可以由一台服务器或多台服务器构成,-和存储节点中的服务器可以随时增加或下线而不会影响下线服务.
-中所有服务都是对等的,可以根据服务器的压力情况随时增加或减少
存储节点(storage): 存储文件,完成文件管理的所有功能
就是这样的存储
同步存储接口
提供存储接口
FastDFS同时对文件metadata进行管理,文件metadata是文件属性列表,可以包含多个键值对
文件metadata: 文件的相关属性,以键值对方式表示
为了支持大容量,存储节点采用分卷的组织方式
存储系统由一个卷或多个卷组成,卷与卷之间的文件是相互独立的,所有卷的文件容量累加就是整个存储系统的文件容量
一个卷可以由一台或多台存储服务器组成,一个卷下的存储服务器中文件都是相同的,卷中的多台服务器起到了冗余备份和负载均衡作用
在卷中增加服务器时,同步已有的文件由系统自动完成,同步完成后,系统自动将新增服务器切换到线上提供服务
当存储空间不足或即将耗尽时,可以动态添加卷,只需要增加一台或多台服务器,配置一个新的卷,这样扩大存储系统的容量
FastDFS 文件标识分为两部分:
卷名
文件名
高可用要有崩溃恢复的能力 服务集群要有同步的功能 否则就要有负载均衡
上传交互过程
client询问tracker上传到的storage,不需要附加参数
tracker返回一台可用的storage
client直接和storage通讯完成文件上传
client为使用FastDFS的调用方,client也是一台服务器,对tracker和对storage的调用均为服务器间的调用
下载交互过程
client询问tracker下载文件的storage,参数为文件标识(卷名和文件名)
tracker返回一台可用的storage
client直接和storage通讯完成文件下载
client为使用FastDFS的调用方,client也是一台服务器,对tracker和对storage的调用均为服务器间的调用
FastDFS结合Nginx
使用FastDFS部署分布式文件系统时,通过FastDFS的客户端API进行文件的上传,下载,删除等操作,同时通过FastDFS和HTTP服务器来提供HTTP服务.但是FastDFS的HTTP服务较为简单,无法提供负载均衡等高性能的服务.需要使用FastDFS的Nginx模块弥补这一缺陷
FastDFS通过tracker服务器,将文件放在storage服务器存储,但是同组之间的服务器需要复制文件,有延迟的问题,可以通过fastdfs-nginx-module可以重定向连接到源服务器取文件,避免客户端由于复制延迟的问题,出现错误
基于Docker安装FastDFS
环境准备:
libfastcommon: FastDFS分离出的一些公用函数包
FastDFS: FastDFS本体
fastdfs-nginx-module: FastDFS和nginx的关联模块
nginx: nginx1.15.4
创建工作目录:
在Linux中创建
/usr/local/docker/fastdfs/environment /usr/local/docker/fastdfs:用于存放docker-compose.yml配置文件及FastDFS数据卷 /usr/local/docker/fastdfs/environment:用于存放Dockerfile镜像配置文件及FastDFS所需环境
在 /usr/local/docker/fastdfs/environment目录中创建Dockerfile
# 更新数据源 WORKDIR /etc/apt RUN echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted universe multiverse' > sources.list RUN echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted universe multiverse' >> sources.list RUN echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted universe multiverse' > sources.list RUN echo 'deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse' > sources.list RUN apt-get update # 安装依赖 RUN apt-get install make gcc libpcre3-dev zliblg-dev --assume-yes # 复制工具包 ADD fastdfs-5.11.tar.gz /usr/local/src ADD fastdfs-nginx-module_v1.16.tar.gz /usr/local/src ADD libfastcommon.tar.gz /usr/local/src ADD nginx-1.15.4.tar.gz /usr/local/src # 安装libfastcommon WORKDIR /usr/local/src/libfastcommon RUN ./make.sh && ./make.sh install # 安装 FastDFS WORKDIR /usr/local/src/fastdfs-5.11 RUN ./make.sh && ./make.sh install # 配置FastDFS tracker ADD tracker.conf /etc/fdfs RUN mkdir -p /fastdfs/tracker # 配置FastDFS storage ADD storage.conf /etc/fdfs RUN mkdir -p /fastdfs/storage # 配置FastDFS客户端 ADD client.conf /etc/fdfs # 配置fastdfs-nginx-module ADD config /usr/local/src/fastdfs-nginx-modules/src # FastDFS与Nginx集成 WORKDIR /usr/local/src/nginx-1.13.6 RUN ./configure --add-module=/usr/local/src/fastdfs-nginx-module/src RUN make && make install ADD mod_fastdfs.conf /etc/fdfs WORKDIR /usr/local/src/fastdfs-5.11/conf RUN cp http.conf mime.types /etc/fdfs/ # 配置Nginx ADD nginx.conf /usr/local/nginx/conf COPY entrypoint.sh /usr/local/bin/ ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] WORKDIR / EXPOSE 8888 CMD ["/bin/bash"]
在/usr/local/docker/fastdfs/environment创建entrypoint.sh,创建完成的后要执行 chmod +x entrypoint.sh命令文件才可以使用
# !/bin/sh /etc/init.d/fdfs_trackerd start /etc/init.d/fdfs_storaged start /usr/local/nginx/sbin/nginx -g 'daemon off;'
相关配置文件
tracker.conf: FastDFS-配置,容器路径为:/etc/fdfs,修改:
base_path=/fastdfs/tracker
storage.conf: FastDFS存储节点配置,容器路径为:/etc/fdfs,修改:
base_path=/fastdfs/storage store_path0=/fastdfs/storage tracker_server=192.168.32.255:22122 http.server_port=8888
client.conf: FastDFS客户端配置,容器中路径为:/etc/fdfs,修改:
base_path=/fastdfs/tracker tracker_server=192.168.32.255:22122
config: fastdfs-nginx-module配置文件,容器中路径为:/usr/local/src/fastdfs-nginx-module/src,修改:
# 修改前 CORE_INCS="$CORE_INCS /usr/local/include/fastdfs /usr/local/include/fastcommon/" CORE_LIBS="$CORE_LIBS -L/usr/local/lib -lfastcommon -lfdfsclient" # 修改后 CORE_INCS="$CORE_INCS /usr/include/fastdfs /usr/include/fastcommon/" CORE_LIBS="$CORE_LIBS -L/usr/lib -lfastcommon -lfdfsclient"
mod_fastdfs.conf: fastdfs-nginx-module配置文件,容器中路径:/usr/local/src/fastdfs-nginx-module/src,修改:
connect_timeout=10 tracker_server=192.168.75.128:22122 url_have_group_name=true store_path0=/fastdfs/storage
nginx.conf: Nginx配置文件,容器中的路径为:/usr/local/src/nginx-1.15.4/conf,修改:
user root; worker_processes 1; events { worker_connections 1024; } http{ include mime.types; defaulte_type application/octet-stream; sendfile on; keepalive_timeout 65; server{ listen 8888; server_name localhost; location ~/group([0-9])/M00{ ngx_fastddfs_module; } error_page 500 502 503 504 /50x.html location = /50x.html { root html; } } }
启动容器
docker-compose.yml: 在/usr/local/docker/fastdfs文件夹中创建docker-compose.yml
version: '3.1' services: fastdfs: build: environment restart: always container_name: fastdfs volumes: - ./storage:/fastdfs/storage network_mode: host # 网络模式:主机模式--将所有端口映射到主机,Docker容器与宿主机共享端口,即端口一致
执行命令,使文件编译生效
docker-compose up -d
测试上传
交互式进入容器:
docker exec -it fastdfs /bin/bash
测试文件上传: 在/usr/bin目录中执行(第1个是二进制可执行文件客户端,第2个是客户端的客户端配置文件,第3个是需要上传的文件)
/usr/bin/fdfs_upload_file /etc/fdfs/client.conf /usr/local/src/fastdfs-5.11/INSTALL
服务器反馈上传地址: 文件的上传路径(非地址),通过在浏览器输入Ngnix的访问地址+文件上传路径即可访问服务器上的文件
group1/M00/00/00/wKliyyfhHHkjsio986777
测试Nginx访问: 通过在浏览器输入Ngnix的访问地址+文件上传路径即可访问服务器上的文件
http://192.168.32.255:8888/group1/M00/00/00/wKliyyfhHHkjsio986777
配置 FastDFS Java客户端
创建项目: 创建项目名为myshop-service-upload的服务提供者项目
安装FastDFS Java客户端
从github上git clone FastDFS项目代码:
git clone https://github.com/happyfish100/fastdfs-client-java.git
配置到本地仓库: 在项目目录的target包下有项目的jar文件
mvn clean install
将项目jar文件上传到Nexus中
在项目中添加依赖:
创建FastDFS工具类
定义文件存储服务接口:
package com.oxford.myshop.service.upload.fastdfs; public interface StorageService{ /** *上传文件 * *@param data 文件的二进制符 *@param extName 扩展名 *@return 上传成功后返回生成文件的id,失败则返回null */ public String upload(byte[] data,String extName); /** *删除文件 * *@param fileId 被删除的文件id *@return 删除成功后返回0,失败后返回错误代码 */ public int delete(String fileId); }
实现文件存储服务接口:
public class FastDFSStorageService implements StorageService,InitializingBean{ private static final Logger logger=LoggerFactory.getLogger(FastDFSStorageService.class); private TrackerClient trackerClient; @Value("${storage.fastdfs.tracker_server}") @Override public String upload(byte[] data,String extName){ TrackerServer trackerServer=null; StorageServer storageServer=null; StorageClient storageClient=null; try{ NameValuePair[] meta_list=null; // new NameValuePair[0] trackerServer=trackerClient.getConnection(); if(trackerServer==null){ logger.error("getConnection return null"); } storageServer=trackerClient.getStoreStorage(trackerServer); storageClient1=new StorageClient1(trackerServer,storageServer); String fileId=storageClient1.upload_file1(data,extName,meta_list); logger.debug("uploaded file <{}>",fileId); return fileId; }catch(Exception ex){ logger.error("Uploaded fail",ex); return null; }finally{ if(storageServer!=null){ try{ storageServer.close(); }catch(IOException e){ e.printStackTrace(); } } if(trackeServer!=null){ try{ trackeServer.close(); }catch(IOException e){ e.printStackTrace(); } } storageClient1=null; } } @Override public int delete(String fileId){ TrackerServer trackerServer=null; StorageServer storageServer=null; StorageClient storageClient=null; int index=fileId.indexOf('/'); String groupName=fileId.substring(0,index); try{ trackerServer=trackerClient.getConnection(); if(trackerServer==null){ logger.error("getConnection return null"); } storageServer=trackerClient.getStoreStorage(trackerServer,groupName); storageClient1=new StorageClient1(trackerServer,storageServer); int result=storageClient1.delete_file1(fileId); return result; }catch(Exception ex){ logger.error("Delete fail",ex); return 1; }finally{ ifreturn fileId; }catch(Exception ex){ logger.error("Uploaded fail",ex); return null; }finally{ if(storageServer!=null){ try{ storageServer.close(); }catch(IOException e){ e.printStackTrace(); } } if(trackeServer!=null){ try{ trackeServer.close(); }catch(IOException e){ e.printStackTrace(); } } storageClient1=null; } } @Override public void afterPropertiesSet() throws Exxception{ File confFile=File.createTempFile("fastdfs",".conf"); PrintWriter confWriter=new PrintWriter(new FileWriter(confFile)); confWriter.println("tracker_server="+trackerServer); confWriter.close(); ClientGlobal.init(confFile.getAbsolutePath()); confFile.delete(); TrackerGroup trackerGroup=ClientGlobal.g_tracker_group; trackerClient=new TrackerClient(trackerGroup) logger.info("Init FastDFS with tracker_server : {}",trackerServer); } }
文件存储服务工厂
public class StorageFactory implements FactoryBean
配置文件存储服务工厂类
/** * Java配置方式定义StorageFactory的bean,使其可以被依赖注入 */ @Configuration public classs FastDFSConfiguration{ @Bean public StorageFactory storageFactory(){ return new StorageFactory(); } }
创建FastDFS控制器
增加云配置: application.yml
# SpringBoot Application spring: application: name: myshop-service-upload # FastDFS Configuration fastdfs.base.url: htttp//192.168.32.255:8888/ storage: type: fastdfs fastdfs: tracker_server: 192.168.32.255:22122
控制器代码
@CrossOrigin(origins="*",maxAge=3600) @RestController public class UploadController{ @Value("${fastdfs.base.url}") private String FASTDFS_BASE_URL; @Autowired private StorageService storageService; @RequestMapping(value="upload",method=RequestMethod.POST) public Map
创建SpringBoot Application,运行执行分布式文件上传项目
Nginx 分布式
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。