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

简简单单搭建一个oss服务

第一部分:什么是 OSS?

​OSS​​ 的全称是 ​​对象存储服务​​。

你可以把它想象成一个巨大的、无限的、在互联网上的“网盘”,但它是专门为程序(而不是主要为人)来存储和读取文件而设计的。

为了理解它,我们通常把它和另外两种存储方式做对比:

  1. ​块存储​

    • ​比喻​​:就像电脑的硬盘(C盘、D盘)。它被格式化成一种文件系统(如NTFS, ext4),你可以创建文件夹、移动文件、直接修改文件的一部分。
    • ​特点​​:低延迟,常用于安装操作系统、数据库等需要直接读写磁盘块的场景。
    • ​例子​​:你电脑的硬盘、服务器的本地硬盘、SAN。
  2. ​文件存储​

    • ​比喻​​:就像一个公司内部的共享网络驱动器(Network Attached Storage - NAS)。你通过路径(如 \\NAS\部门\项目\报告.doc)来访问文件。
    • ​特点​​:有目录层级,支持文件锁,多人可共享访问。
    • ​例子​​:Windows 网络共享、NFS。
  3. ​对象存储(OSS)​

    • ​比喻​​:一个巨大的仓库。每个文件都是一个独立的“对象”。你不需要关心这个对象放在仓库的哪个货架(路径)上,系统会给你一个唯一的“取件码”(Object Key 或 URL)。你通过这个“取件码”来存或取整个文件。
    • ​核心概念​​:
      • ​对象​​: 文件本身 + 文件的元数据(描述信息,如创建时间、类型) + 一个全局唯一的 ​​Key​​。
      • ​桶​​: 存放对象的容器,你可以把它理解成仓库里的一个区域。桶名在全球必须是唯一的。
      • ​扁平结构​​: 没有真正的文件夹概念。虽然 Key 可以包含类似路径的前缀(如 images/2024/photo.jpg),但这只是为了组织方便,在底层它依然是一个唯一的字符串 Key。
    • ​特点​​:
      • ​海量存储​​: 容量可以轻松扩展到 EB 级别。
      • ​高可靠耐用​​: 数据会自动在多个设备、多个机房备份,防止丢失。
      • ​高可用性​​: 随时可以通过互联网访问。
      • ​RESTful API​​: 使用简单的 HTTP/HTTPS 请求(GET, PUT, DELETE)即可上传下载文件。
      • ​成本低​​: 通常比块存储和文件存储更便宜。

​主流 OSS 服务商​​:阿里云 OSS、腾讯云 COS、AWS S3、微软 Azure Blob Storage 等。


第二部分:怎么做一个简单的 OSS?

搭建一个生产级别、高可用的 OSS(像阿里云那样)极其复杂,涉及分布式系统、集群管理、数据一致性等高级话题。但我们可以​​搭建一个简化版的、单机的 OSS 服务​​来理解其核心原理。

我们的目标是:​​创建一个可以通过 HTTP API 上传、下载、删除文件的服务。​

​技术栈选择:​

  • ​后端语言​​: Python(简单易学,库丰富)
  • ​Web 框架​​: FastAPI(现代,高性能,自动生成 API 文档)
  • ​文件存储​​: 直接使用服务器的本地文件系统
  • ​元数据存储​​: 使用 SQLite 数据库(轻量级)来记录文件的元信息(Key, 文件名, 大小等)
实现步骤:

​第 1 步:项目初始化​

# 创建项目目录
mkdir my_simple_oss
cd my_simple_oss# 创建虚拟环境(可选但推荐)
python -m venv venv
source venv/bin/activate  # Linux/Mac
# venv\Scripts\activate.bat  # Windows# 安装依赖
pip install fastapi uvicorn sqlalchemy python-multipart

​第 2 步:编写代码 (main.py)​

from fastapi import FastAPI, File, UploadFile, HTTPException
from fastapi.responses import FileResponse
import sqlite3
import os
import shutil
from pathlib import Path
from pydantic import BaseModel# 初始化 FastAPI 应用
app = FastAPI(title="我的简易 OSS")# 配置
STORAGE_PATH = "./storage"  # 文件存储的根目录
DB_PATH = "./metadata.db"   # 元数据库路径# 确保存储目录存在
Path(STORAGE_PATH).mkdir(exist_ok=True)# 初始化数据库
def init_db():conn = sqlite3.connect(DB_PATH)cursor = conn.cursor()cursor.execute('''CREATE TABLE IF NOT EXISTS objects (key TEXT PRIMARY KEY,original_filename TEXT,size INTEGER,content_type TEXT,uploaded_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)''')conn.commit()conn.close()# 启动时初始化数据库
init_db()class ObjectItem(BaseModel):key: stroriginal_filename: strsize: intcontent_type: str# 1. 上传文件(创建对象)
@app.post("/objects/{key}")
async def upload_object(key: str, file: UploadFile = File(...)):# 防止路径遍历攻击,确保 key 是安全的if ".." in key or "/" in key:raise HTTPException(status_code=400, detail="Invalid key")file_path = os.path.join(STORAGE_PATH, key)# 保存文件到本地存储with open(file_path, "wb") as buffer:# 读取文件内容并写入,避免大内存占用contents = await file.read()buffer.write(contents)# 将文件元信息保存到数据库conn = sqlite3.connect(DB_PATH)cursor = conn.cursor()try:cursor.execute("INSERT INTO objects (key, original_filename, size, content_type) VALUES (?, ?, ?, ?)",(key, file.filename, len(contents), file.content_type))conn.commit()except sqlite3.IntegrityError:# 如果 key 已存在,我们覆盖它(实际生产环境可能更复杂)os.remove(file_path)raise HTTPException(status_code=409, detail=f"Object with key '{key}' already exists")finally:conn.close()return {"message": "File uploaded successfully", "key": key}# 2. 下载文件(获取对象)
@app.get("/objects/{key}")
async def download_object(key: str):file_path = os.path.join(STORAGE_PATH, key)# 检查文件是否存在if not os.path.isfile(file_path):raise HTTPException(status_code=404, detail="Object not found")# 从数据库获取元信息(例如文件名)conn = sqlite3.connect(DB_PATH)cursor = conn.cursor()cursor.execute("SELECT original_filename, content_type FROM objects WHERE key=?", (key,))row = cursor.fetchone()conn.close()if row is None:raise HTTPException(status_code=404, detail="Object metadata not found")original_filename, content_type = row# 使用 FileResponse 返回文件,并设置正确的下载文件名return FileResponse(path=file_path,filename=original_filename,media_type=content_type)# 3. 列出所有对象(可选,简单实现)
@app.get("/objects/")
async def list_objects():conn = sqlite3.connect(DB_PATH)cursor = conn.cursor()cursor.execute("SELECT key, original_filename, size, content_type FROM objects")rows = cursor.fetchall()conn.close()objects = []for row in rows:key, original_filename, size, content_type = rowobjects.append(ObjectItem(key=key,original_filename=original_filename,size=size,content_type=content_type))return objects# 4. 删除对象
@app.delete("/objects/{key}")
async def delete_object(key: str):file_path = os.path.join(STORAGE_PATH, key)# 删除文件if os.path.isfile(file_path):os.remove(file_path)# 删除元数据conn = sqlite3.connect(DB_PATH)cursor = conn.cursor()cursor.execute("DELETE FROM objects WHERE key=?", (key,))conn.commit()conn.close()return {"message": f"Object '{key}' deleted successfully"}if __name__ == "__main__":import uvicornuvicorn.run(app, host="0.0.0.0", port=8000)

​第 3 步:运行服务​

python main.py

服务会运行在 http://127.0.0.1:8000。访问 http://127.0.0.1:8000/docs 可以看到自动生成的 API 文档界面,你可以在那里直接测试接口。

测试你的简易 OSS

使用 curl 或 Postman 测试:

  1. ​上传文件​​:

    curl -X POST -F "file=@/path/to/your/local/image.jpg" http://127.0.0.1:8000/objects/my-first-image
  2. ​下载文件​​:
    直接浏览器打开 http://127.0.0.1:8000/objects/my-first-image

  3. ​列出文件​​:
    浏览器打开 http://127.0.0.1:8000/objects/

从“简易 OSS”到“生产级 OSS”的差距

我们这个简易 OSS 只是一个教学模型,离真正的云服务相差甚远,主要差距在:

  • ​分布式与高可用​​: 单点故障!服务器挂了服务就没了。生产级 OSS 数据会在多个节点、多个机房冗余存储。
  • ​性能​​: 单机磁盘 I/O 是瓶颈。生产级使用分片上传、CDN 加速、负载均衡。
  • ​安全性​​: 缺少身份认证(AK/SK)、权限控制(Bucket Policy)、加密、防盗链等
  • ​数据一致性​​: 确保在分布式环境下数据读写的一致性非常复杂。
  • ​生命周期管理​​: 自动将旧数据转移到更便宜的归档存储。
  • ​版本控制​​: 防止文件被覆盖或误删。

总结

  • ​OSS 是什么​​: 一个通过 HTTP API 存取海量非结构化数据的服务。
  • ​如何做一个​​:
    • ​使用云服务​​:对于绝大多数应用,直接使用阿里云 OSS、AWS S3 等是最好、最经济的选择。
    • ​自建开源方案​​:如果需要私有化部署,可以考虑 ​​MinIO​​ 或 ​​Ceph​​,它们提供了生产级别的对象存储能力,你可以基于它们搭建自己的 OSS。
    • ​自己从头开发​​:如上所示,可以做一个原型理解概念,但要达到生产级别,需要巨大的工程投入。
http://www.dtcms.com/a/407763.html

相关文章:

  • 做网站简单需要什么网页美工设计的要点分别是什么
  • SQL SERVER 查看锁表
  • 网站链接视频怎么做兴县做网站的公司
  • 专业的网站制作公司哪家好北京网站制作公司兴田德润在那里
  • 【通信】LNA释义
  • html网页设计 静态网页模板 前端html页面模板
  • 前端路由原理及特点
  • 手机里面的网站怎么制作巢湖网 网站
  • 人员徘徊检测的智能视觉分析技术与应用
  • 第三十五天:移除元素
  • 上海网站怎么备案网站开发 注意事项
  • mysql字符串截取,如何在MySQL备份文件中安全截取敏感字符串?
  • RAG技术与应用—基础
  • 英语学习-Saints018
  • 阿里巴巴上面可以做网站wordpress淘客采集
  • 深度学习入门:从神经网络基础到模型训练优化
  • 衡水做网站建设还有那个网站可以做兼职呢
  • 机器人控制:SDO和PDO在实际应用中如何配置和使用?
  • 免费做网站公司内容营销的形式有哪些
  • 【杀鸡焉用牛刀?】基于模板匹配的极简OCR实现
  • 合肥网站建设培训班wordpress采集规则
  • Spring Cloud Gateway 环境属性修改漏洞复现 (CVE-2025-41243)
  • 自然语言编程如何重塑软件开发教育?新人学习路径的辩证思考
  • 金华网站建设公司哪个好12389举报网站建设项目
  • 动态代理与反射
  • VUE 和 jquery 对比总结
  • 免费自学编程的app网站seo诊断的主要内容
  • Modbus TCP转RS485智能网关应用实例:集成工业测温器至云平台的数据采集方案
  • 需求模糊:架构复杂度背后的“隐藏杀手”
  • ARM芯片架构之CoreSight SoC-400组件详解