当前位置: 首页 > news >正文

【项目】云备份系统笔记

服务端:包含多个文件,每个文件代表不同的模块和功能

cloud.conf:配置文件包含

热点文件的时间(30,超过30s不再访问,就不再是热点文件)

服务器的ip和端口(绑定监听)

下载请求的前缀("/download/")

压缩文件的后缀(.lz)

压缩文件的路径("./packdir/",不再是热点文件会主动进行压缩存储)

备份文件的路径("./backdir/",用户端传过来需要保存的文件都在这个文件夹中,超过一定时间不被访问,就会被主动压缩,并且将压缩文件方法哦packdir中)

上传文件的备份信息文件("./cloud.dat" ,存放了已经被备份下来文件的基本信息,文件名)

config.hpp:

就包含一个类,config,是读取配置文件的类,因为配置文件只有一份,所以可以采用单例模式,把config类的构造函数私有化,只能通过一个公共成员函数getinstance()来创建对象(new config()),在类的内部可以调用私有化构造函数,构造函数里面再调用读取配置文件的函数,用自己实现的工具类读取配置文件,将读到的内容放到一个字符串中,然后再将字符串用Json进行序列化,然后给类中的成员变量进行赋值,类中的成员变量就包含了cloud.conf里面包含的信息,一一对应。然后实现了获取每个成员变量的成员函数。

注意:

static Config *GetInstance(){if (_instance == nullptr){_mutex.lock();if (_instance == nullptr){_instance = new Config();}_mutex.unlock();}return _instance;}
  1. 限制实例化:单例模式将类的构造函数设为私有,以防止外部直接创建对象。
  2. 提供访问点:通过一个静态方法(通常是 getInstance)来提供对该唯一实例的访问。
  3. 确保唯一性:使用静态成员变量来存储类的唯一实例,以确保只有一个实例被创建。

所以_instance必须是static修饰,属于整个类且唯一,同样的锁也是一样,只要需要创建这个类的实例,那么多个线程之间用到的是同一把锁。或者说使_mutex成为类级别的资源。

所以这两个成员变量都要在类外面进行初始化,对于_instance可以初始化为nullptr,但是对于锁不需要,因为std::mutex是一个不需要显示初始化的类,在创建时自动处于未锁定状态。所以初始化代码为:

std::mutex Config::_mutex;

为什么进行两次判断是否为nullptr?

第一次:在多线程并发创建实例的情况下,如果其他线程已经创建了,那么该线程可以直接获取实例,不用再次创建。

加锁:如果发现没有实例,就要创建实例,但创建实例的过程只能由一个线程来完成,保证单例模式的原则(不然会有多个线程new config()),因为配置文件资源是唯一的,对于临界区资源一般都要进行加锁保护(防止数据竞争,线程间对_instance的写操作会干扰,出现未定义行为)。

第二次:防止其他线程已经创建实例后,再次创建实例,因为当多个线程同时进入都判断没有实例,然后都会去竞争锁,如果一个线程竞争到锁,把实例创建之后释放锁,其他线程拿到锁,没发现实例已经创建,就会重复创建,所以必须要进行二次检查。

data.hpp:主要是管理备份文件的基本信息,包含数据管理模块(class DataManager)和文件备份信息结构体(BackupInfo)

BackupInfo:包含以下成员变量和通过绝对路径生成backupinfo的构造函数

        public:bool _pack_flag;  //是否被压缩size_t _fsize;    //文件大小time_t _mtime;    //最近修改时间time_t _atime;    //最近访问时间string _real_path;//绝对路径string _pack_path;//压缩存放的路径string _url;      //请求路径

DataManager:

 DataManager (){    pthread_rwlock_init(&_rwlock,nullptr);               _backup_file=Config::GetInstance()->GetBackUpFile();  InitLoad();   };

构造函数包括:初始化读写锁、初始化基本备份信息文件名、

数据管理模块的初始化:读取基本备份信息文件(如果不存在文件就创建)到字符串,对字符串进行反序列化生成多个backupinfo放入到hash表中进行管理,接下来对基本信息的管理变成了对hash表的管理(包括增删查改的操作),从hash表中读取数据要加读锁,对hash进行写操作要加写锁。

  • 读锁 (pthread_rwlock_rdlock):允许多个线程同时持有读锁,适用于并发读取数据的场景。其他线程不能获取写锁,确保数据在读操作期间不会被修改。

  • 写锁 (pthread_rwlock_wrlock):只能有一个线程持有写锁,其他线程无法持有读锁或写锁。这种锁定机制用于数据修改时,确保没有其他线程在修改期间读取或修改数据。

最后还包括了数据的持久化,即把hash表中backinfo同步到基本备份信息文件当中,当hash表中的数据内容发生变化,就要把数据变化也同步到基本备份信息文件。

hot.hpp:包含一个热点管理的类,class HotManager

private:string _back_dir;  //备份文件的存放目录string _pack_dir;  //备份文件压缩之后的存放目录string _pack_suffix;    //压缩文件的后缀int _hot_time;          //超过多少时间没有访问就是非热点文件要进行压缩

该类的构造函数中,也是获取了配置文件的单例,然后从配置文件中获取备份文件的目录和压缩之后的存放目录、热点时间和压缩文件的后缀,同时创建这两个目录。

在RunModule()函数中,是一个死循环,会不断去检测备份文件目录中的文件是否是热点文件,即是否超过_hot_time没有被访问了,如果发现不是热点文件了,或者发现备份文件存在,但是内存数据管理并不存在这个文件的基本信息backinfo(其实就是新上传上来的文件),但不管存不存在文件的基本信息,文件存在且访问时间超过了热点时间,那么就要进行压缩,压缩存放的路径可以通过backinfo中的_pack_path获取,同时对backinfo里面的是否压缩字段进行更新,放入hash表中进行管理。同时每次检测可以休眠一秒,因为如果是空目录的话,每次遍历检查都发现没有文件,那么就会消耗cpu资源。

service.hpp:

绑定了请求路径对应的请求方法,如文件的上传、下载和备份文件基本信息的展示。

下载文件:分为正常下载和断点续传,要让http支持断点续传的功能,那么服务端返回给客户端的响应里面就要包含ETag:自定义请求头(文件名-文件最后一次修改时间-文件大小)和Accept-Ranges:bytes请求头,客户端接受到后,就会把ETag的值保存下来,下次再想服务端发送请求时就会携带上If-Range请求头里面的值就是服务端传给客户端的Etag,但如果没有这个请求头就代表正常下载的请求,不会用到断点续传,如果存在If-Range取到对应的ETag值,还要通过url获取hash表中backinfo中的文件信息来判断该文件最近是否被修改过,如果被修改了,还是重新下载,如果没被修改,才是断点续传。

断点续传:客户端发送请求时会携带Range请求头:start-end,代表请求的数据范围,服务端解析出start和end,然后读取文件中对应范围的数据写入到响应的正文(response的body)当中,然后带上响应头Content-Range:bytes start-end/fsize,同时设置响应状态码为206,代表服务器成功处理了部分 GET 请求。

常用状态码:

1xx:继续,代表客户端应该继续请求

200:ok,请求成功

204:No Content,没有内容,服务器成功处理,但没有返回内容。

206:Partial Content,服务器成功处理了部分get请求

301:永久重定向,请求的资源被永久移动到了新的URL。

302:临时重定向,资源只是临时被移动

304:未修改,请求的资源没有修改,服务器不会返回任何数据

400:客户端请求的语法错误,服务器无法理解

401:要求用户的身份认证

403:禁止,服务器理解客户端的请求,但拒绝执行请求

404:服务器没有找到资源,也可能是服务器拒绝请求

500:服务器内部错误,无法完成请求

501:服务器不具备完成请求的功能

客户端:

cloud.hpp:包含一个backup类,里面实现了备份的功能,也就是备份模块。

bool RunModule(){while (true){FileUtil fu(_back_dir.c_str());vector<string> arry;fu.ScanDirectory(&arry);for (auto& file : arry){if (IsNeedUpload(file)){if (Upload(file) == true){_data->Insert(file, GetFileId(file));}}}Sleep(1);}}

客户端生成一个备份文件夹,只要是放入这个文件夹中的文件,会被备份模块进行管理,该模块会去遍历这个文件夹,把遍历到的文件名放到一个容器中,再对容器进行遍历,也就是对指定文件夹下的所有文件进行遍历,看是否需要上传文件到服务器进行备份,判断的逻辑为:距离上一次修改文件的时间是否已经过去了三秒,如果超过了3秒就把文件进行上传,但存在两种情况,一种情况是文件是新添加进来的需要进行上传备份,内存中不存在这个文件的备份信息,上传文件之后会将备份信息加载到内存用hash表进行管理,一种情况是文件已经被上传过了,内存中已经存在这个文件的备份信息,但是这个文件期间被修改过了,也需要重新上传,所以可以通过备份信息里面的文件标识来判断文件是否被修改过,因为文件标识中包含了文件最后一次修改的时间,如果文件被修改了,那么文件标识就会不同,可以重新上传。

data.hpp:包含一个DataManager的类,进行数据管理,是数据管理模块。

string _back_file;
unordered_map<string, string> _table;

 备份文件名和进行备份信息管理的hash表

InitLoad():从备份信息文件中读取备份信息,信息是以key val\n构成的字符串,key是文件名,val是文件标识(文件名+文件大小+最后一次修改时间),进行反序列化之后存入hash表中,同样以文件名作为key,文件标识作为val,完成数据管理的初始化。

Storage():把hash表中数据持久化(要进行自定义序列化)到备份信息文件当中,每次对hash进行了更新或者新增的操作都要更新备份信息文件。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 部署SAM2遇到的问题
  • JVM理论篇(一)
  • 项目策划书六度自由双足机器人
  • 云计算day33
  • Docker Desktop镜像路径修改一直报错
  • Linux环境下配置jdk、Tomcat和Mysql详解
  • 高性能web服务器4——Nginx反向代理A
  • 工业数采边缘网关: 直击行业痛点,GXF222-4G助您解忧
  • Cesium 全球视角 和 多方案镜头切换
  • webserver使用webbench工具连续压测失败
  • java grpc 使用
  • 关于tresos Studio(EB)的MCAL配置之ADC
  • linux 进程开机自启
  • 从事大模型研发的技术栈和学习路线
  • SX_Git Graph图形化案例详解_20
  • extjs4学习之配置
  • HTTP传输编码增加了传输量,只为解决这一个问题 | 实用 HTTP
  • JavaScript工作原理(五):深入了解WebSockets,HTTP/2和SSE,以及如何选择
  • JavaSE小实践1:Java爬取斗图网站的所有表情包
  • mysql中InnoDB引擎中页的概念
  • php面试题 汇集2
  • Python3爬取英雄联盟英雄皮肤大图
  • Python连接Oracle
  • SpiderData 2019年2月23日 DApp数据排行榜
  • vue 个人积累(使用工具,组件)
  • vue的全局变量和全局拦截请求器
  • 给第三方使用接口的 URL 签名实现
  • 基于Android乐音识别(2)
  • 理解在java “”i=i++;”所发生的事情
  • 每个JavaScript开发人员应阅读的书【1】 - JavaScript: The Good Parts
  • 如何正确配置 Ubuntu 14.04 服务器?
  • 小程序开发之路(一)
  • ​2021半年盘点,不想你错过的重磅新书
  • ​DB-Engines 11月数据库排名:PostgreSQL坐稳同期涨幅榜冠军宝座
  • ​如何防止网络攻击?
  • # linux 中使用 visudo 命令,怎么保存退出?
  • #我与Java虚拟机的故事#连载15:完整阅读的第一本技术书籍
  • (1)SpringCloud 整合Python
  • (AtCoder Beginner Contest 340) -- F - S = 1 -- 题解
  • (LeetCode) T14. Longest Common Prefix
  • (libusb) usb口自动刷新
  • (MTK)java文件添加简单接口并配置相应的SELinux avc 权限笔记2
  • (pt可视化)利用torch的make_grid进行张量可视化
  • (二) Windows 下 Sublime Text 3 安装离线插件 Anaconda
  • (更新)A股上市公司华证ESG评级得分稳健性校验ESG得分年均值中位数(2009-2023年.12)
  • (论文阅读笔记)Network planning with deep reinforcement learning
  • (四)Tiki-taka算法(TTA)求解无人机三维路径规划研究(MATLAB)
  • (原創) 人會胖會瘦,都是自我要求的結果 (日記)
  • (源码分析)springsecurity认证授权
  • (转)http协议
  • (转)拼包函数及网络封包的异常处理(含代码)
  • .NET 8.0 发布到 IIS
  • .net core 调用c dll_用C++生成一个简单的DLL文件VS2008
  • .NET Core 控制台程序读 appsettings.json 、注依赖、配日志、设 IOptions
  • .NET Framework 4.6.2改进了WPF和安全性