关于fastdfs:解密FastDFS的安装及部署实战篇

前言天猫、淘宝等购物网站,海量的商品图片和视频,是如何存储的?当用户访问量大时,又如何保障下载速度?分布式文件系统就是用来解决这些问题的。 那么分布式文件系统该如何应用呢?别急,明天袁老师就会率领大家来学习这些十分实用的技能: 分布式文件系统概述支流的分布式文件系统的介绍重点介绍FastDFS架构把握FastDFS的装置和配置FastDFS概述1.分布式文件系统分布式文件系统(Distributed File System)是一个软件/软件服务器,此软件能够用来治理在多个服务器节点中的文件(这些服务器节点通过网络相连并形成一个宏大的文件存储服务器集群,即这些服务器节点都是用来存储文件资源的,且用DFS来治理这些文件)。而传统文件系统与分布式文件系统的比照,有如下区别: 通过比照,咱们会发现传统文件系统存在如下毛病: 若用户数量多,则IO操作会很频繁 则对磁盘的拜访压力会较大; 若磁盘故障,则可能会造成数据的失落; 一个磁盘的存储容量无限。 2.支流的分布式文件系统2.1 HDFSHadoop Distributed File System,Hadoop分布式文件系统。这是一个高容错的零碎,适宜部署到便宜的机器上,能提供高吞吐量的数据拜访,非常适合大规模数据利用。HDFS采纳主从构造,一个HDFS是由一个name节点和N个data节点组成。name节点贮存元数据,一个文件宰割成N份存储在不同的data节点上。 2.2 GFSGoogle File System,可扩大的分布式文件系统,用于大型的,分布式的,对大量数据进行拜访的利用。GFS能够运行于便宜的一般硬件上,能够提供容错性能,它能够给大量的用户提供总体性能较高的服务。GFS采纳主从构造,一个GFS集群由一个master和大量的chunkserver(分块服务器)组成,一个文件被宰割若干块,扩散贮存到多个分块server中。 2.3 FastDFSFastDFS由淘宝资深架构师余庆编写并开源,应用C语言编写而成。FastDFS为互联网量身定制,充分考虑了冗余备份、负载平衡、线性扩容等机制,并重视高可用、高性能等指标。应用FastDFS可能很容易搭建出一套高性能的文件服务器集群,实现文件上传、下载等服务。 HDFS和GFS都是通用的文件系统,他们的长处是开发体验好,然而零碎的复杂度较高,性能也个别。相比之下,专用的分布式文件系统体验差,然而复杂度低,性能也高。尤其是FastDFS,特地适宜图片、小视频等小文件。因为FastDFS对文件是不宰割的,所以没有文件合并的开销。并且FastDFS网络通信应用Socket,速度也较快。 基于FastDFS的诸多长处,所以接下来咱们就重点给大家介绍FastDFS的应用。 FastDFS架构FastDFS架构包含Tracker Server和Storage Server。客户端申请Tracker Server进行文件上传、下载,通过Tracker Server调度最终由Storage Server实现文件上传和下载。 Tracker Server作用是负载平衡和调度,通过Tracker Server在文件上传时能够依据一些策略找到Storage Server提供文件上传服务。能够将Tracker称为追踪服务器或调度服务器。 Storage Server作用是文件存储,客户端上传的文件最终存储在Storage服务器上,Storage Server没有实现本人的文件系统而是利用操作系统的文件系统来管理文件。能够将Storage称为存储服务器。 Tracker集群FastDFS集群中的Tracker Server能够有多台,Tracker Server之间是互相平等关系同时提供服务,Tracker Server不存在单点故障。客户端申请Tracker Server采纳轮询形式,如果申请的Tracker无奈提供服务则换另一个Tracker。Storage集群Storage集群采纳了分组存储形式。Storage集群由一个或多个组形成,集群存储总容量为集群中所有组的存储容量之和。一个组由一台或多台存储服务器组成,组内的Storage Server之间是平等关系,不同组的Storage Server之间不会互相通信,同组内的Storage Server之间会相互连接进行文件同步,从而保障同组内每个Storage上的文件完全一致的。一个组的存储容量为该组内存储服务器容量最小的那个,由此可见组内存储服务器的软硬件配置最好是统一的。采纳分组存储形式的益处是灵便、可控性较强。比方上传文件时,能够由客户端间接指定上传到的组也能够由Tracker进行调度抉择。一个分组的存储服务器拜访压力较大时,能够在该组减少存储服务器来裁减服务能力(纵向扩容)。当零碎容量有余时,能够减少组来裁减存储容量(横向扩容)。 Storage状态收集Storage Server会连贯集群中所有的Tracker Server,定时向他们报告本人的状态,包含磁盘残余空间、文件同步情况、文件上传下载次数等统计信息。文件上传流程 客户端上传文件后存储服务器将文件ID返回给客户端,此文件ID用于当前拜访该文件的索引信息。文件索引信息包含:组名,虚构磁盘门路,数据两级目录,文件名。 组名文件上传后所在的Storage组名称,在文件上传胜利后由Storage服务器返回,须要客户端自行保留。 虚构磁盘门路Storage配置的虚构门路,与磁盘选项store_path*对应。如果配置了store_path0则是M00,如果配置了store_path1则是M01,以此类推。 数据两级目录Storage服务器在每个虚构磁盘门路下创立的两级目录,用于存储数据文件。 文件名与文件上传时不同。是由存储服务器依据特定信息生成,文件名蕴含:源存储服务器IP地址、文件创建工夫戳、文件大小、随机数和文件拓展名等信息。 文件下载流程 Tracker依据申请的文件门路即文件ID来疾速定义文件,比方申请下边的文件: 以上申请处理过程如下: 通过组名Tracker可能很快的定位到客户端须要拜访的存储服务器组是group1,并抉择适合的存储服务器提供客户端拜访。存储服务器依据文件存储“虚构磁盘门路”和“数据两级目录”能够很快定位到文件所在目录,并依据文件名找到客户端须要拜访的文件。理解了FastDFS的运行原理之后,接下来咱们就来开始进行FastDFS的装置及配置过程吧。 FastDFS装置及配置 1.FastDFS装置1.1 装置gcc应用yum命令装置gcc和gcc-c++,编译时须要应用。 [root@user ~]# yum install -y gcc gcc-c++ ...

April 11, 2023 · 2 min · jiezi

关于fastdfs:FastDFS配置Nginx访问

FastDFS配置Nginx拜访FastDFS分布式文件系统装置和配置_亲测胜利 下载相干依赖软件包yum -y install wget make zlib zlib-devel gcc-c++ libtool openssl openssl-develwget http://nginx.org/download/nginx-1.10.2.tar.gztar -xzvf nginx-1.10.2.tar.gz装置Nginxcd nginx-1.10.2./configure --prefix=/data/apps/nginx-download \ --pid-path=/data/logs/nginx-download/nginx.pid \ --lock-path=/data/apps/nginx-download/nginx.lock \ --error-log-path=/data/logs/nginx-download/error.log \ --http-log-path=/data/logs/nginx-download/access.log \ --http-client-body-temp-path=/data/temps/nginx-download/client_body_temp \ --http-proxy-temp-path=/data/temps/nginx-download/proxy_temp \ --http-fastcgi-temp-path=/data/temps/nginx-download/fastcgi_temp \ --http-uwsgi-temp-path=/data/temps/nginx-download/uwsgi_temp \ --http-scgi-temp-path=/data/temps/nginx-download/scgi_temp \ --with-http_stub_status_module \ --with-http_realip_module \ --with-http_ssl_module makemake installNginx配置拜访FastDFSvim /data/apps/nginx-download/conf/nginx.conf upstream fdfs_group1 { server 192.168.0.2:9999; server 192.168.0.3:9999;}upstream fdfs_group2 { server 192.168.0.4:9999; server 192.168.0.5:9999;} location /group1 { proxy_pass http://fdfs_group1; } location /group2 { proxy_pass http://fdfs_group2; }启动Nginxmkdir -p /data/temps/nginx-download/client_body_temp ...

January 1, 2023 · 1 min · jiezi

关于fastdfs:实现fastdfs防盗链功能

1、背景咱们能够通过fastdfs实现一个分布式文件系统,如果咱们的fastdfs部署在外网,那么任何一个人晓得了咱们的上传接口,那么它就能够文件的上传和拜访。那么咱们如何阻止别人拜访咱们fastdfs服务器上的文件呢?此处就须要应用fastdfs的防盗链性能。 2、实现原理fastdfs的防盗链是通过token机制来实现的。当咱们开启防盗链性能后,须要在url后减少2个额定的参数token和ts。token和ts的生成都是须要在服务端。 2.1 开启防盗链vim /etc/fdfs/http.conf # true 示意开启防盗链http.anti_steal.check_token = true# token的过期工夫,单位为秒http.anti_steal.token_ttl = 60# 密钥,不可透露,用于生成tokenhttp.anti_steal.secret_key = thisisasecuritykey# 当图片回绝拜访后,显示的图片,此图片须要可拜访,不然可能会呈现问题http.anti_steal.token_check_fail = /data/fastdfs/401.jpghttp.anti_steal.token_check_fail 指定的图片须要可拜访,否则可能会呈现问题 2.2 重启 nginx/usr/local/nginx/sbin/nginx -s reload 2.3 Java代码生成token1、token生成规定token = md5(文件ID+私钥+工夫戳) 文件ID:不能蕴含group group1/M00/00/00/wKh5iWNBl7-AKvj1AAAwWD4VeAg577.jpg`须要替换成`M00/00/00/wKh5iWNBl7-AKvj1AAAwWD4VeAg577.jpg私钥:须要和 /etc/fdfs/http.conf 中的 http.anti_steal.secret_key 值统一工夫戳:单位秒 2、java生成token/** * 生成token * * @param fileId the filename return by FastDFS server,不能含有组 * @param timestampSecond 工夫戳 单位秒 * @return token * @throws NoSuchAlgorithmException */ private String generatorToken(String fileId, Long timestampSecond) throws NoSuchAlgorithmException { // 须要去掉 group fileId = fileId.substring(fileId.indexOf("/") + 1); byte[] bsFilename = fileId.getBytes(StandardCharsets.UTF_8); byte[] bsTimestamp = timestampSecond.toString().getBytes(StandardCharsets.UTF_8); // thisisasecuritykey 须要和 /etc/fdfs/http.conf 中的 http.anti_steal.secret_key 值统一 byte[] bsKey = "thisisasecuritykey".getBytes(StandardCharsets.UTF_8); byte[] buff = new byte[bsFilename.length + bsKey.length + bsTimestamp.length]; System.arraycopy(bsFilename, 0, buff, 0, bsFilename.length); System.arraycopy(bsKey, 0, buff, bsFilename.length, bsKey.length); System.arraycopy(bsTimestamp, 0, buff, bsFilename.length + bsKey.length, bsTimestamp.length); return md5(buff); } public static String md5(byte[] source) throws NoSuchAlgorithmException { char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5"); md.update(source); byte tmp[] = md.digest(); char str[] = new char[32]; int k = 0; for (int i = 0; i < 16; i++) { str[k++] = hexDigits[tmp[i] >>> 4 & 0xf]; str[k++] = hexDigits[tmp[i] & 0xf]; } return new String(str); }3、测试3.1 带正确token拜访 ...

October 9, 2022 · 1 min · jiezi

关于fastdfs:SpringBoot整合fastdfs

1、背景在前一节中,咱们搭建了一个单机版的fastdfs服务,此处咱们将fastdfs与springboot进行整合,实现文件的上传和下载。 2、整合步骤2.1、引入依赖<dependency> <groupId>com.github.tobato</groupId> <artifactId>fastdfs-client</artifactId> <version>1.27.2</version></dependency>2.2、引入fastdfs配置fdfs: so-timeout: 2000 # 读取工夫 connect-timeout: 1000 # 连贯超时工夫 thumb-image: # 生成缩略图 height: 150 # 缩略图高度 width: 150 # 缩略图宽度 tracker-list: # tracker 服务器地址 - 192.168.121.137:22122 web-server-url: http://192.168.121.137:8888/ # storage 服务器上nginx的地址 pool: # 可参考 ConnectionPoolConfig #从池中借出的对象的最大数目(配置为-1示意不限度) max-total: -1 #获取连贯时的最大期待毫秒数(默认配置为5秒) max-wait-millis: 5000 #每个key最大连接数 key配置的是连贯服务端的地址(IP+端口)连贯状况,如果有连贯不够用的状况能够调整以上参数 max-total-per-key: 50 #每个key对应的连接池最大闲暇连接数 max-idle-per-key: 10 #每个key对应的连接池最小闲暇连接数 min-idle-per-key: 5 #向调用者输入“连贯”资源时,是否检测有效性 test-on-borrow: true2.3 编写文件上传和下载接口package com.huan.fastdfs.controller;import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;import com.github.tobato.fastdfs.domain.fdfs.MetaData;import com.github.tobato.fastdfs.domain.fdfs.StorePath;import com.github.tobato.fastdfs.domain.proto.storage.DownloadByteArray;import com.github.tobato.fastdfs.service.FastFileStorageClient;import lombok.AllArgsConstructor;import lombok.extern.slf4j.Slf4j;import org.apache.commons.io.Charsets;import org.apache.commons.io.FileUtils;import org.apache.commons.io.FilenameUtils;import org.apache.commons.io.IOUtils;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.*;import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.net.URLEncoder;import java.util.ArrayList;import java.util.HashSet;import java.util.List;import java.util.Set;/** * fastdfs 文件上传和下载控制器 * @author huan.fu * @date 2022/10/8 - 20:24 */@RestController@AllArgsConstructor@RequestMapping("fdfs")@Slf4jpublic class FastdfsController { private final FastFileStorageClient fastFileStorageClient; private final FdfsWebServer fdfsWebServer; /** * 上传文件 */ @PostMapping("uploadFile") public List<String> uploadFile(MultipartFile file) throws IOException { String fileName = file.getOriginalFilename(); // 获取文件扩展名 String extension = FilenameUtils.getExtension(fileName); // 文件元数据信息 Set<MetaData> metaData = new HashSet<>(4); metaData.add(new MetaData("fileName",fileName)); // 上传文件 StorePath storePath = fastFileStorageClient.uploadImageAndCrtThumbImage(file.getInputStream(), file.getSize(), extension, metaData); log.info("文件上传门路:[{}]",storePath.getFullPath()); String viewPath = fdfsWebServer.getWebServerUrl() + storePath.getFullPath(); log.info("可拜访门路:[{}]",viewPath); extension = FilenameUtils.getExtension(viewPath); String xthumbPath = viewPath.replace("." + extension, "")+"_150x150."+extension; log.info("缩略图门路:[{}]",xthumbPath); List<String> result = new ArrayList<>(3); result.add(viewPath); result.add(xthumbPath); result.add(storePath.getFullPath()); return result; } /** * 下载文件 */ @GetMapping("download") public void downloadFile(String filePath, HttpServletResponse response) throws IOException { log.info("须要下载的文件:[{}]",filePath); String group = filePath.substring(0, filePath.indexOf("/")); String path = filePath.substring(filePath.indexOf("/") + 1); Set<MetaData> metadata = fastFileStorageClient.getMetadata(group, path); String fileName = metadata.iterator().next().getValue(); byte[] bytes = fastFileStorageClient.downloadFile(group, path, new DownloadByteArray()); response.setContentType("application/octet-stream"); response.addHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fileName, Charsets.UTF_8.displayName())); IOUtils.write(bytes,response.getOutputStream()); }}2.4 测试文件上传从上图中能够,实现了文件的上传和缩略图的生成。 ...

October 8, 2022 · 2 min · jiezi

关于fastdfs:centos7上单机安装fastdfs609

1、背景最近因为某些起因接触到了分布式存储,而像阿里云的OSS等都是须要付费的,那么有没有收费的呢?fastdfs就是一个收费的,此处记录一下如何搭建一个单机版的 fastdfs 环境。 2、fastdfs的一些常识2.1 fastdfs的特点分组存储,灵便简洁对等构造,不存在单点文件ID由FastDFS生成,作为文件拜访凭证。FastDFS不须要传统的name server和风行的web server无缝连接,FastDFS已提供apache和nginx扩大模块大、中、小文件均能够很好反对,反对海量小文件存储反对多块磁盘,反对单盘数据恢复反对雷同文件内容只保留一份,节俭存储空间存储服务器上能够保留文件附加属性下载文件反对多线程形式,反对断点续传2.2 架构图 2.2.1 client 介绍客户端,即文件上传或下载的服务器,也就是咱们本人我的项目部署的服务器。 2.2.2 tracker-server 介绍tracker-server是跟踪服务器,次要起调度作用。负责管理所有 storage server的元数据信息,比方:storage ip、port、group等信息。每个storage server在启动的时候,会向tracker server连贯,上报本人的元数据信息,并与之放弃周期性的心跳。tracker-server之间通常不会互相通信2.2.3 storage-server 介绍storage-server是存储服务器,次要用来存储各种文件。storage-server是以Group为单位,每个Group内能够有多台storage server,同一个组内多个storage server为互为备份关系。每个Group中的机器的存储倡议配置成一样大,否则以这个Group内容量最小的storage为准。由storage server被动向tracker server报告状态信息2.3 fastdfs须要装置的软件依赖库备注libfatscommon根底库-fastdfs分离出来的公共函数libserverframe根底库-网络框架库FastDFSfastdfs本地fastdfs-nginx-modulefastdfs与nginx整合模块nginxnginx2.4 为什么须要fastdfs-nginx-module其实这个次要是因为,同一个group中存在多个storage server,而多个storage server之间会存在文件同步,那么可能就会呈现 同步提早 问题。 比方:咱们存在2台storage server,别离是 storageA 和 storageB。 FastDFS通过Tracker服务器,将文件放入到了storageA服务器存储。上传胜利后将 文件ID 返回给客户端。此时FastDFS存储集群机制会将这个文件同步到同组存储storageB,在文件还没有复制实现的状况下,客户端如果用这个文件ID在storageB上取文件,就会呈现文件无法访问的谬误。而fastdfs-nginx-module能够重定向文件连贯到源服务器取文件,防止客户端因为同步提早导致的文件无法访问谬误。 2.5 fastdfs的一些材料fastdfs 源码地址 https://github.com/happyfish100/fastdfs官方论坛 http://bbs.chinaunix.net/forum.php?mod=forumdisplay&fid=240&filter=typeid&typeid=424fastdfs 配置文件解释 http://bbs.chinaunix.net/thread-1941456-1-1.htmlfastdfs ppt介绍 http://bbs.chinaunix.net/thread-1958475-1-1.htmlfastdfs faq http://bbs.chinaunix.net/thread-1920470-1-1.html3、fastdfs软件装置3.1 前置条件3.1.1 依赖库装置yum install git gcc gcc-c++ make automake autoconf libtool pcre pcre-devel zlib zlib-devel openssl-devel -y3.1.2 fastdfs源码所在目录[[email protected] fastdfs]# pwd/opt/fastdfs[[email protected] fastdfs]# lsfastdfs-6.09.tar.gz fastdfs-nginx-module-1.23.tar.gz libfastcommon-1.0.61.tar.gz libserverframe-1.1.20.tar.gz nginx-1.22.0.tar.gz[[email protected] fastdfs]#3.1.3 tracker 和 storage server此处因为是fastdfs单机装置,因而 tracker server 和 storage server 装置到同一台机器上。 ...

October 8, 2022 · 4 min · jiezi

关于fastdfs:FastDFS-海量小文件存储解决之道

作者:vivo互联网服务器团队-Zhou Changqing一、FastDFS原理介绍FastDFS是一个C语言实现的开源轻量级分布式文件系统 。 反对 Linux、FreeBSD、AID 等Unix零碎,解决了大容量的文件存储和高并发拜访问题,文件存取实现了负载平衡,适宜存储 4KB~500MB 之间的小文件,特地适宜以文件为载体的在线服务,如图片、视频、文档等等。 二、FastDFS 架构FastDFS 由三个局部形成: 客户端(Client)跟踪服务器(TrackerServer)存储服务器(StorageServer) 2.1 Tracker Server (跟踪服务器)Tracker Server (跟踪服务器) 次要是做调度工作,起到负载平衡的作用。 (1)【服务注册】治理StorageServer存储集群,StorageServer启动时,会把本人注册到TrackerServer上,并且定期报告本身状态信息,包含磁盘残余空间、文件同步情况、文件上传下载次数等统计信息。 (2)【服务发现】Client拜访StorageServer之前,必须先拜访TrackerServer,动静获取到StorageServer的连贯信息,最终数据是和一个可用的StorageServer进行传输。 (3)【负载平衡】 store group调配策略:0:轮询形式1:指定组2:均衡负载(抉择最大残余空间的组(卷)上传)store server调配策略:0:轮询形式1:依据 IP 地址进行排序抉择第一个服务器( IP 地址最小者)2:依据优先级进行排序(上传优先级由storage server来设置,参数名为upload_priority)stroe path调配 :0:轮流形式,多个目录顺次寄存文件2:抉择残余空间最大的目录寄存文件(留神:残余磁盘空间是动静的,因而存储到的目录或磁盘可能也是变动的)2.2 Tracker Server (跟踪服务器)Tracker Server (跟踪服务器) 次要提供容量和备份服务。 【分组治理】以Group为单位,每个Group蕴含多台Storage Server,数据互为备份,存储容量以Group内容量最小的 storage 为准,已 Group 为单位组织存储不便利用隔离、负载平衡和正本数据定制。 毛病:Group容量受单机存储容量的限度,数据恢复只能依赖Group其余机器从新同步。 【数据同步】文件同步只能在 Group 内的Storage Server之间进行,采纳push形式,即源服务器同步给指标服务器。源服务器读取 binlog 文件,将文件内容解析后,按操作命令发送给指标服务器,有指标服务按命令进行操作。 三、上传下载流程3.1 上传流程解析 3.1.1 抉择Tracker Server集群中的 tracker 之间都是对等的,客户端在上传文件时可任意抉择一个 tracker 即可。 3.1.2 调配Group、Stroage Server 和storage path(磁盘或者挂载点)tracker 接管到上传申请时会先给该文件调配一个能够存储的 Group ,而后在Group中调配一个Storage Server给客户端,最初在接管到客户端写文件申请时,Storage Server 会调配一个数据存储目录并写入。 (该过程中的调配策略详见:【负载平衡】) ...

April 26, 2022 · 2 min · jiezi

关于fastdfs:CentOS7中搭建FastDFS分布式文件系统

介绍FastDFS是一个开源的分布式文件系统,她对文件进行治理,性能包含:文件存储、文件同步、文件拜访(文件上传、文件下载)等,解决了大容量存储和负载平衡的问题。特地适宜以文件为载体的在线服务,如相册网站、视频网站等等。 FastDFS服务端有两个角色:跟踪器(tracker)和存储节点(storage)。跟踪器次要做调度工作,在拜访上起负载平衡的作用。 指标 在CentOS7中搭建FastDFS分布式文件系统;FastDFS+ Nginx + fastdfs-nginx-module整合;对FastDFS文件治理(上传、下载、预览、删除);剖析 装置依赖包;装置FastDFS;整合Nginx与fastdfs-nginx-module;测试。环境 CentOS7FastDFS_v5.08.tar.gznginx-1.19.10.tar.gzlibfastcommon-master.zip依赖装置 要装置 gccyum install gcc-c++装置 libeventyum -y install libevent装置 libeventyum -y install libevent装置 libfastcommon 或 libfastcommon-mastertar -zxvf libfastcommon-master.zip cd libfastcommon-master./make.sh./make.sh install 这里抉择libfastcommon-master.zip因为libfastcommon配置后FastDFS编译不胜利;libfastcommon 是 FastDFS 官网提供的,libfastcommon 蕴含了 FastDFS 运行所须要的一些根底库。装置FastDFS 解压安装包tar -zxvf FastDFS_v5.08.tar.gz进入目录cd FastDFS编译./make.sh装置./make.sh install查看装置地位ls -la /usr/bin/fdfs*配置Tracker服务 进入/etc/fdfs目录,看到几个文件 没有到/mysoft/FastDFS/conf文件拷贝过去;拷贝tracker.conf.sample,改tracker.conf;cp /etc/fdfs/tracker.conf.sample /etc/fdfs/tracker.conf编辑tracker.conf 批改相干参数 vi /etc/fdfs/tracker.conf #tracker存储data和log的跟门路,必须提前创立好 base_path=/home/fastdfs/tracker port=22122 #tracker默认22122 http.server_port=80 #http端口,须要和nginx雷同启动tracker(反对start|stop|restart) /usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf start|stop|restart或 /etc/init.d/fdfs_trackerd start|stop|restart查看端口状况:netstat -apn|grep fdfs netstat -apn|grep fdfs配置Storage服务 进入/etc/fdfs目录,看到几个文件 没有到/mysoft/FastDFS/conf文件拷贝过去;拷贝storage.conf.sample,改storage.conf;cp /etc/fdfs/storage.conf.sample /etc/fdfs/storage.conf编辑storage.conf 批改相干参数 vi /etc/fdfs/storage.conf ...

May 30, 2021 · 1 min · jiezi

centos-fastdfs-nginx-docker-化

环境准备:使用的软件:libfatscommon:FastDFS分离出的一些公用函数包 https://github.com/happyfish1... FastDFS:FastDFS本体 https://github.com/happyfish1... fastdfs-nginx-module:FastDFS和nginx的关联模块 https://github.com/happyfish1... nginx:nginx1.16.1 http://nginx.org/en/download.... 将以上文件,下载下来,并放到一个地方 Dockerfile 编写FROM centosMAINTAINER 陈少平 18250073990@163.com# install dependencyRUN yum -y upgrade \ && yum install git gcc gcc-c++ make automake autoconf libtool pcre pcre-devel zlib zlib-devel openssl-devel -yWORKDIR /usr/local/src# copy tool packageADD fastdfs-5.11.tar.gz ./ADD fastdfs-nginx-module-1.20.tar.gz ./ADD libfastcommon-1.0.39.tar.gz ./ADD nginx-1.16.1.tar.gz ./# install libfastcommonWORKDIR /usr/local/src/libfastcommon-1.0.39RUN ./make.sh && ./make.sh install# install FastDFSWORKDIR /usr/local/src/fastdfs-5.11RUN ./make.sh \ && ./make.sh install# install fastdfs-nginx-moduleADD config /usr/local/src/fastdfs-nginx-module-1.20/src# install nginxWORKDIR /usr/local/src/nginx-1.16.1RUN ./configure --add-module=/usr/local/src/fastdfs-nginx-module-1.20/src \ && make \ && make install# copy filesRUN cp /etc/fdfs/tracker.conf.sample /etc/fdfs/tracker.conf \ && cp /etc/fdfs/storage.conf.sample /etc/fdfs/storage.conf \ && cp /etc/fdfs/client.conf.sample /etc/fdfs/client.conf \ && cp /usr/local/src/fastdfs-5.11/conf/http.conf /etc/fdfs/ \ && cp /usr/local/src/fastdfs-5.11/conf/mime.types /etc/fdfs/ \ && cp /usr/local/src/fastdfs-nginx-module-1.20/src/mod_fastdfs.conf /etc/fdfs# create fastdfs storage RUN mkdir /home/dfsWORKDIR /etc/fdfs# nginx portEXPOSE 80# fdfs-tracker portEXPOSE 22122# fdfs-client portEXPOSE 8888CMD ["/bin/bash"]修改 /usr/local/src/fastdfs-nginx-module/src/config 文件信息(ngx_module_incs,CORE_INCS, CORE_LIBS 修改这 3个地方)ngx_addon_name=ngx_http_fastdfs_module ...

August 17, 2019 · 2 min · jiezi

FastDFS-Docker化部署-以及-Java-SpringMVC实践

简介FastDFS是一个轻量级分布式文件系统。可以对文件进行管理,功能包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,而且可以集群部署,有高可用保障。相应的竞品有Ceph、TFS等。相比而言FastDFS对硬件的要求比较低,所以适合中小型公司。 概念FastDFS服务端由两个重要部分组成:跟踪器(Tracker)和存储节点(Storage)。 Tracker主要做调度工作,在访问上起负载均衡的作用。Tracker可以做集群部署,各个节点之间是平等的,客户端请求时采用轮询机制,某个Tracker不能提供服务时就换另一个。Storage启动后会连接到Tracker Server告知自己的Group信息,形成映射关联,并采用心跳机制保持状态。Storage存储节点负责文件的存储,Storage可以集群部署。 Storage集群有以下特点: 以组(Group)为单位(也有称呼为卷 Volume的),集群的总容量为所有组的集合。一个卷(组)内storage server之间相互通信,文件进行同步,保证卷内storage完全一致,所以一个卷的容量以最小的服务器为准。不同的卷之间相互不通信。当某个卷的压力较大时可以添加storage server(纵向扩展),如果系统容量不够可以添加卷(横向扩展)。上传流程此章节根据资料整理,可能随着版本有所改变,这里只介绍大致的,以便了解整个运作流程。如果需要深入研究,建议还是以官方文档为标准。 一,客户端请求会打到负载均衡层,到tracker server时,由于每个server之间是对等的关系,所以可以任意选择一个tracker server。 二,到storage层:tracker server接收到upload file请求时,会为该请求分配一个可以存储该文件的group。 分配group规则: Round robin 轮询Specified group 指定一个groupLoad balance 剩余存储空间多的group优先三,确定group后,tracker会在group内选择一个storage server给客户端。 在group内选择storage server时规则: Round robin 轮询First server ordered by ip 按ip排序First server ordered by priority,按优先级排序(优先级在storage上配置)四,选择storage path:当分配好storage server后,客户端向storage发送写文件请求,storage将会为文件分配一个数据存储目录,支持规则如下: round robin 轮询剩余存储空间最多的优先五,生成File id:选定存储目录之后,storage会为文件生成一个File id。规则如下: 由storage server ip、文件创建时间、文件大小,文件crc32和一个随机数拼接而成,然后将这个二进制串进程base64编码,转换为可打印的字符串。六,选择两级目录:每个存储目录下有两级256 * 256的子目录,storage会按文件Field进行两次hash,路由到其中的一个目录,然后将文件以file id为文件名存储到该子目录下。 一个文件路径最终由如下组成:组名/磁盘/目录/文件名 七,客户端upload file成功后,会拿到一个storage生成的文件名,接下来客户端根据这个文件名即可访问到该文件。 下载流程下载流程如下: 一,选择tracker server:和upload file一样,在download file时随机选择tracker server。 二,选择group:tracker发送download请求给某个tracker,必须带上文件名信息,tracker从文件名中解析出group、大小、创建时间等信息,根据group信息获取对于的group。 三,选择storage server:从group中选择一个storage用来服务读请求。由于group内的文件同步时在后台异步进行的,所以有可能出现在读到的时候,文件还没有同步到某些storage server上,为了尽量避免反问道这样的storage,tracker按照一定的规则选择group内可读的storage。 文件HTTP预览服务Storage还可以结合nginx的fastdfs-nginx-module提供http服务,以实现图片等预览功能。 这个部分这里不做介绍,后续可能单独写篇文章,因为我发现对fastDFS集群提供http服务还是挺复杂,包括我下面找的docker镜像都不完善,主要是规划的问题,包括衍生的服务,缓存,以及对图片的处理(nginx+lua)这些,后续打算研究下,重新开源个docker构建镜像。 ...

May 23, 2019 · 2 min · jiezi

FastDFS入门一篇就够

完整安装流程下载的包都存放在~/caibh/fdfs-package目录下。下载libfastcommon、fastdfs、fastdfs-nginx-module:cd ~/caibh/fdfs-package# -S print server response# -O write documents to filewget https://github.com/happyfish100/libfastcommon/archive/V1.0.39.tar.gz -SO libfastcommon.tar.gzwget https://github.com/happyfish100/fastdfs/archive/V5.11.tar.gz -SO fastdfs.tar.gzwget https://github.com/happyfish100/fastdfs-nginx-module/archive/V1.20.tar.gz -SO fastdfs-nginx-module.tar.gz# 解压tar -xf xxx.tar.gz 安装 libfastcommoncd ~/caibh/fdfs-packagecd libfastcommon-1.0.39./make.sh./make.sh install安装 fastdfscd ~/caibh/fdfs-packagecd fastdfs-5.11./make.sh./make.sh install安装好后,程序是在/usr/bin目录下:$ which fdfs_trackerd/usr/bin/fdfs_trackerd而配置文件是在/etc/fdfs目录下:$ cd /caibh/fdfs-package/fastdfs-5.11$ ls /etc/fdfsclient.conf.sample storage_ids.conf.sample tracker.conf.sample storage.conf.sample但是这些配置文件是不全的,而且都是模板,所以需要从fastdfs包中拷贝过来,并修改配置:$ cd /caibh/fdfs-package/fastdfs-5.11/conf$ lsanti-steal.jpg client.conf http.conf mime.types storage.conf storage_ids.conf tracker.conf$ sudo cp /caibh/fdfs-package/fastdfs-5.11/conf/* /etc/fdfs修改配置sudo vi /etc/fdfs/tracker.conf:# the tracker server portport=22122# the base path to store data and log filesbase_path=/home/caibh/fdfs# HTTP port on this tracker serverhttp.server_port=9270sudo vi /etc/fdfs/storage.conf:# storage所属的组group_name=group1# the storage server portport=23000# the base path to store data and log filesbase_path=/home/caibh/fdfs# store_path#, based 0, if store_path0 not exists, it’s value is base_path# the paths must be existstore_path0=/home/caibh/fdfs#store_path1=/home/caibh/fdfs2# tracker服务器,虽然是同一台机器上,但是不能写127.0.0.1。这项配置可以出现一次或多次tracker_server=191.8.1.77:22122# the port of the web server on this storage serverhttp.server_port=8888sudo vi /etc/fdfs/client.conf:# the base path to store log filesbase_path=/home/caibh/fdfs/client# tracker_server can ocur more than once, and tracker_server format is# “host:port”, host can be hostname or ip addresstracker_server=191.8.1.77:22122#HTTP settingshttp.tracker_server_port=9270sudo vi /etc/fdfs/mod_fastdfs.conf:# the base path to store log filesbase_path=/tmp# FastDFS tracker_server can ocur more than once, and tracker_server format is# “host:port”, host can be hostname or ip address# valid only when load_fdfs_parameters_from_tracker is truetracker_server=191.8.1.77:22122# the port of the local storage server# the default value is 23000storage_server_port=23000# the group name of the local storage servergroup_name=group1# store_path#, based 0, if store_path0 not exists, it’s value is base_path# the paths must be exist# must same as storage.confstore_path0=/home/caibh/fdfs#store_path1=/home/yuqing/fastdfs1配置过程中有几点要注意:确保配置中用到的目录已经创建了。比如/fdfs/client、/fdfs/data、/fdfs/logs确保各种配置文件之间引用的端口一直。比如:mod_fastdfs.conf文件中tracker_server的端口应该跟tracker.conf中port一致;mod_fastdfs.conf文件中storage_server_port的端口应该跟跟storage.conf中port一致;其他配置或文件虽然不用修改,但是fastdfs-nginx-module模块会用到:anti-steal.jpghttp.confmime.types启动tracker和storage:# 启动fdfs_trackerd /etc/fdfs/tracker.conf startfdfs_storaged /etc/fdfs/storage.conf start# 查看日志tail -n10 ~/fdfs/logs/trackerd.logtail -n10 ~/fdfs/logs/storaged.log# 如果日志显示有错误信息,需要根据信息来查找错误原因用fdfs_test测试上传$ fdfs_test /etc/fdfs/client.conf upload ~/caibh/test_images/XinXiJuZhiWang.jpg安装fastdfs-nginx-module思路:安装过程比较复杂,由于当前系统已经有一个nginx在运行了,所以要先确认当前系统nginx的版本,然后到官网下载对应版本的nginx源码,然后查看系统nginx的编译选项,用一模一样的编译选项外加fastdfs-nginx-module的源码,重新编译一个nginx程序。用新的nginx替换系统的nginx。注意:这里的安装场景是tracker和storage都装在同一个机器上。查看已安装并在运行中的nginx的版本:$ nginx -vnginx version: nginx/1.10.3 (Ubuntu)到官网下载对应版本的nginx源码,并解压,改名为nginx-src,然后进入nginx-src目录查看当前运行的ngxin原来的编译选项:$ cd ~/caibh/nginx-src$ nginx -Vnginx version: nginx/1.10.3 (Ubuntu)built with OpenSSL 1.0.2g 1 Mar 2016TLS SNI support enabledconfigure arguments: –with-cc-opt=’-g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2’ –with-ld-opt=’-Wl,-Bsymbolic-functions -fPIE -pie -Wl,-z,relro -Wl,-z,now’ –prefix=/usr/share/nginx –conf-path=/etc/nginx/nginx.conf –http-log-path=/var/log/nginx/access.log –error-log-path=/var/log/nginx/error.log –lock-path=/var/lock/nginx.lock –pid-path=/run/nginx.pid –http-client-body-temp-path=/var/lib/nginx/body –http-fastcgi-temp-path=/var/lib/nginx/fastcgi –http-proxy-temp-path=/var/lib/nginx/proxy –http-scgi-temp-path=/var/lib/nginx/scgi –http-uwsgi-temp-path=/var/lib/nginx/uwsgi –with-debug –with-pcre-jit –with-ipv6 –with-http_ssl_module –with-http_stub_status_module –with-http_realip_module –with-http_auth_request_module –with-http_addition_module –with-http_dav_module –with-http_geoip_module –with-http_gunzip_module –with-http_gzip_static_module –with-http_image_filter_module –with-http_v2_module –with-http_sub_module –with-http_xslt_module –with-stream –with-stream_ssl_module –with-mail –with-mail_ssl_module –with-threads为了方便编辑,复制上面信息,在nginx-src目录下创建一个custom_configure.sh文件,把复制的内容拷贝进去,并在最后加上fastdfs-nginx-module的源码:$ cd /caibh/nginx-src$ cat custom_configure.sh ./configure --with-cc-opt=’-g -O2 -fPIE -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2’ --with-ld-opt=’-Wl,-Bsymbolic-functions -fPIE -pie -Wl,-z,relro -Wl,-z,now’ --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-ipv6 --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_addition_module --with-http_dav_module --with-http_geoip_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module --with-http_v2_module --with-http_sub_module --with-http_xslt_module --with-stream --with-stream_ssl_module --with-mail --with-mail_ssl_module --with-threads --add-module=/caibh/fdfs-package/fastdfs-nginx-module-1.20/src执行custom_configure.sh:# ~/caibh/nginx-src# 执行编译$ sudo ./custom_configure.sh # 报错./configure: error: the HTTP XSLT module requires the libxml2/libxsltlibraries. You can either do not enable the module or install the libraries.# 解决sudo apt-get install libxml2 libxml2-dev libxslt-dev# 再次执行$ sudo ./custom_configure.sh # 报错./configure: error: the HTTP image filter module requires the GD library.You can either do not enable the module or install the libraries.#解决sudo apt-get install libgd-dev# 再次执行$ sudo ./custom_configure.sh # 报错./configure: error: the GeoIP module requires the GeoIP library.You can either do not enable the module or install the library.# 搜索$ sudo apt-cache search geoipgeoclue-ubuntu-geoip - Provide positioning for GeoClue via Ubuntu GeoIP servicesgeoip-bin - IP lookup command line tools that use the GeoIP librarygeoip-database - IP lookup command line tools that use the GeoIP library (country database)geoip-dbg - debugging symbols for the GeoIP packageslibgeoip-dev - Development files for the GeoIP library…..# 解决$ sudo apt-install libgeoip-dev执行后有用的信息,通过这些信息可以知道编译出来的nginx会装到哪里,配置文件会放在哪里,错误日志会放在哪里:Configuration summary + using threads + using system PCRE library + using system OpenSSL library + md5: using OpenSSL library + sha1: using OpenSSL library + using system zlib library nginx path prefix: “/usr/share/nginx” nginx binary file: “/usr/share/nginx/sbin/nginx” nginx modules path: “/usr/share/nginx/modules” nginx configuration prefix: “/etc/nginx” nginx configuration file: “/etc/nginx/nginx.conf” nginx pid file: “/run/nginx.pid” nginx error log file: “/var/log/nginx/error.log” nginx http access log file: “/var/log/nginx/access.log” nginx http client request body temporary files: “/var/lib/nginx/body” nginx http proxy temporary files: “/var/lib/nginx/proxy” nginx http fastcgi temporary files: “/var/lib/nginx/fastcgi” nginx http uwsgi temporary files: “/var/lib/nginx/uwsgi” nginx http scgi temporary files: “/var/lib/nginx/scgi"停止nginx,并备份原来的nginx执行文件,和配置文件:$ which nginx/usr/sbin/nginx$ sudo cp /usr/sbin/nginx /usr/sbin/nginx_org_bak$ sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak继续在nginx-src目录执行make和make install:$ cd ~/caibh/nginx-src$ sudo make# 报错Fatal error: can’t create objs/addon/src/ngx_http_fastdfs_module.o: Permission deniedIn file included from /home/xxxx/caibh/fdfs-package/fastdfs-nginx-module-1.20/src/common.c:26:0, from /home/xxxx/caibh/fdfs-package/fastdfs-nginx-module-1.20/src/ngx_http_fastdfs_module.c:6:/usr/include/fastdfs/fdfs_define.h:15:27: fatal error: common_define.h: No such file or directory# 解决# 修改fastdfs-nginx-module的src/config文件$ cd /home/xxxx/caibh/fdfs-package/fastdfs-nginx-module-1.20/src$ sudo vi config# 修改一下两项:ngx_module_incs="/usr/include/fastdfs /usr/include/fastcommon/“CORE_INCS="$CORE_INCS /usr/include/fastdfs /usr/include/fastcommon/”# 重新运行 nginx-src/custom_configure.sh$ pwd/home/xxxx/caibh/nginx-src$ sudo ./custom_configure.sh$ sudo make$ sudo make install# make install 会在/usr/share/nginx/sbin目录下生成一个名为nginx的可执行文件$ sudo ls /usr/share/nginxhtml sbin关闭系统原有的nginx,并备份好系统原来的nginx文件:sudo nginx -s stopcd /usr/sbinsudo cp mv /usr/sbin/nginx /usr/sbin/nginx_bak备份好后创建一个软链接,放在/usr/sbin目录下:# 检查自己编译出来的nginx能否运行$ ./nginx -vnginx version: nginx/1.10.3# 创建软链接$ sudo ln -s /usr/share/nginx/sbin/nginx /usr/sbin/nginx配置nginx,加入路由规则,映射到fastdfs的数据目录:# config for fastdfs-nginx-moduleserver { listen 8777; location /M00 { root /fdfs/data; ngx_fastdfs_module; }}开放端口:sudo iptables -A IN_public_allow -p tcp –dport 8777 -j ACCEPTsudo iptables -L -n测试上传图片:$ fdfs_test /etc/fdfs/client.conf upload /caibh/test_images/XinXiJuZhiWang.jpgThis is FastDFS client test program v5.11Copyright (C) 2008, Happy Fish / YuQingFastDFS may be copied only under the terms of the GNU GeneralPublic License V3, which may be found in the FastDFS source kit.Please visit the FastDFS Home Page http://www.csource.org/ for more detail.[2019-02-22 14:54:33] DEBUG - base_path=/home/xxxx/fdfs/client, connect_timeout=30, network_timeout=60, tracker_server_count=1, anti_steal_token=0, anti_steal_secret_key length=0, use_connection_pool=0, g_connection_pool_max_idle_time=3600s, use_storage_id=0, storage server id count: 0tracker_query_storage_store_list_without_group: server 1. group_name=, ip_addr=191.8.2.203, port=23000group_name=group1, ip_addr=191.8.2.203, port=23000storage_upload_by_filenamegroup_name=group1, remote_filename=M00/00/00/vwgCy1xvnKmAIDXDAAEM3XOobI4945.jpgsource ip address: 191.8.2.203file timestamp=2019-02-22 14:54:33file size=68829file crc32=1940417678example file url: http://191.8.2.203:9270/group1/M00/00/00/vwgCy1xvnKmAIDXDAAEM3XOobI4945.jpgstorage_upload_slave_by_filenamegroup_name=group1, remote_filename=M00/00/00/vwgCy1xvnKmAIDXDAAEM3XOobI4945_big.jpgsource ip address: 191.8.2.203file timestamp=2019-02-22 14:54:33file size=68829file crc32=1940417678example file url: http://191.8.2.203:9270/group1/M00/00/00/vwgCy1xvnKmAIDXDAAEM3XOobI4945_big.jpg访问:http://191.8.2.203:8777/M00/00/00/vwgCy1xvnKmAIDXDAAEM3XOobI4945_big.jpg# 如果能看到图片则表示安装fastdfs-nginx-module成功附录1:FastDFS 官网介绍FastDFS是一款高性能的分布式文件系统。主要功能包括:文件存储,文件同步,文件访问(上传下载)。它可以解决高容量和负载均衡的问题。FastDFS适合用来做文件相关的网站,如图片分享、视频分享等。FastDFS有两种角色:tracker和storage。tracker负责文件访问的跟踪和负载均衡。storage负责存储文件,它的功能包括:文件存储、文件同步、提供文件访问接口,storage还负责管理文件的元数据,这些数据是以键值对的形式表示的,如:width=1024,键是“width”,值是“1024”。tracker和storage可以是一个或多个服务器。在tracker或storage的集群中,任何时候都可以从中删除服务器,对线上服务没有任何影响。tracker集群中的服务器是点对点的。存储服务器以 卷/组 形式组织,以获取高容量。存储系统包括一个或多个卷,卷与卷之间的文件是相互独立的。整个存储系统的总容量等于所有卷的容量之和。一个文件卷包括一个或多个存储服务器,一个卷中的存储服务器之间的文件是一样的。一个文件卷中的服务器会互相备份,且这些服务器之间是负载均衡的。当添加一个存储服务器到一个卷的时候,卷中的文件会自动复制到新的服务器,复制完以后,系统会把新服务器切换到线上,已提供存储服务。当存储容量不足时,你可以添加一个或多个卷来扩展存储容量。一个文件的标识包括两部分:卷名和文件名附录2:FastDFS官方INSTALL文件step 1. 下载安装 libfastcommon地址:https://github.com/happyfish1…step 2. 下载安装 FastDFS 解压:tar xzf FastDFS_v5.08.tar.gzstep 3. 进入FastDFS的目录cd FastDFSstep 4. 执行make:./make.shstep 5. 执行make install./make.sh installstep 6. 修改tracker和storage的配置文件:/etc/fdfs/tracker.conf几个重要的配置:# the tracker server portport=22122# the base path to store data and log filesbase_path=/home/caibh/fdfs# which group to upload file# when store_lookup set to 1, must set store_group to the group namestore_group=group2# HTTP port on this tracker serverhttp.server_port=9270/etc/fdfs/storage.conf几个重要的配置:# the storage server portport=23000# the base path to store data and log filesbase_path=/home/caibh/fdfs# store_path#, based 0, if store_path0 not exists, it’s value is base_path# the paths must be existstore_path0=/home/caibh/fdfs#store_path1=/home/caibh/fdfs2# tracker_server can ocur more than once, and tracker_server format is# “host:port”, host can be hostname or ip address# 在同一台机器上配置tracker和storage时,这里如果是127.0.0.1会报错,所以要配置真正的ip地址。tracker_server=191.8.1.77:22122# the port of the web server on this storage serverhttp.server_port=8888step 7. run server programs启动tracker:/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf restartin Linux, you can start fdfs_trackerd as a service:/sbin/service fdfs_trackerd start启动storage:/usr/bin/fdfs_storaged /etc/fdfs/storage.conf restartin Linux, you can start fdfs_storaged as a service:/sbin/service fdfs_storaged startstep 8. 测试修改客户端配置文件:/etc/fdfs/client.conf几个重要的配置:# the base path to store log filesbase_path=/home/caibh/fdfs/client# tracker_server can ocur more than once, and tracker_server format is# “host:port”, host can be hostname or ip addresstracker_server=191.8.1.77:22122#HTTP settingshttp.tracker_server_port=9270run the client test program:/usr/bin/fdfs_test <client_conf_filename> <operation>/usr/bin/fdfs_test1 <client_conf_filename> <operation>例如上传一个图片文件:caibh@pc:$ fdfs_test /etc/fdfs/client.conf upload /develop/fastdfs/test_file/LiuLangDiQiu.jpgThis is FastDFS client test program v5.11Copyright (C) 2008, Happy Fish / YuQingFastDFS may be copied only under the terms of the GNU GeneralPublic License V3, which may be found in the FastDFS source kit.Please visit the FastDFS Home Page http://www.csource.org/ for more detail.[2019-02-19 11:32:30] DEBUG - base_path=/home/caibh/fdfs/client, connect_timeout=30, network_timeout=60, tracker_server_count=1, anti_steal_token=0, anti_steal_secret_key length=0, use_connection_pool=0, g_connection_pool_max_idle_time=3600s, use_storage_id=0, storage server id count: 0tracker_query_storage_store_list_without_group: server 1. group_name=, ip_addr=191.8.1.77, port=23000group_name=group1, ip_addr=191.8.1.77, port=23000storage_upload_by_filenamegroup_name=group1, remote_filename=M00/00/00/vwgBTVxreM6AD-mcAAEE_qeEI2s285.jpgsource ip address: 191.8.1.77file timestamp=2019-02-19 11:32:30file size=66814file crc32=2810454891example file url: http://191.8.1.77:9270/group1/M00/00/00/vwgBTVxreM6AD-mcAAEE_qeEI2s285.jpgstorage_upload_slave_by_filenamegroup_name=group1, remote_filename=M00/00/00/vwgBTVxreM6AD-mcAAEE_qeEI2s285_big.jpgsource ip address: 191.8.1.77file timestamp=2019-02-19 11:32:30file size=66814file crc32=2810454891example file url: http://191.8.1.77:9270/group1/M00/00/00/vwgBTVxreM6AD-mcAAEE_qeEI2s285_big.jpgstep 9. 查看状态run the monitor program:/usr/bin/fdfs_monitor <client_conf_filename># 如:caibh@pc:$ fdfs_monitor /etc/fdfs/storage.conf[2019-02-19 10:25:09] DEBUG - base_path=/home/caibh/fdfs, connect_timeout=30, network_timeout=60, tracker_server_count=1, anti_steal_token=0, anti_steal_secret_key length=0, use_connection_pool=0, g_connection_pool_max_idle_time=3600s, use_storage_id=0, storage server id count: 0server_count=1, server_index=0tracker server is 191.8.1.77:22122group count: 1Group 1:group name = group1disk total space = 111868 MBdisk free space = 62228 MBtrunk free space = 0 MBstorage server count = 1active server count = 1storage server port = 23000storage HTTP port = 8888store path count = 1subdir count per path = 256current write server index = 0current trunk file id = 0 Storage 1: id = 191.8.1.77 ip_addr = 191.8.1.77 (191-8-1-77.user.vivozap.com.br) ACTIVE http domain = version = 5.11 join time = 2019-02-19 10:22:53 up time = 2019-02-19 10:22:53 total storage = 111868 MB free storage = 62228 MB upload priority = 10 store_path_count = 1 subdir_count_per_path = 256 storage_port = 23000 storage_http_port = 8888 tracker server config file sample please see conf/tracker.confstorage server config file sample please see conf/storage.confclient config file sample please see conf/client.confItem detailserver common itemsitem nametypedefaultMustbase_pathstring YdisabledbooleanfalseNbind_addrstring Nnetwork_timeoutint30(s)Nmax_connectionsint256Nlog_levelstringinfoNrun_by_groupstring Nrun_by_userstring Nallow_hostsstringNsync_log_buff_intervalint10(s)Nthread_stack_sizestring1MNmemo:base_path is the base path of sub dirs: data and logs. base_path must exist and it’s sub dirs will be automatically created if not exist. $base_path/data: store data files $base_path/logs: store log fileslog_level is the standard log level as syslog, case insensitiveemerg: for emergencyalertcrit: for criticalerrorwarn: for warningnoticeinfodebugallow_hosts can ocur more than once, host can be hostname or ip address,”" means match all ip addresses, can use range like this: 10.0.1.[1-15,20] or host[01-08,20-25].domain.com, for example: allow_hosts=10.0.1.[1-15,20] allow_hosts=host[01-08,20-25].domain.comtracker server itemsitem nametypedefaultMustitem nametypedefaultMustportint22000Nstore_lookupint0Nstore_groupstring Nstore_serverint0Nstore_pathint0Ndownload_serverint0Nreserved_storage_spacestring1GBNmemo: the value of store_lookup is:0: round robin (default)1: specify group2: load balance (supported since V1.1)store_group is the name of group to store files.when store_lookup set to 1(specify group), store_group must be set to a specified group name.reserved_storage_space is the reserved storage space for system or other applications. if the free(available) space of any stoargeserver in a group <= reserved_storage_space, no file can be uploadedto this group (since V1.1)bytes unit can be one of follows: G or g for gigabyte(GB) M or m for megabyte(MB) K or k for kilobyte(KB) no unit for byte(B)storage server itemsitem nametypedefaultMustgroup_namestring Ytracker_serverstring Yportint23000Nheart_beat_intervalint30(s)Nstat_report_intervalint300(s)Nsync_wait_msecint100(ms)Nsync_intervalint0(ms)Nsync_start_timestring00:00Nsync_end_timestring23:59Nstore_path_countint1Nstore_path0stringbase_pathNstore_path#string Nsubdir_count_per_pathint256Ncheck_file_duplicateboolean0Nkey_namespacestring Nkeep_aliveboolean0Nsync_binlog_buff_intervalint60sNmemo:tracker_server can ocur more than once, and tracker_server format is “host:port”, host can be hostname or ip address.store_path#, # for digital, based 0check_file_duplicate: when set to true, must work with FastDHT server, more detail please see INSTALL of FastDHT. FastDHT download page: http://code.google.com/p/fast...key_namespace: FastDHT key namespace, can’t be empty when check_file_duplicate is true. the key namespace should short as possible附录3:FastDFS Nginx模块官方INSTALL文件step 1. first install the FastDFS storage server and client library, the FastDFS version should >= 5.11. download address: https://github.com/happyfish1...step 2. install nginx server FastDFS nginx module test passed with nginx 1.15.1, my nginx installed in /usr/local/nginxstep 3. download FastDFS nginx module source package and unpack it, such as:cd /home/yuqinggit clone https://github.com/happyfish100/fastdfsstep 4. enter the nginx source dir, compile and install the module, such as:cd nginx-1.15.1./configure –add-module=/home/yuqing/fastdfs-nginx-module/srcmake; make install注意: before compile, you can change FDFS_OUTPUT_CHUNK_SIZE and FDFS_MOD_CONF_FILENAME macro in the config file as:CFLAGS="$CFLAGS -D_FILE_OFFSET_BITS=64 -DFDFS_OUTPUT_CHUNK_SIZE=‘256*1024’ -DFDFS_MOD_CONF_FILENAME=’"/etc/fdfs/mod_fastdfs.conf"’" step 5. config the nginx config file such as nginx.conf, add the following lines: location /M00 { root /home/yuqing/fastdfs/data; ngx_fastdfs_module; }step 6. 创建软链接 ${fastdfs_base_path}/data/M00 链接到 ${fastdfs_base_path}/data,命令如下:ln -s /home/yuqing/fastdfs/data /home/yuqing/fastdfs/data/M00step 7. change the config file /etc/fdfs/mod_fastdfs.conf, more detail please see itstep 8. 重启nginx:/usr/local/nginx/sbin/nginx -s stop; /usr/local/nginx/sbin/nginx ...

February 22, 2019 · 8 min · jiezi

Netty+SpringBoot+FastDFS+Html5实现聊天App详解(三)

Netty+SpringBoot+FastDFS+Html5实现聊天App,项目介绍。Netty+SpringBoot+FastDFS+Html5实现聊天App,项目github链接。本章完整代码链接。本节主要讲解聊天App PigChat中关于好友申请的发送与接受。包含以下内容:(1)搜索好友接口(2)发送添加好友申请的接口(3)接受添加好友申请的接口搜索好友接口定义枚举类型 SearchFriendsStatusEnum,表示添加好友的前置状态 SUCCESS(0, “OK”), USER_NOT_EXIST(1, “无此用户…”), NOT_YOURSELF(2, “不能添加你自己…”), ALREADY_FRIENDS(3, “该用户已经是你的好友…”);在service中定义搜索朋友的前置条件判断的方法preconditionSearchFriends。传入的是用户的Id以及搜索的用户的名称。【1】首先根据搜索的用户的名称查找是否存在这个用户。【2】如果搜索的用户不存在,则返回[无此用户]。【3】如果搜索的用户是你自己,则返回[不能添加自己]。【4】如果搜索的用户已经是你的好友,则返回[该用户已经是你的好友]。【5】否则返回成功。 @Transactional(propagation = Propagation.SUPPORTS) @Override public Integer preconditionSearchFriends(String myUserId, String friendUsername) { //1. 查找要添加的朋友是否存在 Users user = queryUserInfoByUsername(friendUsername); // 2. 搜索的用户如果不存在,返回[无此用户] if (user == null) { return SearchFriendsStatusEnum.USER_NOT_EXIST.status; } // 3. 搜索账号是你自己,返回[不能添加自己] if (user.getId().equals(myUserId)) { return SearchFriendsStatusEnum.NOT_YOURSELF.status; } // 4. 搜索的朋友已经是你的好友,返回[该用户已经是你的好友] Example mfe = new Example(MyFriends.class); Criteria mfc = mfe.createCriteria(); mfc.andEqualTo(“myUserId”, myUserId); mfc.andEqualTo(“myFriendUserId”, user.getId()); MyFriends myFriendsRel = myFriendsMapper.selectOneByExample(mfe); if (myFriendsRel != null) { return SearchFriendsStatusEnum.ALREADY_FRIENDS.status; } //返回成功 return SearchFriendsStatusEnum.SUCCESS.status; }在controller中创建搜索好友接口 searchUser。传入的是用户的Id,以及要搜索的用户的名字。【0】首先判断传入的参数是否为空。【1】通过userService的preconditionSearchFriends方法得到前置条件。【2】如果搜索前置条件为成功,则向前端返回搜索用户的信息。【3】否则搜索失败。 /** * @Description: 搜索好友接口, 根据账号做匹配查询而不是模糊查询 / @PostMapping("/search") public IMoocJSONResult searchUser(String myUserId, String friendUsername) throws Exception { // 0. 判断 myUserId friendUsername 不能为空 if (StringUtils.isBlank(myUserId) || StringUtils.isBlank(friendUsername)) { return IMoocJSONResult.errorMsg(""); } // 前置条件 - 1. 搜索的用户如果不存在,返回[无此用户] // 前置条件 - 2. 搜索账号是你自己,返回[不能添加自己] // 前置条件 - 3. 搜索的朋友已经是你的好友,返回[该用户已经是你的好友] //1. 得到前置条件状态 Integer status = userService.preconditionSearchFriends(myUserId, friendUsername); //2. 搜索成功,返回搜索用户的信息 if (status == SearchFriendsStatusEnum.SUCCESS.status) { Users user = userService.queryUserInfoByUsername(friendUsername); UsersVO userVO = new UsersVO(); BeanUtils.copyProperties(user, userVO); return IMoocJSONResult.ok(userVO); } else { //3. 搜索失败 String errorMsg = SearchFriendsStatusEnum.getMsgByKey(status); return IMoocJSONResult.errorMsg(errorMsg); } }发送添加好友申请的接口在service中定义添加好友请求记录,保存到数据库的sendFriendRequest方法。传入的是添加好友记录的发送方——用户的Id,以及记录的接收方——想要添加的朋友的名称。【1】首先根据用户名把朋友信息查询出来。【2】然后查询发送好友请求记录表。【3】如果不是你的好友,并且好友记录没有添加,则新增好友请求记录。这样可以保证打你发送了两次请求之后,数据库中仍然只记录一次请求的数据。 @Transactional(propagation = Propagation.REQUIRED) @Override public void sendFriendRequest(String myUserId, String friendUsername) { // 1. 根据用户名把朋友信息查询出来 Users friend = queryUserInfoByUsername(friendUsername); // 2. 查询发送好友请求记录表 Example fre = new Example(FriendsRequest.class); Criteria frc = fre.createCriteria(); frc.andEqualTo(“sendUserId”, myUserId); frc.andEqualTo(“acceptUserId”, friend.getId()); FriendsRequest friendRequest = friendsRequestMapper.selectOneByExample(fre); if (friendRequest == null) { // 3. 如果不是你的好友,并且好友记录没有添加,则新增好友请求记录 String requestId = sid.nextShort(); FriendsRequest request = new FriendsRequest(); request.setId(requestId); request.setSendUserId(myUserId); request.setAcceptUserId(friend.getId()); request.setRequestDateTime(new Date()); friendsRequestMapper.insert(request); } }在controller中创建发送添加好友请求的接口。传入的是添加好友记录的发送方——用户的Id,以及记录的接收方——想要添加的朋友的名称。【0】首先判断传入参数不为空。【1】然后判断前置条件,若为成功则通过userService的sendFriendRequest方法发送好友请求,否则返回失败。 /* * @Description: 发送添加好友的请求 / @PostMapping("/addFriendRequest") public IMoocJSONResult addFriendRequest(String myUserId, String friendUsername) throws Exception { // 0. 判断 myUserId friendUsername 不能为空 if (StringUtils.isBlank(myUserId) || StringUtils.isBlank(friendUsername)) { return IMoocJSONResult.errorMsg(""); } // 前置条件 - 1. 搜索的用户如果不存在,返回[无此用户] // 前置条件 - 2. 搜索账号是你自己,返回[不能添加自己] // 前置条件 - 3. 搜索的朋友已经是你的好友,返回[该用户已经是你的好友] // 1. 判断前置条件 Integer status = userService.preconditionSearchFriends(myUserId, friendUsername); if (status == SearchFriendsStatusEnum.SUCCESS.status) { userService.sendFriendRequest(myUserId, friendUsername); } else { String errorMsg = SearchFriendsStatusEnum.getMsgByKey(status); return IMoocJSONResult.errorMsg(errorMsg); } return IMoocJSONResult.ok(); }最终实现效果接受添加好友申请的接口在service中定义查询好友请求列表的queryFriendRequestList方法。 @Transactional(propagation = Propagation.SUPPORTS) @Override public List<FriendRequestVO> queryFriendRequestList(String acceptUserId) { return usersMapperCustom.queryFriendRequestList(acceptUserId); }在controller中定义接受添加好友请求的接口queryFriendRequests。 /* * @Description: 发送添加好友的请求 */ @PostMapping("/queryFriendRequests") public IMoocJSONResult queryFriendRequests(String userId) { // 0. 判断不能为空 if (StringUtils.isBlank(userId)) { return IMoocJSONResult.errorMsg(""); } // 1. 查询用户接受到的朋友申请 return IMoocJSONResult.ok(userService.queryFriendRequestList(userId)); } 最终实现效果 ...

February 16, 2019 · 2 min · jiezi

Netty+SpringBoot+FastDFS+Html5实现聊天App详解(二)

Netty+SpringBoot+FastDFS+Html5实现聊天App,项目介绍。Netty+SpringBoot+FastDFS+Html5实现聊天App,项目github链接。本章完整代码本节主要讲解聊天App PigChat中关于用户信息处理,以及文件服务器FastDFS的相关操作。包含以下内容:(1)注册与登录功能(2)文件服务器的配置(3)上传用户头像(4)设置用户昵称(5)用户二维码的生成与上传注册与登录功能自定义一个工具类IMoocJSONResult,是后端响应前端的数据结构。包含下面三个属性: // 响应业务状态 private Integer status; // 响应消息 private String msg; // 响应中的数据 private Object data;提供错误响应与正常响应的方法: public static IMoocJSONResult ok(Object data) { return new IMoocJSONResult(data); } public static IMoocJSONResult ok() { return new IMoocJSONResult(null); } public static IMoocJSONResult errorMsg(String msg) { return new IMoocJSONResult(500, msg, null); } public static IMoocJSONResult errorMap(Object data) { return new IMoocJSONResult(501, “error”, data); } public static IMoocJSONResult errorTokenMsg(String msg) { return new IMoocJSONResult(502, msg, null); } public static IMoocJSONResult errorException(String msg) { return new IMoocJSONResult(555, msg, null); }根据数据库所建的表创建对应的pojo包与mapper包,数据库建表详情创建UserController方法,写入进行注册于登录处理的registOrLogin接口。【0】前端传入Users对象,首先判断前端传入的Users对象是否为空。【1】然后通过userService的queryUsernameIsExist方法根据传入的用户名在数据库中进行查询。【1.1】若该用户存在则进行登录,通过userService的queryUserForLogin方法判断前端传入的用户名与密码试凑匹配,若匹配则登录成功,否则登录失败。【1.2】若该用户不存在则记性注册,根据前端传入的信息构建Users对象,通过userService的saveUser将其保存入数据库中。【2】最后构造UsersVO对象,返回给前端。注意:密码需要使用MD5工具类进行加密后再保存到数据库中。 /** * @Description: 用户注册/登录 / @PostMapping("/registOrLogin") public IMoocJSONResult registOrLogin(@RequestBody Users user) throws Exception { // 0. 判断用户名和密码不能为空 if (StringUtils.isBlank(user.getUsername()) || StringUtils.isBlank(user.getPassword())) { return IMoocJSONResult.errorMsg(“用户名或密码不能为空…”); } // 1. 判断用户名是否存在,如果存在就登录,如果不存在则注册 boolean usernameIsExist = userService.queryUsernameIsExist(user.getUsername()); Users userResult = null; if (usernameIsExist) { // 1.1 登录 userResult = userService.queryUserForLogin(user.getUsername(), MD5Utils.getMD5Str(user.getPassword())); if (userResult == null) { return IMoocJSONResult.errorMsg(“用户名或密码不正确…”); } } else { // 1.2 注册 user.setNickname(user.getUsername()); user.setFaceImage(""); user.setFaceImageBig(""); user.setPassword(MD5Utils.getMD5Str(user.getPassword())); userResult = userService.saveUser(user); } // 2.构造UsersVO对象 UsersVO userVO = new UsersVO(); BeanUtils.copyProperties(userResult, userVO); return IMoocJSONResult.ok(userVO); }文件服务器的配置在linux中配置好文件服务器FastDFS后,需要在项目中添加如下配置:(1)在Application同目录下创建FastdfsImporterpackage com.imooc;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.EnableMBeanExport;import org.springframework.context.annotation.Import;import org.springframework.jmx.support.RegistrationPolicy;import com.github.tobato.fastdfs.FdfsClientConfig;/* * 导入FastDFS-Client组件 * * @author tobato * /@Configuration@Import(FdfsClientConfig.class)// 解决jmx重复注册bean的问题@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)public class FastdfsImporter { // 导入依赖组件}(2)在application.properties中添加如下配置:fdfs.soTimeout=1501fdfs.connectTimeout=601fdfs.thumbImage.width=80fdfs.thumbImage.height=80# 192.168.1.70为Linux虚拟机的ip地址fdfs.trackerList[0]=192.168.1.70:22122启动服务命令:/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf/usr/bin/fdfs_storaged /etc/fdfs/storage.conf#查看服务启动情况(23000/22122端口)netstat -lnp |grep fdfscd /usr/local/nginx/sbin./nginx上传用户头像在UserController中添加上传用户头像的uploadFaceBase64接口。【1】前端传入UserBO对象,首先获取前端传来的base64字符串,并通过文件工具类FileUtils的base64ToFile方法将其转换成文件对象保存在本地。【2】将文件对象转换成MultipartFile,并通过fastDFSClient的uploadBase64方法将其上传到文件服务器fastDFS中,打印出服务器返回的路径,我们可以通过这个路径访问这张图片。【3】对返回的路径进行切割后得到缩略图的路径。【4】更新数据库中用户头像信息。 /* * @Description: 上传用户头像 / @PostMapping("/uploadFaceBase64") public IMoocJSONResult uploadFaceBase64(@RequestBody UsersBO userBO) throws Exception { // 1. 获取前端传过来的base64字符串, 然后转换为文件对象再上传 String base64Data = userBO.getFaceData(); // 在本地存储图片的路径 String userFacePath = “C:\” + userBO.getUserId() + “userface64.png”; FileUtils.base64ToFile(userFacePath, base64Data); // 2.上传文件到fastdfs MultipartFile faceFile = FileUtils.fileToMultipart(userFacePath); String url = fastDFSClient.uploadBase64(faceFile); System.out.println(url); // “dhawuidhwaiuh3u89u98432.png”// “dhawuidhwaiuh3u89u98432_80x80.png” // 3.获取缩略图的url String thump = “_80x80.”; String arr[] = url.split("\."); String thumpImgUrl = arr[0] + thump + arr[1]; // 4.更新用户头像 Users user = new Users(); user.setId(userBO.getUserId()); user.setFaceImage(thumpImgUrl); user.setFaceImageBig(url); Users result = userService.updateUserInfo(user); return IMoocJSONResult.ok(result); }设置用户昵称在UserController添加设置用户昵称的setNickname接口。 /* * @Description: 设置用户昵称 */ @PostMapping("/setNickname") public IMoocJSONResult setNickname(@RequestBody UsersBO userBO) throws Exception { Users user = new Users(); user.setId(userBO.getUserId()); user.setNickname(userBO.getNickname()); Users result = userService.updateUserInfo(user); return IMoocJSONResult.ok(result); }用户二维码的生成与上传在UserServiceImpl中引入相关工具类与组件 //二维码工具类 @Autowired private QRCodeUtils qrCodeUtils; //上传文件到fsatDFS需要的组件 @Autowired private FastDFSClient fastDFSClient;在UserServiceImpl保存用户信息的saveUser方法中需要为每一个用户生成一个唯一的二维码。【1】通过二维码工具类qrCodeUtils的createQRCode方法为每个用户生成一个唯一的二维码,第一个参数为生成的二维码存储的路径,第二个参数为二维码中保存的信息,然后将文件转成MultipartFile对象,方便上传操作。【2】通过fastDFSClient的uploadQRCode方法将二维码图片上传到文件服务器中。 @Transactional(propagation = Propagation.REQUIRED) @Override public Users saveUser(Users user) { //生成唯一的id String userId = sid.nextShort(); // 1.为每个用户生成一个唯一的二维码 //本地用来存储生成的二维码图片的路径 String qrCodePath = “C://user” + userId + “qrcode.png”; // 扫描二维码后得到的信息:zhuzhu_qrcode:[username] qrCodeUtils.createQRCode(qrCodePath, “zhuzhu_qrcode:” + user.getUsername()); MultipartFile qrCodeFile = FileUtils.fileToMultipart(qrCodePath); //2.上传文件 String qrCodeUrl = “”; try { qrCodeUrl = fastDFSClient.uploadQRCode(qrCodeFile); } catch (IOException e) { e.printStackTrace(); } user.setQrcode(qrCodeUrl); user.setId(userId); userMapper.insert(user); return user; } ...

February 15, 2019 · 2 min · jiezi