对象存储系统 软件详细设计说明书
1.引言
随着生命科学和生物技术的快速发展,海量的生物数据需求和复杂的数据处理场景不断涌现,对高效且可靠的数据存储和管理系统的需求也越来越迫切。为此,设计一套具备分布式架构的生物数据对象存储子系统显得尤为必要,以满足生物数据在大规模存储、快速访问、安全可靠性和数据备份方面的需求。本软件详细设计说明书旨在为生物数据对象存储子系统提供全面、详实的设计参考,确保系统能够在复杂的数据处理和多样化的应用场景下稳定运行。
本说明书将围绕系统的架构设计、模块实现、接口设计、用户界面、异常处理、性能优化和部署等方面进行详细阐述,提供各模块的实现方案与接口细节,帮助开发团队和相关利益方全面了解系统的设计思路与实现细节。
1.1目的
本软件详细设计说明书的目的在于,为生物数据对象存储子系统的设计、开发、实施和维护提供清晰、完整的技术指南。具体目的包括:
为开发人员提供设计指导:通过详细定义系统架构、模块功能、接口设计和性能要求,确保开发团队能够依据设计需求构建和实现符合业务目标的对象存储子系统。
支持系统维护和扩展:本说明书详细描述了各模块的设计、交互和实现细节,为未来的系统维护和扩展提供技术参考。
统一设计理解:通过详细、系统的设计说明,使开发、测试、运维和产品管理等各团队对系统设计的理解保持一致,减少设计偏差和沟通误解。
确保系统的可扩展性与稳定性:结合详细的性能要求和异常处理方案,保证系统在大数据量、高并发环境下稳定运行,并具备良好的扩展能力,以应对未来的业务增长和变化需求。
1.2适用范围
本软件详细设计说明书适用于生物数据对象存储子系统的设计、开发、部署和运维等各个阶段,具体适用范围包括:
系统架构和模块设计:说明书包含系统的整体架构设计、各核心模块的功能描述和设计方案,适用于开发团队在各模块的开发和实现过程中参考。
接口和用户界面设计:本说明书明确了对象存储子系统的内外部接口和用户界面设计方案,适用于系统集成和用户交互界面的开发实现。
性能和异常处理:说明书定义了系统的性能指标、优化策略和异常处理机制,适用于系统的优化和维护,以保障系统的稳定性和高效性。
部署和运维指导:包含系统的部署架构和环境配置要求,为运维人员提供参考,确保系统的高效部署和稳定运行。
此说明书适用于生物数据对象存储子系统的开发团队、测试人员、运维人员以及产品管理和决策人员,用于支持项目实施的全流程技术工作。
1.3术语和缩略语
对象存储:对象存储是一种以非结构化格式(称为对象)存储和管理数据的技术。
存储空间:存储桶,Bucket。
API:应用程序编程接口,是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。
FTP:文件传输协议(File Transfer Protocol,FTP)是用于在网络上进行文件传输的一套标准协议。
S3:Amazon Simple Storage Service(Amazon S3)是一种对象存储服务,Amazon 是最早提供对象存储服务的厂商,制定推出S3协议标准,S3 提供一套S3协议标准的RESTful API以编程方式实现与该服务的交互。
SDK: Software Development Kit的缩写,软件开发工具包。
2.总体设计
2.1背景
本项目以国家生物信息中心数据存储需求为导向,研发分布式对象存储、存储管理调度及统一监控软件,实现数据在热温冷存储介质之间的调度和全生命周期管理,协助管理员实时掌握存储系统的运行、健康、性能状态,有效支撑国家生物信息中心项目数据汇交、共享、计算、服务等业务需求。
而生物数据对象存储子系统作为其中的一个重要建设内容,主要研发分布式对象存储软件,实现海量数据存储以及异步备份、监控、日志与流量统计功能,为用户提供支持http API、ftp、web等方式的数据访问服务。
2.2设计目标和原则
2.2.1设计目标
生物数据对象存储子系统的设计目标包括以下几个方面:
高效存储和访问
实现分布式存储架构,提供PB级别的数据存储能力,支持海量生物数据的高效、可靠存储。通过纠删码技术优化存储空间利用率,并结合多样化访问接口(如HTTP、FTP、S3兼容接口和本地挂载),满足用户的多种访问需求。
数据安全与可靠性
确保数据存储的高可用性与可靠性,设计异地容灾备份机制,确保在数据中心故障或数据损坏的情况下能够快速恢复。同时,支持多副本冗余策略与数据加密,保障数据安全。
高性能和可扩展性
支持系统水平扩展,通过负载均衡与并发处理能力提升系统响应效率,满足海量用户同时访问的性能需求。同时,系统设计允许平滑扩展,在数据量和访问请求增加时,轻松添加更多存储和计算资源。
运维监控与流量统计
提供全面的系统监控、日志管理和流量统计功能,使管理员可以随时监控系统状态,分析访问行为,检测潜在威胁或异常情况,便于故障诊断和系统优化。
灵活适配与兼容性
系统需具备较强的适应性,支持主流数据存储和访问接口的兼容,实现用户无缝迁移和数据流转,特别是兼容AWS S3接口标准,满足对外集成的需求。
2.2.2设计原则
为达到上述目标,系统设计遵循以下原则:
模块化与解耦
各模块之间设计尽量保持独立性,通过清晰的接口定义来实现数据访问、存储、负载均衡、监控等模块的解耦。这种设计不仅有利于后期的维护,还便于系统的扩展和功能的快速迭代。
安全优先
数据安全是生物数据存储的核心要求,系统设计将数据备份、权限管理、数据加密、访问控制等安全措施贯穿于各模块。通过访问控制、日志记录与恶意访问检测,确保用户数据的机密性和完整性。
高效利用资源
采用纠删码技术与多副本冗余的存储策略,以最优的存储资源达到数据冗余的效果,提升存储效率。同时,通过负载均衡、性能监控与优化策略,确保系统在不同负载情况下的高效运行。
灵活扩展与兼容
系统设计时预留扩展空间,使其具备良好的横向扩展能力,适应数据量和用户需求的增长。实现与主流接口协议的兼容性,如AWS S3兼容接口,确保系统具备强大的兼容性和对外集成能力。
用户体验与易用性
从用户访问的便捷性出发设计数据访问接口,提供多种数据访问方式,减少用户访问障碍。同时,系统界面及操作流程清晰明了,提升用户的使用体验。
3.模块设计
3.1整体设计
生物数据对象存储子系统由底层存储模块、数据访问服务模块、数据访问客户端模块、异地容灾备份模块、负载均衡与监控模块、日志和流量统计模块等6个模块共同构成。子系统面向所有用户使用web负载均衡进行访问控制,用户可通过http接口、ftp、web页面和挂载到本地目录的方式访问数据;面向底层存储提供数据库负载均衡;面向管理员提供监控服务、日志分析和流量统计。
(1)底层存储模块:构建一套分布式对象存储系统,池化对象存储服务器中所有机械硬盘,构造36+4纠删码规则的存储集群,实现90%有效存储空间利用率;构建底层分布式关系型数据存储模型,依靠raft协议实现3副本分布式存储,部分机器出现故障时系统可自动切换备份。
(2)数据访问服务模块:研究http API接口、S3 API接口、ftp访问方式,并研发相应的后端服务。
(3)数据访问客户端模块:研发基于浏览器和本地目录挂载方式的客户端适配软件,实现访问对象存储桶,对桶内数据的增删改查等基础操作。
(4)异地容灾备份模块:在异地构建和维护一个备份存储系统,实现多线程高效备份及备份压缩,为用户提供控制备份任务的接口,使目的存储桶的对象副本是源存储桶中对象的精确副本。
(5)负载均衡与监控模块:研究软件系统负载均衡,主要解决用户访问流量压力的均衡,包括:web访问、数据库访问,构建高性能、高可用的服务环境。监控服务器中指标类、日志类的数据进行可视化展示和聚合查询。
(6)日志和流量统计模块:研发相应系统一方面分析用户情况和流量访问情况;另一方面能够检测分析出恶意用户或恶意访问,提升系统安全。
3.1.1数据库设计
对象存储子系统数据库所包含的表:
底层存储模块、数据访问服务模块、数据访问客户端模块、异地容灾备份模块、负载均衡与监控模块、日志和流量统计模块
---各模块按照所用到的数据库表进行添加,这两个表仅供参考
用户表(userprofile)
字段名 | 中文名 | 主键 | 数据类型 | 说明 |
---|---|---|---|---|
id | 主键id | PK | Integer | |
username | 用户名 | String | ||
邮箱 | String | |||
first_name | 名 | String | ||
last_name | 姓 | String | ||
is_staff | 状态码 | Integer | 是否有权登录admin后台(0有,1无) | |
is_active | 账户是否激活 | Integer | 0 未激活,1 已激活 | |
date_joined | 加入时间 | Datetime | ||
telephone | 电话 | String | ||
company | 单位 | String | ||
last_active | 最后活跃日期 | Datetime | ||
third_app | 登录方式 | Integer | 0:本地登录;1:科技云通行证登录 |
存储桶表(bucket)
字段名 | 中文名 | 主键 | 数据类型 | 说明 |
---|---|---|---|---|
id | 主键id | PK | Integer | |
name | 存储桶名称 | String | ||
created_time | 创建时间 | Datetime | ||
modified_time | 修改时间 | Datetime | ||
remarks | 备注信息 | String | ||
lock | 读写锁 | Integer | 0(正常读写),1(锁定写),2(锁定读写) | |
access_permission | 桶访问权限 | Integer | 1(公有只读),2(私有),3(公有读写)) | |
user | 所属用户 | 外键 | Integer | 外键用户表 |
objs_count | 对象数量 | Integer | ||
size | 桶内对象总字节大小 | Integer | ||
stats_time | 统计时间 | Datetime | ||
ftp_enable | ftp可用状态 | String | ||
ftp_password | ftp 访问密码 | String |
存储桶归档表
字段名 | 中文名 | 主键 | 数据类型 | 说明 |
---|---|---|---|---|
id | 主键id | PK | Integer | |
original_id | 存储桶id | Integer | ||
name | 存储桶名称 | String | ||
created_time | 创建时间 | Datetime | ||
modified_time | 修改时间 | Datetime | ||
archive_time | 归档时间 | Datetime | ||
table_name | 存储桶对应的表名 | String | ||
remarks | 备注信息 | String | ||
access_permission | 桶访问权限 | Integer | 1(公有只读),2(私有),3(公有读写)) | |
user | 所属用户 | 外键 | Integer | 外键用户表 |
objs_count | 对象数量 | Integer | ||
size | 桶内对象总字节大小 | Integer | ||
stats_time | 统计时间 | Datetime | ||
ftp_enable | ftp可用状态 | |||
ftp_password | ftp 访问密码 |
存储桶数量限制表
字段名 | 中文名 | 主键 | 数据类型 | 说明 |
---|---|---|---|---|
id | 主键id | PK | Integer | |
limit | 可拥有存储桶上限 | Integer | ||
user | 用户 | 外键 | Integer |
存储桶文件信息表
字段名 | 中文名 | 主键 | 数据类型 | 说明 |
---|---|---|---|---|
id | 主键id | PK | Integer | |
na | 全路径文件名或目录名 | String | ||
na_md5 | 全路径MD5值 | String | ||
name | 文件名或目录名 | String | ||
fod | 文件或目录 | Bool | ||
did | 父节点id | Integer | ||
si | 文件大小 | Integer | ||
ult | 文件上传时间 | Datetime | ||
upt | 文件修改时间 | Datetime | ||
dlc | 下载次数 | Integer | ||
shp | 共享密码 | String | ||
stl | 是否有共享时间限制 | Bool | ||
sst | 共享起始时间 | Datetime | ||
set | 共享终止时间 | Datetime | ||
md5 | md5 | String | ||
share | 分享访问权限 | Integer | ||
json_tags | 用户标签 | Json | ||
sync_start1 | 第一备份点开始时间 | Datetime | ||
sync_end1 | 第一备份点结束时间 | Datetime | ||
pool_id | 指定使用的存储池 | Integer |
存储桶Toekn表
字段名 | 中文名 | 主键 | 数据类型 | 说明 |
---|---|---|---|---|
id | 主键id | PK | Integer | |
key | key | String | ||
bucket | 存储桶 | 外键 | Integer | |
permission | 访问权限 | String | ||
created | 创建时间 | Datetime |
存储桶备份表
字段名 | 中文名 | 主键 | 数据类型 | 说明 |
---|---|---|---|---|
id | 主键id | PK | Integer | |
bucket | 存储桶 | 外键 | Integer | |
endpoint_url | 备份点服务地址 | String | ||
bucket_token | 备份点bucket读写token | String | ||
created_time | 创建时间 | Datetime | ||
modified_time | 修改时间 | Datetime | ||
remarks | 备注 | String | ||
status | 状态 | String | ||
backup_num | 备份点编号 | Integer | ||
error | 错误信息 | String |
CEPH集群配置表
字段名 | 中文名 | 主键 | 数据类型 | 说明 |
---|---|---|---|---|
id | 主键id | PK | Integer | |
name | 存储池名称 | String | ||
cluster_name | CLUSTER_NAME配置名称 | String | ||
user_name | 用户名称 | String | ||
disable_choice | 新数据写入启用 | String | ||
pool_names | POOL存储池名称 | Json | ||
config | ceph集群配置文本 | String | ||
config_file | 配置文件保存路径 | String | ||
keyring | ceph集群keyring文本 | String | ||
keyring_file | keyring文件保存路径 | String | ||
modified_time | 修改时间 | Datetime | ||
priority_stored_value | 优先值 | String | ||
remarks | 备注 | String |
用户操作日志表
字段名 | 中文名 | 主键 | 数据类型 | 说明 |
---|---|---|---|---|
id | 主键id | PK | Integer | |
status_code | 状态码 | Integer | ||
method | 请求方法 | String | ||
operation_content | 操作内容 | String | ||
full_path | 请求路径 | String | ||
message | 备注信息 | String | ||
create_time | 备注信息 | Datetime | ||
username | 请求用户 | String | ||
real_user | cstcloud用户 | String |
3.1.2软件开发环境和运行环境设计
---请相关研发的老师帮忙修改把关,谢谢
(1)软件开发环境
开发主机:操作系统CentOS Stream 10,64bit,8CPU核心,16G内存,硬盘200G。
(2)运行环境
应用服务器:操作系统CentOS Stream 10,64bit,规格8CPU核心,16G内存,硬盘500G。其中6台作为6个服务节点部署WEB服务和FTP服务,1台作为服务的地址对外提供服务,部署Nginx代理到6个web服务节点。
存储服务器:物理存储服务器200台,20PB存储容量,用于部署开源的分布式对象存储系统Ceph和100对主备MySQL数据库。
3.2功能模块设计
3.2.1底层存储模块
(1)纠删码存储集群
1)单元架构
分布式对象存储系统包含控制器、文件系统、监控等服务组件,将所有磁盘池化为一个或多个存储池存储数据;控制器组件主要负责监视集群状态以及平衡数据分布;文件系统组件为文件系统原数据计算、缓存及同步;监控组件负责集群状态监控。
2)访问接口
分布式对象存储系统提供了对象存储、块存储、文件系统等多种访问方式;对象存储支持大规模数据存储,可采用纠删码的方式充分利用磁盘空间并保障数据安全;块存储可以采用多副本策略为虚拟机提供持久化存储;文件系统可让用户远程挂载使用磁盘空间。
3)数据切分与存储策略
分布式对象存储系统在运行时,文件会被切分为若干个指定大小的对象数据放入至存储池中,众多的对象数据会以放置组的形式来分布和管理,存储池可对放置组制定纠删码或多副本等存储策略,控制器可监控放置组状态和平衡放置组的分布。
(2)分布式元数据管理
1)单元架构
采用“地区(zone)-数据中心(datacenter)-机柜(rack)-主机(host)”四层部署结构,部署“三副本”分布式数据库集群,包含3个SQL语句处理节点,3个元数据管理调度节点,3个分布式存储节点。用户可以直接访问或通过程序调用访问数据库。
2)存储层
存储层使用3个节点构建分布式元数据存储,以键值对方式存储,采用Raft协议保证数据一致性,构建3副本可靠存储。
3)计算层
计算层接收并解析客户端的SQL请求,并将表数据映射为键值对。这一层对用户来讲是无状态的,访问任何一个节点都可以获取数据库的全部数据。
4)调度层
调度层进行副本管理、存储数量管理和访问热点管理,使得所有数据能够在存储节点间的均匀分配。同时,为数据库提供全局统一事务时间戳,保证副本数量正确,保证某节点故障仍能提供访问服务。
3.2.2数据访问服务模块
(1)http API接口服务
1)单元架构
采用标准的 RESTful API 设计风格,接口简洁、易用,支持常见的 HTTP 动词进行操作。为普通用户和管理员分别提供独立的 API 接口集合。为所有接口提供认证与授权机制,使用 token 或密钥对进行用户身份验证与存储桶认证。
2)存储桶与文件管理
提供 API 接口来创建、删除存储桶,并提供全局存储桶列表查询功能。支持文件对象的上传、下载、删除操作。文件对象会关联到对应的存储桶和目录。
3)身份认证与权限控制
提供 token 认证机制,支持用户的访问 token 和访问密钥对的创建、刷新与删除。为每个存储桶提供独立的访问认证,支持读写和只读模式的访问控制。提供 FTP 服务的开启与修改 FTP 密码的能力,确保存储桶文件通过 FTP 可安全访问。
4)数据检索与共享管理
支持对存储桶内的文件对象进行关键词模糊检索,提供查询结果返回。存储桶共享、目录共享、文件对象共享这3个粒度,同时提供设置共享时长和共享密码。
(2)S3 API接口服务
1)单元架构
本单元采用多子域名路由配置方案实现S3部分接口功能,预计兼容的S3 API分为3类,包括:存储桶管理、对象管理和分片上传,共18个接口。
(3)ftp服务
1)单元架构
本系统采用分层架构设计,包括前端页面管理、FTP 服务端、身份认证模块、权限控制模块和缓存模块。通过Django框架提供Web管理界面,结合 pyftpdlib 提供高效的FTP服务支持。
2)身份认证
研发ftp身份认证功能模块,开通本单元管理对象存储服务的权限。
3)FTP 访问权限设置
开启存储桶ftp访问权限,并自行设置存储桶的只读访问密码或者读写访问密码,两种密码不得相同。或者用户可以使用默认密码。
(4)分布式http服务运行环境
本单元研发一种快速搭建部署分布式对象存储http服务运行环境的方法,在应用服务器层选择1个节点配置服务端运行条件,运行对象存储系统的web服务端;然后,将相关配置文件批量分发复制至其他节点,即可实现快速部署。在负载均衡层,配置负载均衡策略,指向已部署运行环境的服务器节点,即可实现服务端的高并发能力。该方法为服务配置简单化、便捷化提供思路。
3.2.3数据访问客户端模块
面向科研人员自主研发基于浏览器和本地目录挂载方式的客户端适配软件。因此,本模块研究对象存储客户端软件,将重点研发web前端UI和挂载客户端。用户通过这2种客户端可直观地访问对象存储桶。
1) 模块概述
面向科研人员自主研发基于浏览器和本地目录挂载方式的客户端适配软件。因此,本模块研究对象存储客户端软件,将重点研发web前端UI和挂载客户端。用户通过这2种客户端可直观地访问对象存储桶。
图3.2.3-1 数据访问客户端模块架构图
数据访问服务模块包含web前端UI、挂载客户端2个单元,各单元细节如下所述。
单元1:web前端UI
单元功能:
本单元的目的在于用户能够使用浏览器访问对象存储桶,实现对桶内数据的增删改查等基础操作,提供在线检索、存储桶容量统计、token管理以及访问权限设置等操作。
单元技术方案:
web前端UI是负责处理用户与子系统交互活动的统一媒介,融合多方面功能。要求多个团队并行开发,成果统一运行。传统架构仅创建单一工程,在代码存储、合并、编译时需逐一解决复杂的代码冲突,严重影响开发效率。微前端架构将多团队的工程协作发生点从开发时转移到运行时。各个工程在开发时是互相独立的,仅在运行时发生互相沟通。微前端架构消除了代码冲突,极大提升了开发效率,实现了各个团队独立进行开发、测试、部署、维护。同时满足了前端界面统一运行,保证了开发体验、产品体验超越传统架构。是多团队进行并行开发的最佳实践。
为了给用户更好的使用体验,本单元基于微前端技术架构进行研发,使用TypeScript编程语言和Vue.js 3.2框架,结合quasar组件库进行研发。整体设计了3个微应用,①root-config微应用从全局定义页面路由,以及进行应用的生命周期管理;②Main微应用,路由定义为“/”,是首页路由,主要管理子系统的全局认证和保存全局浏览器状态,后端与认证(比如:通行证API进行交互);③Storage微应用是核心应用,处理用户与对象存储系统之间的业务交互,路由是“/my/storage”,后端调用数据访问服务模块提供的http API接口服务,实现普通用户和管理员用户的前端管理页面。
图 3.2.3-2 前端UI微前端架构图
单元关键技术指标:
支持chrome、edge、Firefox等主流浏览器访问。
单元2:挂载客户端
单元功能:
本单元的目的在于用户能够将对象存储桶挂载至本地目录,便于用户在本地访问。
单元技术方案:
对象存储大文件传输客户端,通过嵌入插件扩展的方式,与对象存储子系统的API适配,在本地文件系统实现文件复制、文件同步、文件移动、文件删除等功能。
图 3.2.3-3 挂载客户端技术架构图
单元关键技术指标:
支持10GB以上大文件传输;支持16线程以上并发传输。
2) 数据访问客户端模块存储方案设计
本模块主要涉及用户侧客户端软件实现,不涉及数据库表的设计。
3) 模块接口
本模块主要涉及用户侧客户端软件实现,不涉及接口设计。
4) 模块界面设计
图3.2.3-4对象存储桶列表示意图
表 2.5–13 对象存储桶列表页面元素表
界面元素名称 | 含义及内容说明 |
---|---|
功能按钮 | “新建存储桶”按钮提供存储桶新建功能;“删除存储桶按钮”提供存储桶删除功能;“检索对象”提供存储桶内数据检索功能 |
存储桶表格 | 表格展示存储桶的关键信息,包括:名称、创建时间、访问权限、ftp状态、读写密码、只读密码、备份和展开详情按钮。表格的部分信息可修改和复制 |
展开详情按钮 | 该详情按钮展开后,可查看存储桶统计信息,可创建/删除存储桶token |
5) 模块主要技术参数和指标
支持edge、chrome、Firefox等主流浏览器访问。
支持10GB以上大文件传输;支持16线程以上并发传输。
3.2.4异地容灾备份模块
异地容灾备份模块后端基于Python的Django框架构建,前端基于TypeScript的微前端架构构建用户交互页面。
业务流程如下:用户开启备份后,后端基于任务调度框架创建备份任务,并将备份任务进行分发执行;根据用户所选压缩算法(如 zlib、lz4、gzip)调用对应库进行压缩;再利用对象存储数据传输接口将压缩后数据并发传输至目标存储桶,期间实时更新进度信息至前端。
图3.2.4-1 异地容灾备份模块架构图
异地容灾备份模块包含备份任务管理、备份任务执行、数据压缩算法管理等3个单元,各单元细节如下所述。
单元1:备份任务管理
备份任务管理单元收集用户输入的备份任务信息,新建备份任务的信息包括源端存储桶、目的端对象存储URL、备份开始时间(立即开始、指定时间开始、暂不开始)等关键信息,备份任务id自动指派;修改备份任务的信息包括:备份开始时间(可以改为立即开始、指定时间开始、暂不开始)等;删除备份任务的信息包括:备份任务id。备份任务管理单元会通过操纵数据库完成数据的增删改查。此信息将由执行程序主动获取,来进行任务的执行或暂停。
图3.2.4-2 备份任务管理单元处理流程图
单元2:备份任务执行
备份任务分发核心是控制节点能远程连接子节点服务器并执行相关操作,需要对子节点有控制权限。子节点需提供多线程并发能力,通过读取备份点元数据信息,并根据命令操作是否采用多线程使子节点执行文件传输策略。
控制节点命令接口:
1.远程连接接口:通过目标ip用户名密码连接子节点;
2.命令生成接口:通过控制节点的配置文件批量生成子节点命令;
3.命令执行接口:控制端会将命令分发到对应的子节点;
4.命令停止、运行、状态查询接口:控制端会通过自己的命令搜集子节点的运行服务状况。
子节点命令接口:
1.命令停止、运行、状态查询接口:对备份程序运行状态的管理;
2.多线程运行接口:备份程序支持单线程和多线程执行的命令操作;
3.备份程序调试接口:在备份任务执行前需要对备份程序做测试,查看提前准备的配置是否可用。
4.文件读取接口:传输文件时需要先重存储服务中将文件读出。
5.数据压缩接口:在传输前对文件进行压缩处理,提高传输速率。
图3.2.4-3 备份任务执行示意图
单元3:数据压缩
采用无损压缩技术和算法,本单元提供4种gzip、bz2、lamz、br压缩类型,客户端提前将文件压缩传到服务端,服务端根据压缩类型适配相应的解压缩算法,并对压缩前后的文件进行md5校验,确保文件的完整性和一致性。
图3.2.4-4 数据压缩传输流程图
3.2.5负载均衡与监控模块
1) 模块概述
负载均衡与监控模块主要研究软件系统负载均衡和硬件集群监控问题。负载均衡主要解决用户访问流量压力的均衡,包括:web访问、数据库访问。通过使用高性能的负载均衡服务器缓解后端业务服务器的压力,同时,保护后端服务器网络地址不被暴露或攻击,对于存储服务的持续稳定运行具有重要意义。与此同时,对硬件集群和软件服务的监控也更进一步的维护了存储服务的稳定运行,方便管理员掌握整个子系统状态。
图3.2.5-1 负载均衡与监控模块架构图
负载均衡与监控模块包含数据库负载均衡、web负载均衡、集群监控、服务监控等4个单元,各单元细节如下所述。
单元1:数据库负载均衡
单元功能:
本单元的功能是根据数据库服务器各节点的连接数量及状态,动态分配新连接的服务器节点,以保证数据库连接的均衡。
单元技术方案:
本单元拟部署一个TCP负载均衡服务,该服务可监控数据库的TCP连接状况,支持轮循调度、最小连接、基于来源、基于URI等各种负载均衡策略。
该负载均衡服务将部署于所有的应用服务器,代理数据库的所有可连接的节点,使得应用服务连接本服务器的均衡服务提供的地址及端口即可,无需知道数据库的真实连接地址,方便应用服务的部署及数据库的调整及优化。
单元关键技术指标:
数据库所有的节点连接数大致相等,某个数据库连接节点出现故障不影响应用服务正常运行。
单元2:web负载均衡
单元功能:
本单元的功能是通过Web均衡器实现Web服务的均衡及高可用性。
单元技术方案:
Web均衡器使用一个虚拟IP来接收客户端的请求,将请求中的源地址进行封装发送给其代理的真实服务器;真实服务器接收到并处理完成请求后,会将响应直接返回给封装的源地址,不再经过Web均衡器,大大提高了整个处理的效率。均衡器定时对其代理的所有真实服务器进行健康检查,将失去连接的真实服务器从发送列表中移除,将恢复连接的真实服务器添加至发送列表。
Web服务的高可用性通过部署两个均衡器实现,两个均衡器通过虚拟路由协议使用IP组播的方式抢占同一个虚拟IP。两个均衡器分为主节点和副节点,正常状态下,主节点会获取到虚拟IP,并使用多播的方式不断向副节点发送心跳信息;当主节点故障时,副节点接收不到主节点发送的心跳信息,会调度自身的接管程序,接管虚拟IP,同样以多播的方式发送心跳信息;当主节点恢复时,副节点接收到了主节点的心跳信息,会自动释放虚拟IP,同时主节点接管虚拟IP。
本单元拟配置双主Web均衡器,即两个节点互为主节点和副节点,两个节点均对所有的真实服务器进行健康检查,再通过配置域名的轮循解析,实现了更高可用的负载均衡。
单元关键技术指标:
所有的真实服务器Web连接数量大致相等,某个真实服务器出现故障不会影响Web服务的正常运行。
单元3:集群监控
单元功能:
监控集群内所有物理服务器、虚拟机的各项指标,如CPU使用率、内存使用率等,当其出现指标异常时及时发送警告通知相关运维人员。
单元技术方案:
本单元拟在所有物理服务器、虚拟机部署一个系统性能指标采集器,采集系统各类资源使用情况如CPU使用率、内存使用率、磁盘空间使用率、网络状态等各项信息,并将采集到的信息处理为时序数据以Web的方式展示出来。
本单元会再部署一套监控系统,定期收集所有采集器展示的数据,并提供查询接口和告警组件。监控系统根据时序数据的特征自定义了一种数据查询语言,可通过该查询语言对各项数据进行加减、连接、汇总、聚合等各种操作。监控系统可配置告警规则,将触发告警规则的数据发送给告警组件,告警组件将告警的信息进行去重分组,通过邮件、微信、钉钉等方式发送到指定的接收者。
单元关键技术指标:
可通过监控系统查询集群所有节点15天内的运行状态,出现异常状态5分钟内通知集群运维人员。
单元4:服务监控
单元功能:
监控分布式存储系统、分布式元数据管理系统、Web等关键服务的状态,当出现指标异常时及时发送警告通知相关运维人员。
单元技术方案:
分布式对象存储系统、分布式元数据管理系统、Web等其它应用服务的监控数据同样使用监控系统接收。
分布式对象存储系统通过配置监控组件,实时监控分布式对象存储系统的各项指标,如磁盘数量、磁盘空间、存储池等各项信息。
在分布式元数据管理系统的元数据管理调度节点、存储节点、SQL语句处理节点部署监控探针和监控数据收集服务,通过服务的端口进行监控数据采集;
Web等其它应用服务,可通过服务使用的端口状态来判断服务运行是否正常。可配置监控系统的端口监控组件来监控指定端口的状态。
单元关键技术指标:
可通过监控系统查询指定服务15天内的运行状态,出现异常状态5分钟内通知服务运维人员。
2) 负载均衡与监控模块存储方案设计
本模块仅为子系统的高可用环境解决方案,不涉及数据库存储方案。
3) 模块接口
本模块仅为子系统的高可用环境解决方案,不涉及接口研发。
4) 模块主要技术参数和指标
数据库所有的节点连接数大致相等,某个数据库连接节点出现故障不影响应用服务正常运行。
所有的真实服务器Web连接数量大致相等,某个真实服务器出现故障不会影响Web服务的正常运行。
可通过监控系统查询集群所有节点15天内的运行状态,出现异常状态5分钟内通知集群运维人员。
可通过监控系统查询指定服务15天内的运行状态,出现异常状态5分钟内通知服务运维人员。
3.2.6日志和流量统计模块
日志与流量统计模块分析系统访问日志,一方面分析用户情况和流量访问情况;另一方面能够检测分析出恶意用户或恶意访问,提升系统安全。
图3.2.6-1 日志与流量统计模块架构图
日志与流量统计模块包含分布式日志采集、基于日志的流量统计2个单元,各单元细节如下所述。
单元1:分布式日志采集
本单元拟部署一个水平可扩展、高可用性的日志聚合系统,其可通过存储压缩非结构化日志和仅索引原数据,使得其操作起来更简单、成本开销更低。日志聚合系统也会提供日志查询语言,可对日志数据进行查询汇总。
日志聚合系统主要包含日志采集器、发送器等组件。采集器可收集保存远程节点日志,远程节点可在应用服务中配置日志的远程地址即可将访问日志集中发送至采集器。发送器可将采集器集中采集到的日志文件发送给日志聚合系统。
日志聚合系统收集到日志后,可将日志数据打包为对象数据存放至底层存储系统。
单元2:基于日志的流量统计
通过对应用服务的访问日志进行统一格式,日志数据被日志聚合系统采集到后,自动对日志文本进行分析,提取日志内容里的用户名、存储桶名、文件名、上传/下载流量、访问时间等信息,保存至数据库。
通过查询数据库中的数据,将查询的数据以指定的业务逻辑汇总统计,以用户、存储桶、文件等层面进行分析,得出该层面在指定时间段内的流量数据。
4.接口设计
---请按照六个模块分别进行填写,现有内容为范例,仅供参考。
4.1 对外部系统提供的接口
4.1.1公共参数
Host | obs.casearth.cn | 备注 |
---|---|---|
Content-Type | application/x-www-form-urlencoded; application/json; multipart/form-data; |
支持的请求数据格式 |
Headers | Authorization | 身份认证标头 |
4.1.2 访问秘钥
4.1.2.1 获取当前用户的所有访问密钥
基本信息 |
||||
接口描述 |
获取当前用户的所有访问密钥,需要通过身份认证权限(如session认证) |
|||
接口URL |
GET /api/{version}/auth-key/ |
|||
请求参数 |
||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
version(path) |
API版本 |
String |
True |
v1 |
offset(query) |
返回结果的初始索引 |
integer |
False |
和limit参数配合使用,当访问密钥数量很多时用于分页 |
limit(query) |
每页返回的结果数量 |
integer |
False |
由于个人访问密钥数量限制,offset和limit参数用不到 |
返回数据 HTTP CODE 200, json格式数据 { "keys": [ { "access_key": "1cc2174a30e511e9a004c800a000655d", "secret_key": "0cf91e146740c73a3959b9ab85195e294b0663df", "user": "869588058@qq.com", "create_time": "2019-02-15 13:46:59", "state": true, "permission": "可读可写" }, { ... }, ] } |
4.1.2.2 创建访问密钥
接口描述 |
创建一个新的访问密钥,需要通过身份认证权限(如session,basic认证),或直接提交用户名和密码 |
|||||
接口URL |
POST /api/{version}/auth-key/ |
|||||
请求参数 |
||||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
||
version(path) |
API版本 |
String |
True |
v1 |
||
请求体 |
||||||
名称 |
描述 |
备注 |
||||
username |
用户名 |
可选 |
||||
password |
密码 |
可选 |
||||
返回数据 { 'code': 201, 'code_text': 'Create key successfully', 'key':{ "access_key": "1cc2174a30e511e9a004c800a000655d", "secret_key": "0cf91e146740c73a3959b9ab85195e294b0663df", "user": "869588058@qq.com", "create_time": "2019-02-15 13:46:59", "state": true, "permission": "可读可写" } } |
4.1.2.3 停用或激活访问密钥
基本信息 |
||||
接口描述 |
停用或激活访问密钥,需要通过身份认证权限 |
|||
接口URL |
PATCH /api/{version}/auth-key/{access_key}/ |
|||
请求参数 |
||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
version(path) |
API版本 |
String |
True |
v1 |
access_key(path) |
访问密钥 |
String |
True |
|
active(query) |
为true时,激活key;为false时停用key |
String |
True |
|
返回数据 { "code": 200, "code_text": "The key has been successfully modified" } |
4.1.2.4 删除访问密钥
基本信息 |
|||||
接口描述 |
删除一个访问密钥,需要通过身份认证权限 |
||||
接口URL |
DELETE /api/{version}/auth-key/{access_key}/ |
||||
请求参数 |
|||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
|
version(path) |
API版本 |
String |
True |
v1 |
|
access_key(path) |
访问密钥 |
String |
True |
||
返回数据 HTTP CODE 204,无数据。 |
4.1.3 用户Token
4.1.3.1 获取当前用户Token
基本信息 |
||||
接口描述 |
获取当前用户的token,需要通过身份认证权限(如session认证) |
|||
接口URL |
GET /api/{version}/auth-token/ |
|||
请求参数 |
||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
version(path) |
API版本 |
String |
True |
v1 |
返回数据 HTTP CODE 200, json格式数据 { “token”: { “key”: “655e0bcc7216d0ccf7d2be7466f94fa241dc32cb”, “user”: “username”, “created”: “2018-12-10 14:04:01” } } |
4.1.3.2 身份验证并返回一个Token
基本信息 |
||||||
接口描述 |
获取当前用户的token,需要通过身份认证权限(如session认证) |
|||||
接口URL |
POST /api/{version}/auth-token/ |
|||||
请求参数 |
||||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
||
version(path) |
API版本 |
String |
True |
v1 |
||
new (query) |
为true时,生成一个新token,旧token立即失效 |
Boolean |
false |
|||
请求体 |
||||||
名称 |
描述 |
备注 |
||||
username |
用户名 |
必填 |
||||
password |
密码 |
必填 |
||||
返回数据 HTTP CODE 200, json格式数据 { "token": { "key": "3d18f8d797077b97ce5dfe5e2d9be5f922dd8903", "user": "xxx@qq.com", "created": "2018-12-24 13:58:13" } } |
4.1.3.3 刷新当前用户Token
基本信息 |
||||||
接口描述 |
刷新当前用户的token,旧token失效,需要通过身份认证权限 |
|||||
接口URL |
PUT /api/{version}/auth-token/ |
|||||
请求参数 |
||||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
||
version(path) |
API版本 |
String |
True |
v1 |
||
请求体 |
||||||
名称 |
描述 |
备注 |
||||
username |
用户名 |
必填 |
||||
password |
密码 |
必填 |
||||
返回数据 HTTP CODE 200, json格式数据 { } |
4.1.4 存储桶Token
4.1.4.1 获取存储桶的token的信息
基本信息 |
||||
接口描述 |
获取存储桶的token信息 |
|||
接口URL |
GET /api/{version}/bucket-token/{token}/ |
|||
请求参数 |
||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
version(path) |
API版本 |
String |
True |
v1 |
token(path) |
存储桶token |
String |
True |
|
返回数据 HTTP CODE 200, json格式数据 { } |
4.1.4.2 删除一个存储桶Token
基本信息 |
|||||
接口描述 |
删除一个存储桶的token |
||||
接口URL |
DELETE /api/{version}/bucket-token/{token}/ |
||||
请求参数 |
|||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
|
version(path) |
API版本 |
String |
True |
v1 |
|
token(path) |
存储桶token |
String |
True |
||
返回数据 HTTP CODE 204,无数据 |
4.1.4.3 创建一个存储桶Token
基本信息 |
||||
接口描述 |
创建一个存储桶的token |
|||
接口URL |
POST /api/{version}/buckets/{id_or_name}/token/create/ |
|||
请求参数 |
||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
version(path) |
API版本 |
String |
True |
v1 |
id_or_name (path) |
存储桶的ID或名称 |
String |
True |
默认为bucket ID,使用bucket name需要通过参数by-name指示 |
by-name (query) |
是否使用存储桶名称 |
Boolean |
False |
true,表示使用bucket name指定bucket;其他值忽略 |
permission (query) |
访问权限 |
String |
True |
Readwrite:读写, readonly:只读 |
返回数据 HTTP CODE 200 { "key": "2228bdcf860517850f9fa8652a362459436b4439", "bucket": { "id": 1546, "name": "s3test000010" }, "permission": "readwrite", "created": "2021-07-22T15:23:54.010231+08:00" } |
4.1.4.4 列举存储桶Token
基本信息 |
||||
接口描述 |
列举存储桶的所有token信息 |
|||
接口URL |
GET /api/{version}/buckets/{id_or_name}/token/list/ |
|||
请求参数 |
||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
version(path) |
API版本 |
String |
True |
v1 |
id_or_name (path) |
存储桶的ID或名称 |
String |
True |
默认为bucket ID,使用bucket name需要通过参数by-name指示 |
by-name (query) |
是否使用存储桶名称 |
Boolean |
False |
true,表示使用bucket name指定bucket;其他值忽略 |
返回数据 HTTP CODE 200, json格式数据 { "count": 2, "tokens": [ { "key": "ea08cc6ed8b645e8a9a26f5c2709d244d01b2ab6", "bucket": { "id": 1546, "name": "s3test000010" }, "permission": "readonly", "created": "2021-06-29T13:45:29.566956+08:00" }, { … } ] } |
4.1.5 存储桶
4.1.5.1 获取存储桶列表
基本信息 |
||||
接口描述 |
获取用户所有存储桶 |
|||
接口URL |
GET /api/{version}/buckets/ |
|||
请求参数 |
||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
version(path) |
API版本 |
String |
True |
v1 |
offset(query) |
返回结果的初始索引 |
integer |
False |
和limit参数配合使用,当访问密钥数量很多时用于分页 |
limit(query) |
每页返回的结果数量 |
integer |
False |
由于个人访问密钥数量限制,offset和limit参数用不到 |
返回数据 HTTP CODE 200, json格式数据 { "count": 2, "next": null, "page": { "current": 1, "final": 1 }, "previous": null, "buckets": [ { "id": 1546, "name": "s3test000010", "user": { "id": 530, "username": "yzhang@cnic.cn" }, "created_time": "2021-01-06T09:43:17.804690+08:00", "access_permission": "公有(可读写)", "ftp_enable": true, "ftp_password": "e35271eab0", "ftp_ro_password": "93d423f5f2", "remarks": "" }, { … } ] } |
4.1.5.2 创建一个存储桶
基本信息 |
||||||
接口描述 |
经过认证的用户创建存储桶 |
|||||
接口URL |
POST /api/{version}/buckets/ |
|||||
请求参数 |
||||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
||
version(path) |
API版本 |
String |
True |
v1 |
||
请求体 |
||||||
名称 |
描述 |
是否必填 |
||||
name |
存储桶名称 |
True |
||||
返回数据 >>Http Code: 状态码201,成功; { 'code': 201, 'code_text': '创建成功', 'data': {}, //请求时提交的数据 'bucket': {} //bucket对象信息,详情参考获取桶列表的响应内容 } >>Http Code: 状态码400,参数有误: { 'code': 400, 'code_text': 'xxx', //错误码表述信息 'data':{}, //请求时提交的数据 'existing': true or false // true表示资源已存在 } |
4.1.5.3 获取存储桶的详细信息
基本信息 |
||||
接口描述 |
通过桶ID或name获取一个存储桶详细信息 |
|||
接口URL |
GET /api/{version}/buckets/{id_or_name}/ |
|||
请求参数 |
||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
version(path) |
API版本 |
String |
True |
v1 |
id_or_name (path) |
存储桶的ID或名称 |
String |
True |
默认为bucket ID,使用bucket name需要通过参数by-name指示 |
by-name (query) |
是否使用存储桶名称 |
Boolean |
False |
true,表示使用bucket name指定bucket;其他值忽略 |
返回数据 { "code": 200, "bucket": { "id": 10, "name": "gggg", "user": { "id": 3, "username": "8695xx0@qq.com" }, "created_time": "2019-01-30 14:24:15", "access_permission": "私有" } } |
4.1.5.4 存储桶访问权限设置
基本信息 |
|||||
接口描述 |
存储桶公有或私有权限设置 |
||||
接口URL |
PATCH /api/{version}/buckets/{id_or_name}/ |
||||
请求参数 |
|||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
|
version(path) |
API版本 |
String |
True |
v1 |
|
id_or_name (path) |
存储桶的ID或名称 |
String |
True |
默认为bucket ID,使用bucket name需要通过参数by-name指示 |
|
by-name (query) |
是否使用存储桶名称 |
Boolean |
False |
true,表示使用bucket name指定bucket;其他值忽略 |
|
public(query) |
访问权限 |
Integer |
True |
设置访问权限, 1(公有),2(私有),3(公有可读可写) |
|
返回数据 { "code": 200, "code_text": "存储桶权限设置成功", "public": 1, "share": [ "http://obs.cstcloud.cn/share/s/s3test000010" ] } |
4.1.5.4 删除一个存储桶
基本信息 |
|||||
接口描述 |
删除一个存储桶 |
||||
接口URL |
DELETE /api/{version}/buckets/{id_or_name}/ |
||||
请求参数 |
|||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
|
version(path) |
API版本 |
String |
True |
v1 |
|
id_or_name (path) |
存储桶的ID或名称 |
String |
True |
默认为bucket ID,使用bucket name需要通过参数by-name指示 |
|
by-name (query) |
是否使用存储桶名称 |
Boolean |
False |
true,表示使用bucket name指定bucket;其他值忽略 |
|
ids(path) |
存储桶ID列表或数组 |
array[Integer] |
False |
删除多个存储桶时,通过此参数传递其他存储桶id |
|
返回数据 http code:204,无数据。 |
4.1.5.4 存储桶备注信息设置
基本信息 |
|||||
接口描述 |
设置存储桶的备注信息 |
||||
接口URL |
PATCH /api/{version}/buckets/{id_or_name}/remark/ |
||||
请求参数 |
|||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
|
version(path) |
API版本 |
String |
True |
v1 |
|
id_or_name (path) |
存储桶的ID或名称 |
String |
True |
默认为bucket ID,使用bucket name需要通过参数by-name指示 |
|
by-name (query) |
是否使用存储桶名称 |
Boolean |
False |
true,表示使用bucket name指定bucket;其他值忽略 |
|
remarks (query) |
备注信息 |
String |
True |
||
返回数据 { "code": 200, "code_text": "存储桶备注信息设置成功" } |
4.1.6 目录
4.1.6.1 列举存储桶内对象和目录
基本信息 |
|||||
接口描述 |
列举存储桶内的对象和目录信息 |
||||
接口URL |
GET /api/{version}/list/bucket/{bucket_name}/ |
||||
请求参数 |
|||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
|
version(path) |
API版本 |
String |
True |
v1 |
|
bucket_name (path) |
存储桶名称 |
String |
True |
||
prefix (query) |
列举指定前缀开头的对象 |
String |
False |
||
delimiter (query) |
分隔符是用于对键进行分组的字符 |
String |
False |
||
continuation-token(query) |
指示使用令牌在该存储桶上继续该列表 |
String |
False |
||
max-keys(query) |
设置响应中返回的最大对象数 |
String |
False |
||
exclude-dir(query) |
排除目录,只列举对象 |
String |
False |
此参数不需要值(忽略),存在即有效 |
|
返回数据 http code 200: { "Name": "ddd", # bucket name "Prefix": "test", "Delimiter": "/", # 只有提交参数delimiter时,此内容才存在 "IsTruncated": "false", "MaxKeys": 1000, "KeyCount": 2, "Next":"http://159.226.91.140:8000/api/v1/list/bucket/ddd/?continuation-token=cD01NQ%3D%3D&delimiter=%2F&max-keys=1", "Previous":"http://159.226.91.140:8000/api/v1/list/bucket/ddd/?continuation-token=cj0xJnA9NTU%3D&delimiter=%2F&max-keys=1", "ContinuationToken": "cD03Ng==", # 只有提交参数continuation-token时,此内容才存在 "NextContinuationToken": "cD01Ng==", # 此内容在"IsTruncated" == "true"时存在 "Contents": [ { "Key": "test/月报", # 对象完整路径 "LastModified": "2021-03-31T01:40:05.190793Z", "ETag": "d41d8cd98f00b204e9800998ecf8427e", "Size": 0, "IsObject": false } ] } http code 404: 当使用delimiter参数时,prefix不存在(对象或目录) { "code": "NoSuchKey", "message": "无效的参数prefix,对象或目录不存在" } |
4.1.6.2 获取存储桶根目录下的文件和文件夹信息
基本信息 |
|||||
接口描述 |
获取存储桶根目录下的文件和文件夹信息 |
||||
接口URL |
GET /api/{version}/dir/{bucket_name}/ |
||||
请求参数 |
|||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
|
version(path) |
API版本 |
String |
True |
v1 |
|
bucket_name (path) |
存储桶名称 |
String |
True |
||
only-obj (query) |
是否只列举对象 |
Boolean |
False |
true(只列举对象,不含目录); 其他值忽略 |
|
offset(query) |
返回结果的初始索引 |
integer |
False |
和limit参数配合使用,当访问密钥数量很多时用于分页 |
|
limit(query) |
每页返回的结果数量 |
integer |
False |
由于个人访问密钥数量限制,offset和limit参数用不到 |
|
返回数据 { "code": 200, "bucket_name": "s3test000010", "dir_path": "", "files": [ { "na": "XDA19030301_148", "name": "XDA19030301_148", "fod": false, "did": 0, "si": 0, "ult": "2021-07-18T14:50:46.633773+08:00", "upt": "2021-07-18T14:50:46.633856+08:00", "dlc": 0, "download_url": "", "access_permission": "公有", "access_code": 1, "md5": "d41d8cd98f00b204e9800998ecf8427e" }, { … } ], "count": 14, "next": null, "page": { "current": 1, "final": 1 }, "previous": null } |
4.1.6.3 获取一个目录下的文件和文件夹信息
基本信息 |
|||||
接口描述 |
获取一个目录下的文件和文件夹信息 |
||||
接口URL |
GET /api/{version}/dir/{bucket_name}/{dirpath}/ |
||||
请求参数 |
|||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
|
version(path) |
API版本 |
String |
True |
v1 |
|
bucket_name (path) |
存储桶名称 |
String |
True |
||
only-obj (query) |
是否只列举对象 |
Boolean |
False |
true(只列举对象,不含目录); 其他值忽略 |
|
offset(query) |
返回结果的初始索引 |
integer |
False |
和limit参数配合使用,当访问密钥数量很多时用于分页 |
|
limit(query) |
每页返回的结果数量 |
integer |
False |
由于个人访问密钥数量限制,offset和limit参数用不到 |
|
dirpath(path) |
目录绝对路径 |
String |
True |
||
返回数据 { |
4.1.6.4 创建一个目录
基本信息 |
|||||
接口描述 |
在存储桶下创建目录文件夹 |
||||
接口URL |
POST /api/v1/dir/{bucket_name}/{dirpath}/ |
||||
请求参数 |
|||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
|
bucket_name (path) |
存储桶名称 |
String |
True |
||
dirpath(path) |
目录绝对路径 |
String |
True |
||
返回数据 >>Http Code: 状态码201,创建文件夹成功: { 'code': 201, 'code_text': '创建文件夹成功', 'data': {}, //请求时提交的数据 'dir': {}, //新目录对象信息 } >>Http Code: 400 401 403 404 500 { "code": "xxx", // NoSuchBucket、AccessDenied、BadRequest、BucketLockWrite "code_text": "" } |
4.1.6.4 设置目录访问权限
基本信息 |
|||||
接口描述 |
为目录设置访问权限,包括:私有、公有只读、公有可读可写 |
||||
接口URL |
PATCH /api/{version}/dir/{bucket_name}/{dirpath}/ |
||||
请求参数 |
|||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
|
version(path) |
API版本 |
String |
True |
v1 |
|
bucket_name (path) |
存储桶名称 |
String |
True |
||
dirpath(path) |
目录绝对路径 |
String |
True |
||
share(query) |
设置目录访问权限 |
Integer |
True |
0(私有),1(公有只读),2(公有可读可写) |
|
days(query) |
公开分享天数 |
Integer |
False |
(share=1或2时有效),0表示永久公开,负数表示不公开,默认为0 |
|
password (query) |
分享密码 |
String |
False |
此参数不存在,表示不设密码;可指定4-8字符;若为空,随机分配密码 |
|
返回数据 { } |
4.1.6.5 删除一个目录
基本信息 |
|||||
接口描述 |
删除目录 |
||||
接口URL |
DELETE /api/{version}/dir/{bucket_name}/{dirpath}/ |
||||
请求参数 |
|||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
|
version(path) |
API版本 |
String |
True |
v1 |
|
bucket_name (path) |
存储桶名称 |
String |
True |
||
dirpath(path) |
目录绝对路径 |
String |
True |
||
返回数据 http code 204,删除成功,无数据。 |
4.1.7 FTP
4.1.7.1 开启或关闭存储桶ftp访问限制
基本信息 |
|||||
接口描述 |
存储桶ftp是否开启的开关 |
||||
接口URL |
PATCH /api/{version}/ftp/{bucket_name}/ |
||||
请求参数 |
|||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
|
version(path) |
API版本 |
String |
True |
v1 |
|
bucket_name (path) |
存储桶名称 |
String |
True |
||
enable(query) |
是否开启ftp访问 |
Boolean |
False |
true(开启);false(关闭) |
|
password (query) |
读写密码 |
String |
False |
||
ro_password (query) |
只读密码 |
String |
False |
||
返回数据 { "code": 200, "code_text": "ftp配置成功", "data": { # 请求时提交的数据 "enable": xxx, # 此项提交时才存在 "password": xxx # 此项提交时才存在 "ro_password": xxx # 此项提交时才存在 } } |
4.1.8 JWT
4.1.8.1 刷新获取新的accessJWT
基本信息 |
||||||
接口描述 |
通过refresh JWT获取新的access JWT |
|||||
接口URL |
POST /api/{version}/jwt-refresh/ |
|||||
请求参数 |
||||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
||
version(path) |
API版本 |
String |
True |
v1 |
||
请求体 |
||||||
名称 |
描述 |
备注 |
||||
refresh |
刷新值 |
必填 |
||||
返回数据 http 200: { "access": "xxx" } |
4.1.8.2 校验JWT是否有效
基本信息 |
||||||
接口描述 |
校验JWT是否有效 |
|||||
接口URL |
POST /api/{version}/jwt-verify/ |
|||||
请求参数 |
||||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
||
version(path) |
API版本 |
String |
True |
v1 |
||
请求体 |
||||||
名称 |
描述 |
备注 |
||||
token |
string |
必填 |
||||
返回数据 http 200: 无内容 |
4.1.8.3 获取JWT
基本信息 |
||||||
接口描述 |
登录认证,获取JWT |
|||||
接口URL |
POST /api/{version}/jwt/ |
|||||
请求参数 |
||||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
||
version(path) |
API版本 |
String |
True |
v1 |
||
请求体 |
||||||
名称 |
描述 |
备注 |
||||
username |
string |
必填 |
||||
password |
string |
必填 |
||||
返回数据 access jwt有效时长8h,refresh jwt有效时长2days; http 200: { "refresh": "xxx.xxx.xxx", # refresh JWT, 此JWT通过刷新API可以获取新的access JWT "access": "xxx.xxx.xxx" # access JWT, 用于身份认证,header 'Authorization Bearer } http 401: { "detail": "No active account found with the given credentials" } |
4.1.9 文件对象
4.1.9.1 获取对象或目录元数据
基本信息 |
|||||
接口描述 |
获取对象或目录的元数据信息 |
||||
接口URL |
GET /api/{version}/metadata/{bucket_name}/{path}/ |
||||
请求参数 |
|||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
|
version(path) |
API版本 |
String |
True |
v1 |
|
bucket_name (path) |
存储桶名称 |
String |
True |
||
path(path) |
对象或目录绝对路径 |
String |
True |
||
返回数据 >>Http Code: 状态码200,成功: { "code": 200, "bucket_name": "xxx", "dir_path": "xxx", "code_text": "获取元数据成功", "obj": { "na": "upload/Firefox-latest.exe", # 对象或目录全路径名称 "name": "Firefox-latest.exe", # 对象或目录名称 "fod": true, # true(文件对象);false(目录) "did": 42, # 父目录节点id "si": 399336, # 对象大小,单位字节; 目录时此字段为0 "ult": "2019-02-20T13:56:25+08:00", # 创建时间 "upt": "2019-02-20T13:56:25+08:00", # 最后修改时间; 目录时此字段为空 "dlc": 2, # 下载次数; 目录时此字段为0 "download_url": "http://10.0.86.213/obs/gggg/upload/Firefox-latest.exe", # 对象下载url; "access_permission": "私有" # 访问权限,‘私有’或‘公有’; 目录此字段为空 }, "info": { # 目录时为null "rados": [ # 对象对应rados信息,格式:iharbor:{cluster_name}/{pool_name}/{rados-key} "iharbor:ceph/obs/217_12", # 大小为 chunk_size "iharbor:ceph/obs/217_12_1", # 大小为 chunk_size ... "iharbor:ceph/obs/217_12_N", # 最后一个数据块大小=(size – chunk_size * N);N = len(rados数组) - 1 ], "chunk_size": 2147483648, # 对象分片(rados)的大小 "size": 399336, # 对象大小Byte "filename": "Firefox-latest.exe" # 对象名称 } } |
4.1.9.2 创建一个空对象元数据
基本信息 |
|||||
接口描述 |
创建一个空对象元数据 |
||||
接口URL |
POST /api/{version}/metadata/{bucket_name}/{path}/ |
||||
请求参数 |
|||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
|
version(path) |
API版本 |
String |
True |
v1 |
|
bucket_name (path) |
存储桶名称 |
String |
True |
||
path(path) |
对象或目录绝对路径 |
String |
True |
||
返回数据 { |
4.1.9.3 移动或重命名一个对象
基本信息 |
|||||
接口描述 |
移动或重命名一个对象 |
||||
接口URL |
POST /api/{version}/move/{bucket_name}/{objpath}/ |
||||
请求参数 |
|||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
|
version(path) |
API版本 |
String |
True |
v1 |
|
bucket_name (path) |
存储桶名称 |
String |
True |
||
objpath(path) |
文件对象绝对路径 |
String |
True |
||
move_to (query) |
移动对象到此目录路径下 |
String |
false |
/或空字符串表示桶下根目录 |
|
rename (query) |
重命名对象的新名称 |
String |
false |
||
返回数据 { |
4.1.9.4 分片上传文件对象v1
基本信息 |
|||||
接口描述 |
通过文件对象绝对路径,分片上传文件对象 |
||||
接口URL |
POST /api/{version}/obj/{bucket_name}/{objpath}/ |
||||
请求参数 |
|||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
|
version(path) |
API版本 |
String |
True |
v1 |
|
bucket_name (path) |
存储桶名称 |
String |
True |
||
objpath(path) |
文件对象绝对路径 |
String |
True |
||
chunk_offset (formdata) |
偏移量 |
Integer |
True |
上传文件块在整个文件中的起始位置(bytes偏移量),类型int |
|
chunk_size (formdata) |
文件块大小 |
Integer |
True |
上传文件块的字节大小,类型int |
|
chunk (formdata) |
文件分片的二进制数据块,文件或类文件对象 |
file |
False |
文件分片的二进制数据块,文件或类文件对象,如JS的Blob对象 |
|
reset (query) |
重置按钮 |
Boolean |
False |
reset=true时,如果对象已存在,重置对象大小为0 |
|
返回数据 Http Code: 状态码200:上传成功无异常时,返回数据: { "chunk_offset": 0, # 请求参数 "chunk": null, "chunk_size": 34, # 请求参数 "created": true # 上传第一个分片时,可用于判断对象是否是新建的,True(新建的) } |
4.1.9.5 上传一个完整对象v1
基本信息 |
|||||
接口描述 |
上传一个完整对象, 如果同名对象已存在,会覆盖旧对象; |
||||
接口URL |
PUT /api/{version}/obj/{bucket_name}/{objpath}/ |
||||
请求参数 |
|||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
|
version(path) |
API版本 |
String |
True |
v1 |
|
bucket_name (path) |
存储桶名称 |
String |
True |
||
objpath(path) |
文件对象绝对路径 |
String |
True |
||
file (formdata) |
文件分片的二进制数据块,文件或类文件对象 |
file |
False |
文件分片的二进制数据块,文件或类文件对象,如JS的Blob对象 |
|
返回数据 { } |
4.1.9.6 对象共享或私有权限设置
基本信息 |
|||||
接口描述 |
对象共享或私有权限设置 |
||||
接口URL |
PATCT /api/{version}/obj/{bucket_name}/{objpath}/ |
||||
请求参数 |
|||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
|
version(path) |
API版本 |
String |
True |
v1 |
|
bucket_name (path) |
存储桶名称 |
String |
True |
||
objpath(path) |
文件对象绝对路径 |
String |
True |
||
share (query) |
分享访问权限 |
Integer |
True |
分享访问权限,0(不分享禁止访问),1(分享只读),2(分享可读可写) |
|
days (query) |
对象公开分享天数 |
Integer |
False |
share != 0时有效,0表示永久公开,负数表示不公开,默认为0 |
|
password (query) |
分享密码 |
String |
False |
此参数不存在,不设密码;可指定4-8字符;若为空,随机分配密码 |
|
返回数据 { } |
4.1.9.7 删除一个对象
基本信息 |
|||||
接口描述 |
删除对象 |
||||
接口URL |
DELETE /api/{version}/obj/{bucket_name}/{objpath}/ |
||||
请求参数 |
|||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
|
version(path) |
API版本 |
String |
True |
v1 |
|
bucket_name (path) |
存储桶名称 |
String |
True |
||
objpath(path) |
文件对象绝对路径 |
String |
True |
||
返回数据 http code 204:无数据。 |
4.1.9.8 分片上传文件对象v2
基本信息 |
|||||
接口描述 |
通过文件对象绝对路径,分片上传文件对象 |
||||
接口URL |
POST /api/{version}/obj/{bucket_name}/{objpath}/ |
||||
请求参数 |
|||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
|
version(path) |
API版本 |
String |
True |
V2 |
|
bucket_name (path) |
存储桶名称 |
String |
True |
||
objpath(path) |
文件对象绝对路径 |
String |
True |
||
offset (query) |
偏移量 |
Integer |
True |
分片数据的写入偏移量 |
|
Content-MD5 (header) |
文件的md5值 |
String |
True |
文件对象hex md5 |
|
reset (query) |
重置按钮 |
Boolean |
False |
reset=true时,如果对象已存在,重置对象大小为0 |
|
data (body) |
对象二进制数据 |
string($binary) |
True |
||
返回数据 Http Code: 状态码200:上传成功无异常时,返回数据: { } |
4.1.9.9 分片上传文件对象v2
基本信息 |
|||||
接口描述 |
上传一个完整对象, 如果同名对象已存在,会覆盖旧对象; |
||||
接口URL |
PUT /api/{version}/obj/{bucket_name}/{objpath}/ |
||||
请求参数 |
|||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
|
version(path) |
API版本 |
String |
True |
V2 |
|
bucket_name (path) |
存储桶名称 |
String |
True |
||
objpath(path) |
文件对象绝对路径 |
String |
True |
||
data (body) |
对象二进制数据 |
string($binary) |
True |
||
Content-MD5 (header) |
文件的md5值 |
String |
True |
文件对象hex md5 |
|
返回数据 Http Code: 状态码200:上传成功无异常时,返回数据: { } |
4.1.10 文件对象下载
4.1.10.1 获取对象或目录元数据
基本信息 |
|||||
接口描述 |
浏览器端下载文件对象,公共文件对象或当前用户(如果用户登录了)文件对象下载,没有权限下载非公共文件对象或不属于当前用户文件对象 |
||||
接口URL |
GET /share/obs/{objpath}/ |
||||
请求参数 |
|||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
|
objpath(path) |
文件对象绝对路径 |
String |
True |
以存储桶名称开头文件对象绝对路径 |
|
p (query) |
分享密码 |
string |
False |
||
返回数据 >>Http Code: 状态码200: 返回FileResponse对象,bytes数据流; >>Http Code: 状态码206 Partial Content: 返回FileResponse对象,bytes数据流; |
4.1.10.2 下载文件对象,自定义读取对象数据块
基本信息 |
|||||
接口描述 |
通过文件对象绝对路径,下载文件对象,或者自定义读取对象数据块 |
||||
接口URL |
GET /api/{version}/obj/{bucket_name}/{objpath}/ |
||||
请求参数 |
|||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
|
version(path) |
API版本 |
String |
True |
v1 |
|
bucket_name (path) |
存储桶名称 |
String |
True |
||
objpath(path) |
文件对象绝对路径 |
String |
True |
||
offset (query) |
偏移量 |
Integer |
false |
要读取的文件块在整个文件中的起始位置(bytes偏移量) |
|
size (query) |
文件块大小 |
Integer |
false |
||
返回数据 *注: 1. offset && size参数校验失败时返回状态码400和对应参数错误信息,无误时,返回bytes数据流 2. 不带参数时,返回整个文件对象; >>Http Code: 状态码200: evhb_obj_size,文件对象总大小信息,通过标头headers传递:自定义读取时:返回指定大小的bytes数据流; >>Http Code: 400 401 403 404 500 { 'code': "NoSuchKey", // AccessDenied、BadRequest、BucketLockWrite 'code_text': '参数有误' } |
4.1.11 检索
4.1.11.1 检索存储桶内对象
基本信息 |
|||||
接口描述 |
检索存储桶内对象 |
||||
接口URL |
GET /api/{version}/search/object/ |
||||
请求参数 |
|||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
|
version(path) |
API版本 |
String |
True |
V1 |
|
bucket (query) |
检索的存储桶名称 |
String |
True |
||
search(query) |
检索的对象关键字 |
String |
True |
||
offset(query) |
返回结果的初始索引 |
integer |
False |
和limit参数配合使用,当访问密钥数量很多时用于分页 |
|
limit(query) |
每页返回的结果数量 |
integer |
False |
由于个人访问密钥数量限制,offset和limit参数用不到 |
|
返回数据 >>Http Code: 状态码200: { "bucket": "testcopy", "files": [ { "na": "abc.py", "name": "abc.py", "fod": true, "did": 0, "si": 35, "ult": "2020-12-18T18:02:45.715877+08:00", "upt": "2021-03-01T16:56:10.524571+08:00", "dlc": 0, "download_url": "http://xxx/share/obs/testcopy/abc.py", "access_permission": "私有", "access_code": 0, "md5": "585e699b26602e7dd6054798d8c22d9b" } ], "count": 2, "next": null, "page": { "current": 1, "final": 1 }, "previous": null } |
4.1.12 共享
4.1.12.1 获取对象或目录的分享链接
基本信息 |
|||||
接口描述 |
获取对象或目录的分享链接 |
||||
接口URL |
GET /api/v1/share/{bucket_name}/{path}/ |
||||
请求参数 |
|||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
|
bucket_name (path) |
存储桶名称 |
String |
True |
||
path(path) |
对象或目录的绝对路径 |
String |
True |
||
返回数据 >>Http Code: 状态码200: { "share_uri": "http://159.226.91.140:8000/share/s/ddd/ggg", "is_obj": false, # 对象或目录 "share_code": "c32b" # 分享密码; is_obj为true或者未设置分享密码时此内容不存在 } |
4.1.12.2 获取分享目录下的子目录和文件对象列表
基本信息 |
|||||
接口描述 |
获取分享目录下的子目录和文件对象列表 |
||||
接口URL |
GET /s/list/{share_base}/ |
||||
请求参数 |
|||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
|
share_base (path) |
分享根目录 |
String |
True |
以存储桶名称开头的目录的绝对路径 |
|
subpath (query) |
子目录路径,list此子目录 |
String |
False |
||
p(query) |
分享密码 |
String |
False |
||
返回数据 >>Http Code: 状态码200: { "bucket": "testcopy", "files": [ { "na": "abc.py", "name": "abc.py", "fod": true, "did": 0, "si": 35, "ult": "2020-12-18T18:02:45.715877+08:00", "upt": "2021-03-01T16:56:10.524571+08:00", "dlc": 0, "download_url": "http://xxx/share/obs/testcopy/abc.py", "access_permission": "私有", "access_code": 0, "md5": "585e699b26602e7dd6054798d8c22d9b" } ], "count": 2, "next": null, "page": { "current": 1, "final": 1 }, "previous": null } |
4.1.12.3 下载分享的目录下的文件对象
基本信息 |
|||||
接口描述 |
下载分享的目录下载的文件对象,支持断点续传 |
||||
接口URL |
GET /s/{objpath}/ |
||||
请求参数 |
|||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
|
objpath (path) |
分享根目录 |
String |
True |
以存储桶名称开头的目录的绝对路径 |
|
subpath (query) |
子目录路径 |
String |
True |
分享根目录下的对象相对子路径 |
|
返回数据 >>Http Code: 状态码200: 返回FileResponse对象,bytes数据流; >>Http Code: 状态码206 Partial Content: 返回FileResponse对象,bytes数据流; |
4.1.13 统计
4.1.13.1 获取一个存储桶资源统计信息
基本信息 |
|||||
接口描述 |
获取一个存储桶资源统计信息 |
||||
接口URL |
GET /api/{version}/stats/bucket/{bucket_name}/ |
||||
请求参数 |
|||||
名称 |
描述 |
类型 |
是否必填 |
备注 |
|
version(path) |
API版本 |
String |
True |
V1 |
|
bucket_name (path) |
存储桶名称 |
String |
True |
||
返回数据 >>Http Code: 状态码200: { "stats": { "space": 12500047770969, # 桶内对象总大小,单位字节 "count": 5000004, # 桶内对象总数量 }, "stats_time": "2020-03-04T06:01:50+00:00", # 统计时间 "code": 200, "bucket_name": "xxx" # 存储桶名称 } |
4.1.13.2 获取当前用户资源统计信息
基本信息 |
|
接口描述 |
获取当前用户的资源统计信息 |
接口URL |
GET /api/{version}/stats/user/ |
返回数据 >>Http Code: 状态码200: { "code": 200, "space": 12991806596545, # 已用总容量,byte "count": 5864125, # 总对象数量 "buckets": [ # 每个桶的统计信息 { "stats": { "space": 16843103, # 桶内对象总大小,单位字节 "count": 4 # 桶内对象总数量 }, "stats_time": "2020-03-04T06:01:50+00:00", # 统计时间 "bucket_name": "wwww" # 存储桶名称 }, { "stats": { "space": 959820827, "count": 17 }, "stats_time": "2020-03-04T06:01:50+00:00", "bucket_name": "gggg" }, ] } |
5.部署设计
---请研发并部署系统的老师帮忙看看这部分是否需要修改。
5.1部署架构
子系统运行拓扑结构由纠删码存储集群、元数据管理集群、Web服务器(包含http API服务、S3 API服务、FTP服务)、Web前端UI服务器、备份任务管理服务器、备份任务执行服务器、Web负载均衡服务器、集群/服务监控服务器、日志收集服务器,以及数据库负载均衡器、节点指标采集器、日志收集器。各项服务/服务器部署情况如下:
纠删码存储集群:需3台服务器部署控制器组件服务、1台服务器部署监控组件服务、所有的服务器部署磁盘服务;
元数据管理集群:需3台虚拟机部署应用服务;
Web服务器:所有的服务器部署Web服务、配置TCP负载均衡器,配置日志格式及日志采集器地址;
Web前端UI服务器:需1台虚拟机配置应用服务;
备份任务管理服务器:需1台服务器部署备份任务管理程序;
备份任务执行服务器:所有服务器的部署备份任务执行程序;
Web负载均衡服务器:需2台虚拟机配置Web均衡器;
集群/服务监控服务器:需配置1台虚拟机部署监控系统,所有服务器及所有虚拟机配置指标采集器;
日志收集服务器:需配置1台虚拟机部署日志聚合系统,配置1台虚拟机配置日志采集器和发送器。
5.2环境配置
物理节点 | 运行环境 |
---|---|
Web负载均衡服务器 | Linux Python3.12 |
Web服务器 | Linux Python3.12 |
数据库服务器 | Linux Python3.12 |
纠删码存储服务器 | Linux |
日志收集服务器 | Linux Python3.12 |
监控服务器 | Linux Python3.12 |
备份任务管理服务器 | Linux Python3.12 |