likes
comments
collection
share

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

作者站长头像
站长
· 阅读数 40

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

瞎编的,就是硬想写~

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

本章将带领你开始设计并实现一个类似于阿里云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。可以通过以下命令检查是否已安装:
      node -v
      npm -v
      
  2. 初始化npm项目

    • 在项目目录中运行以下命令初始化npm项目:
      npm init -y
      
  3. 安装TypeScript

    • 全局安装TypeScript编译器:
      npm install -g typescript
      
    • 在项目中本地安装TypeScript及其类型定义文件:
      npm install typescript @types/node --save-dev
      
  4. 配置TSLint/ESLint

    • 安装ESLint及其TypeScript插件:

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

      /* 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文件:
      tsc --init
      
    • 配置tsconfig.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. 创建目录结构

    • 创建项目的基本目录结构:
      mkdir src
      mkdir src/controllers src/models src/routes src/middlewares src/utils
      touch src/index.ts
      
  2. 安装Express

    • 安装Express及其类型定义文件:
      npm install express
      npm install @types/express --save-dev
      
  3. 创建基本的Express服务器

    • src/index.ts中创建一个基础的Express服务器:
      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中添加脚本来编译和运行项目:
      "scripts": {
        "build": "tsc",
        "start": "node dist/index.js",
        "dev": "ts-node-dev src/index.ts"
      }
      
    • 安装ts-node-dev用于开发环境下的自动重启:
      npm install ts-node-dev --save-dev
      
    • 运行开发服务器:
      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.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中添加示例控制器代码:

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

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

      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代码:
      npm run build
      
    • 运行以下命令启动编译后的项目:
      npm run start
      
    • 访问http://localhost:3000/api/hello,应看到控制器返回的Hello from the controller!消息。

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

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

转载自:https://juejin.cn/post/7389800357427609637
评论
请登录