【手写OSS】第1章:项目概述与Express+Ts环境搭建

在当今数字化时代,数据的存储和管理变得至关重要。随着数据量的不断增长,企业和个人用户对高效、安全、可靠的存储解决方案的需求愈发迫切。对象存储系统作为一种新型的存储架构,以其高扩展性、灵活性和易管理性,成为了现代存储解决方案的首选。

瞎编的,就是硬想写~

但是你如果想要借鉴一下到方案中,那还是妥妥的

本章将带领你开始设计并实现一个类似于阿里云OSS的对象存储系统。我们将从零开始,搭建一个完整的项目开发环境,并介绍如何使用Express和TypeScript构建项目的基础结构。通过本章的学习,你将掌握初始化和配置TypeScript项目、安装和配置Express框架、设计项目目录结构以及配置TypeScript编译的基本技能,为后续开发打下坚实的基础。

第1章:项目概述与环境搭建

1.1 项目介绍及目标

1.1.1 详细介绍对象存储系统的用途和优势

对象存储系统是一种用于存储和管理大量非结构化数据的存储架构。其主要用途和优势包括:

  • 高扩展性:对象存储系统能够轻松扩展以容纳海量数据,而不会影响系统的性能。它适合存储大规模的非结构化数据,如图片、视频、备份文件等。
  • 灵活性:对象存储使用键值对(Key-Value)存储数据,可以灵活地管理和访问文件。每个对象都拥有唯一的标识符(Object Key),便于检索。
  • 持久性和可靠性:通过数据冗余和副本机制,对象存储系统确保数据的高可用性和持久性。
  • 易管理性:对象存储系统通常提供丰富的API接口,支持多种编程语言和工具,使得数据管理更加便捷。
  • 成本效益:相比传统的块存储和文件存储,对象存储在处理大规模数据时更具成本效益。
1.1.2 为什么选择自己构建而不是使用第三方服务

尽管使用第三方存储服务(如AWS S3、阿里云OSS)可以省去很多开发工作,但自行构建对象存储系统也有其独特的优势:

  • 灵活性和可控性:自建系统可以根据具体需求进行定制,完全掌控系统的设计、实现和部署。
  • 成本控制:在数据量极大的情况下,自建存储系统可能比长期使用第三方服务更具成本效益。
  • 学习和成长:构建一个完整的对象存储系统可以极大地提升开发者的技术能力,深入理解存储系统的原理和实现。
  • 数据安全和隐私:自建系统可以完全掌握数据的存储和传输,避免数据外泄的风险。
1.1.3 项目短期和长期目标
  • 短期目标(MVP)

    • 实现基本的文件上传、下载和管理功能。
    • 提供用户认证和权限控制。
    • 支持元数据管理和基本的安全机制(如HTTPS加密)。
    • 搭建基本的监控和日志系统。
  • 长期目标

    • 支持大规模数据的分布式存储和多副本机制。
    • 提供高级功能,如文件版本控制、临时访问链接、数据备份与恢复等。
    • 实现多区域支持,提升数据访问的速度和可靠性。
    • 提供跨平台兼容的API接口,支持更多的编程语言和开发工具。
    • 持续优化系统性能和用户体验,提升系统的稳定性和可扩展性。

1.2 技术栈选择

1.2.1 对比不同技术的优缺点
  • Node.js

    • 优点:高并发处理能力、非阻塞I/O、丰富的生态系统、适合实时应用。
    • 缺点:单线程模型对CPU密集型任务支持不足、需要注意异步编程的复杂性。
  • MongoDB

    • 优点:灵活的文档模型、水平扩展性、强大的查询能力、适合存储非结构化和半结构化数据。
    • 缺点:事务支持不如关系型数据库强大、对复杂查询的性能可能不如关系型数据库。
  • Redis

    • 优点:高性能、丰富的数据结构、支持持久化、适合做缓存和会话管理。
    • 缺点:内存占用较大、不适合存储大数据量的持久性数据。
1.2.2 选择这些技术的原因
  • Node.js

    • 高并发处理:Node.js采用事件驱动和非阻塞I/O,能够高效处理并发请求,非常适合文件上传、下载等高并发场景。
    • 丰富的生态系统:Node.js拥有丰富的模块和库,能够快速构建和扩展功能。
    • 全栈开发:使用Node.js可以实现前后端同构开发,提升开发效率。
  • MongoDB

    • 灵活的文档模型:MongoDB的文档模型非常适合存储文件的元数据,如文件名、大小、类型、上传时间等。
    • 水平扩展性:MongoDB支持分片和副本集,能够轻松扩展以处理大规模数据。
    • 强大的查询能力:MongoDB提供丰富的查询语法,能够快速检索和管理文件元数据。
  • Redis

    • 高性能缓存:Redis能够高效地缓存热门文件的元数据,提升系统的响应速度。
    • 丰富的数据结构:Redis支持字符串、哈希、列表、集合等多种数据结构,能够灵活地管理缓存数据。
    • 持久化支持:Redis支持RDB和AOF两种持久化方式,能够确保缓存数据的持久性。

1.3 初始化Express + TypeScript项目

1.3.1 安装和配置TypeScript
  1. 安装Node.js和npm

    • 首先确保已经安装了Node.js和npm。可以通过以下命令检查是否已安装:

      bash 复制代码
      node -v
      npm -v
  2. 初始化npm项目

    • 在项目目录中运行以下命令初始化npm项目:

      bash 复制代码
      npm init -y
  3. 安装TypeScript

    • 全局安装TypeScript编译器:

      bash 复制代码
      npm install -g typescript
    • 在项目中本地安装TypeScript及其类型定义文件:

      bash 复制代码
      npm install typescript @types/node --save-dev
  4. 配置TSLint/ESLint

    • 安装ESLint及其TypeScript插件:

      bash 复制代码
      npm install eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin --save-dev
    • 创建.eslintrc.js文件并配置ESLint:

      javascript 复制代码
      /* eslint-env node */
      // 此文件声明了 ESLint 在 Node.js 环境下运行
      
      module.exports = {
        // extends 属性用于扩展已有的 ESLint 配置
        extends: [
          'eslint:recommended', // 启用 ESLint 内置的推荐规则集
          'plugin:@typescript-eslint/strict', // 启用 TypeScript-ESLint 插件的严格规则集
          'plugin:@typescript-eslint/stylistic', // 启用 TypeScript-ESLint 插件的风格规则集
        ],
        // parser 属性指定了用于解析代码的解析器
        parser: '@typescript-eslint/parser', // 使用 TypeScript-ESLint 的解析器,以支持 TypeScript 语法
        // plugins 属性指定了 ESLint 插件
        plugins: ['@typescript-eslint'], // 加载 TypeScript-ESLint 插件,以便使用其规则
        // root 属性表示这是项目的根配置文件,ESLint 不会向上查找其他配置文件
        root: true,
      };

      注意,eslint官方推荐了另外一种方式来使用eslint。有兴趣可以去看看@Getting Started | typescript-eslint

  5. 创建TypeScript配置文件

    • 运行以下命令生成tsconfig.json文件:

      bash 复制代码
      tsc --init
    • 配置tsconfig.json

      json 复制代码
      {
        "compilerOptions": {
          "target": "ES2020", // 指定 ECMAScript 目标版本为 ES2020,以支持现代 JavaScript 特性
          "module": "commonjs", // 将模块解析设置为 CommonJS,以便与 Node.js 兼容
          "strict": true, // 启用所有严格类型检查选项,以增强代码的类型安全性
          "esModuleInterop": true, // 启用对 ES 模块的互操作性,以便使用 `import` 语句导入 CommonJS 模块
          "skipLibCheck": true, // 跳过对声明文件(.d.ts 文件)的类型检查,以加快编译速度
          "forceConsistentCasingInFileNames": true, // 强制文件名一致大小写,以避免在不同操作系统上的文件名大小写问题
          "outDir": "./dist", // 指定编译输出目录为 `./dist`
          "rootDir": "./src" // 指定输入文件的根目录为 `./src`
        },
        "include": ["src"] // 指定要包含在编译中的文件或目录
      }
1.3.2 创建基础项目结构
  1. 创建目录结构

    • 创建项目的基本目录结构:

      bash 复制代码
      mkdir src
      mkdir src/controllers src/models src/routes src/middlewares src/utils
      touch src/index.ts
  2. 安装Express

    • 安装Express及其类型定义文件:

      bash 复制代码
      npm install express
      npm install @types/express --save-dev
  3. 创建基本的Express服务器

    • src/index.ts中创建一个基础的Express服务器:

      typescript 复制代码
      import express, { Request, Response } from 'express';
      
      const app = express();
      const port = process.env.PORT || 3000;
      
      app.get('/', (req: Request, res: Response) => {
        res.send('Hello, Object Storage System!');
      });
      
      app.listen(port, () => {
        console.log(`Server is running on http://localhost:${port}`);
      });
  4. 编译并运行项目

    • package.json中添加脚本来编译和运行项目:

      json 复制代码
      "scripts": {
        "build": "tsc",
        "start": "node dist/index.js",
        "dev": "ts-node-dev src/index.ts"
      }
    • 安装ts-node-dev用于开发环境下的自动重启:

      bash 复制代码
      npm install ts-node-dev --save-dev
    • 运行开发服务器:

      bash 复制代码
      npm run dev
      
      > ore@0.0.1 dev
      > ts-node-dev src/index.ts
      
      [INFO] 10:30:48 ts-node-dev ver. 2.0.0 (using ts-node ver. 10.9.2, typescript ver. 5.5.3)
      Server is running on http://localhost:3000

1.4 配置Express框架

1.4.1 解释每个中间件的作用和配置方法
  1. 安装常用中间件

    • 安装body-parsercorsmorgan等常用中间件:

      bash 复制代码
      npm install cors morgan
      npm install @types/cors @types/morgan --save-dev
  2. 配置中间件

    • src/index.ts中配置中间件:

      typescript 复制代码
      import express from "express";
      import cors from "cors";
      import morgan from "morgan";
      
      const app = express();
      const port = process.env.PORT || 3000;
      
      // 使用内置的中间件来解析 JSON 和 URL 编码的请求体
      app.use(express.json());
      app.use(express.urlencoded({ extended: true }));
      
      // 使用 cors 和 morgan 中间件
      app.use(cors());
      app.use(morgan("dev"));
      
      app.get("/", (req, res) => {
        res.send("Hello, Object Storage System!");
      });
      
      app.listen(port, () => {
        console.log(`Server is running on port ${port}`);
      });
  3. 解释中间件的作用

    • body-parser:解析请求体,支持JSON和URL编码格式。

    • cors:解决跨域资源共享问题,允许来自不同来源的请求。

    • morgan:HTTP请求日志记录器,便于开发和调试。

    • express.static 提供静态资产,例如 HTML 文件、图像等。

      express.json 使用 JSON 有效负载分析传入请求。

      注意:适用于 Express 4.16.0+

      express.urlencoded 使用 URL 编码的有效负载解析传入请求。

      注意:适用于 Express 4.16.0+

1.5 项目目录结构设计

1.5.1 详细说明每个目录和文件的用途
  • src/controllers:存放控制器文件,处理具体的业务逻辑和请求响应。
  • src/models:存放数据模型文件,定义数据库模式和数据结构。
  • src/routes:存放路由文件,定义API路由和请求处理。
  • src/middlewares:存放中间件文件,处理请求的预处理和后处理逻辑。
  • src/utils:存放工具函数和通用模块,提供辅助功能。
  • src/index.ts:项目的入口文件,配置和启动Express服务器。

1.6 配置TypeScript编译

1.6.1 提供一个简单的示例代码
  1. 配置TypeScript编译

    • 确保tsconfig.json配置正确,指定rootDirsrcoutDirdist
  2. 编写示例代码

    • src/controllers/helloController.ts中添加示例控制器代码:

      typescript 复制代码
      import { Request, Response } from 'express';
      
      export const helloController = (req: Request, res: Response) => {
        res.send('Hello from the controller!');
      };
    • src/routes/helloRoute.ts中添加示例路由代码:

      typescript 复制代码
      import { Router } from 'express';
      import { helloController } from '../controllers/helloController';
      
      const router = Router();
      
      router.get('/hello', helloController);
      
      export default router;
    • src/index.ts中使用示例路由:

      typescript 复制代码
      import express from "express";
      import cors from "cors";
      import morgan from "morgan";
      import helloRoute from "./routes/helloRoute";
      
      const app = express();
      const port = process.env.PORT || 3000;
      
      // 配置中间件
      app.use(express.json()); // 使用 Express 内置的 JSON 解析中间件
      app.use(express.urlencoded({ extended: true })); // 使用 Express 内置的 URL 编码解析中间件
      app.use(cors());
      app.use(morgan("dev"));
      
      // 配置路由
      app.use("/api", helloRoute);
      
      app.get("/", (req, res) => {
        res.send("Hello, Object Storage System!");
      });
      
      app.listen(port, () => {
        console.log(`Server is running on http://localhost:${port}`);
      });
  3. 编译并运行项目

    • 运行以下命令编译TypeScript代码:

      bash 复制代码
      npm run build
    • 运行以下命令启动编译后的项目:

      bash 复制代码
      npm run start
    • 访问http://localhost:3000/api/hello,应看到控制器返回的Hello from the controller!消息。

通过本章的学习,我们已经成功搭建了Express + TypeScript项目的开发环境,并创建了项目的基础结构。我们详细介绍了项目的目标和技术栈选择,完成了TypeScript的安装和配置,创建了基础的项目目录结构,并配置了Express框架和常用中间件。这些准备工作为我们后续的开发打下了坚实的基础。

在接下来的章节中,我们将深入探讨用户管理、文件上传与下载、文件元数据管理、权限控制与安全机制等核心功能的实现。通过逐步构建和完善这些功能,我们将最终实现一个高效、安全、可靠的对象存储系统。让我们继续前行,迎接下一章的挑战吧!

相关推荐
码事漫谈1 分钟前
智谱 ZCode 静默上传 Git 历史:48 小时信任危机复盘
后端
掘金码甲哥22 分钟前
当对话模型遇上向量模型,vllm production stack 又该如何应对?
后端
传奇开心果编程1 小时前
【springboot基础语法学与练】第 1 课:从零开始
java·spring boot·后端·学习
IT_陈寒1 小时前
Java线程池用错参数,我的服务居然悄悄崩溃了
前端·人工智能·后端
光影少年1 小时前
Express 中间件原理
后端·node.js·express
时速GEO系统1 小时前
初元 AI V1.1 版本升级,首个正式版发布一周・实现生成、部署、上线、优化全流程自动化闭环
人工智能·数据挖掘·node.js
aramae2 小时前
MySQL内置函数(7)
开发语言·笔记·后端·mysql·其他
徐小夕3 小时前
存量.doc 文档怎么办?JitWord 开源转换库打通旧文档到在线协同全链路
后端·架构·github
ee又momo3 小时前
一次 JWT Token 过期续期的踩坑记录
后端
二月龙3 小时前
App 瘦身实战:图片、so 库、资源压缩,安装包体积减小 40%
后端