无际软工队 - 求职岛:技术规格说明书
项目 | 内容 |
---|---|
这个作业属于哪个课程 | 2022年北航敏捷软件工程 |
这个作业的要求在哪里 | 团队项目-计划阶段要求 |
我们在这个课程的目标是 | 熟悉敏捷开发的方法论,并通过实际开发产品进行实践。 |
这个作业在哪个具体方面帮助我实现目标 | 熟悉敏捷开发的方法论:学习敏捷开发的技术定义规范和方法。 通过实际开发产品进行实践:实际定义所开发产品的技术规格。 |
Author: 无际软工队
Date: 2022.04.18
摘要
本文档设计并定义了平台的系统架构。
项目硬件架构及技术栈
本项目基于微信小程序与网页 web 端实现,目标适配 PC 和手机端。项目将部署到腾讯云服务器云端,部署环境为 Debian 11
。服务器基本配置如下:
- 4 核 8G,100G SSD 云盘存储,10Mbps 公网带宽
项目前后端开发所涉及的具体技术栈如下:
- 微信小程序端:使用微信官方开发工具开发;
- Web前端:前端所用的程序设计语言为
HTML + CSS + JS
,采用Nuxt.js
全家桶开发; - 后端:
- 后端所用的程序设计语言为
Python
,采用django-rest-framework
框架 - 测试采用
Django
框架自带的单元测试 - 数据存储使用关系型数据库
PostgreSQL
- 其中
Python
版本为 3.8,Django
版本为4.0,PostgreSQL
版本为 14.2,后续可能会视具体兼容情况决定是否做相应调整。
- 后端所用的程序设计语言为
软件架构
软件的整体架构如下图所示:
下面对其中的主要模块所承担的功能任务进行简要介绍。
后端 Django 框架
依照 RESTful 样式(Model - Serializer - API)设计后端,利用 Django 提供的对象关系映射机制 (ORM)、路由管理、用户认证与权限组件可显著降低开发成本,提升整体开发效率。同时,利用 Django-rest-framework(DRF)插件快速开发RESTful样式的接口,利用 django-rest-framework-simplejwt 插件实现JWT样式的用户鉴权,从而快速迭代实现前端所需的各类接口。
前端
前端使用 MVVM 架构,视图层 (View) 负责向用户展示界面,视图模型层 (View Model) 负责实现页面视图与数据的双向绑定,数据模型层 (Model) 负责和后端交互以及相关逻辑的处理。
CDN & COS
用于解决高并发时流量瓶颈问题,前端的静态文件如 .css/.js
会由内容分发网络 CDN
进行缓存和分发。用户的头像、图片、简历等等大文件将依托于腾讯云提供的对象存储服务 COS
进行存储与分发,此举既可以减轻服务器带宽压力,也可以加快用户下载速度提升用户体验。
后端开发目标
代码编写 & 系统设计
数据建模
数据的建模依托于 Django 提供的 ORM 框架,通过编写 Python 类来自动生成数据库中的数据表和表之间的依赖关系。将实验室、实验室招聘者、求职者、求职信息、实验室与导师评价等实体抽象成对象,利用 ORM 进行面向对象编程
API 设计及抽象
参照 RESTful 范式将对象的字段、完整性验证以及与对象状态转变相关的过程封装在 Model
类中;将模型对象表示为 json 的方法实现为 Serializer
类,将面向前端调用的对象视图以及对象操作方法封装为 APIView
类,从而实现高内聚、松耦合和模块化。以上做法可以充分利用 django-rest-framework 的框架实现, 大幅提升开发效率。
错误机制及处理办法
后端的错误包括两大类:通用错误和特定错误,通用错误是在任何 API 调用时都有可能出现的错误;而特定错误是仅针对某个或某些API可能会发生的错误。
除了的上述两类意料中错误以外,还可能出现意料外错误,如网络不可达、nginx 反代连接失败、后端崩溃等等,其标志为返回的报文不是 json 格式,前端可能仍需要处理此类错误。
区别 | 通用错误 | 特定错误 |
---|---|---|
发生位置 | 任何API都有可能出现 | 文档中特别规定某API中会出现 |
HTTP Status Code | 4xx ~ 5xx | 4xx ~ 5xx |
报文信息格式 | {“code”: 400, “detail”: “…”} 其中code 与 HTTP Status Code 一致 | {“code”: 600+, “detail”: “…”, “data”: {…}} |
前端处理优先级 | 最后处理 | 优先处理(先判定code字段是否大于600) |
格式定义方式 | 定义于此,类型数量固定 | 定义于API文档,随时增加 |
处理方式 | 跳转登录,或弹窗报错,或刷新页面,或根据前端对于不同场景的定制化设置 | 前端具体分析data内容决定 |
通用错误类型一览
- 400 BadRequest:json不能解析或数据不满足约束
- 401 Unauthorized:当前用户未登录,或token失效
- 403 Forbidden:用户已登录,但是无权访问资源
- 404 NotFound:为了满足用户的请求所需要的某一部分资源不存在
- 405 MethodNotFound:比如API只定义了GET方法,那么用POST就会出这个错
- 500 InternalServerError:后端运行过程中报了其他错误
后端具体写法
对于通用错误类型,请抛出rest-framework内置的特定错误如:
raise rest_framework.exceptions.ValidationError
对于特定错误类型,请在core.exceptions内新建一个异常类,继承自rest_framework.exceptions.APIException,并在异常类中定义好转换成json的方法,在需要抛出异常的地方将其抛出并由 rest_framework 框架自动转化为指定的格式
class MyException(APIException):
code = 600
default_detail = "foo"
...
大部分错误如果前端可以进行处理的将由前端处理,若有恶意用户直接向后端发送非前端生成的数据包后端不会额外返回错误详细信息而是直接返回一个 400 BadRequest
,前端无需对此处理。
需要后端查询数据才能发现的错误将与前端协商一个错误码,返回的数据包格式如下所示,所有的内容根据具体的错误以及前端所需要的信息单独设定
{"code": 600, "detail": "...", "data": {...}}
若后端处理正确将会返回一个 200 Success
数据包,内容各自约定,不采用上面的格式。
系统性能分析 & 高并发应对
因为与职协有合作,可能会存在高并发的情况,因此我们购置了 4核8G
的服务器,使用 nginx + uwsgi
的方式部署基本上可以符合要求,如果真的出现了处理能力不足的情况还可以额外购置服务器并利用 nginx
的分流机制提升并发能力。
同时我们会使用对象存储分发大文件,减小带宽的压力。
需求迭代的灵活性
由于我们的软件整体设计上呈现扁平化趋势,且团队规模与软件大小均相对轻量,因此当出现新增需求时,我们可以实现“一站式”流水线应对方案。
具体操作流程为:
- 前端设计实现用户操作接口、相应界面与控制逻辑
- 前端判断现有 API 能否满足新需求需要,若不可,则定义新的 API,同时更新 API 文档
- 后端基于 API 文档实现其内部控制逻辑,同时判断现有数据模型能否满足新需求需要
- 若不可,则调整数据模型,进行迁移
网络安全设计
- 任何生产环境密码不得进入 git 仓库,需要在 CI 中使用的密码填入 Action Secret 。
- 用户的密码通过安全的
pbkdf2_sha256
的方式存储,即将用户密码加随机盐之后使用散列函数循环计算 320000 次后将结果存入数据库中,有效防止暴力破解与意外的数据库泄露导致的密码泄露。在注册和修改密码时会要求用户的密码长度、使用大小写字母与特殊符号并拒绝使用常见密码。 - 数据传输会采用全程 https 安全加密并禁用 http 不安全传输方式。
- 用户登录后将会得到一个符合 JWT 标准的 token,之后的所有用户操作后端都会根据此 token 进行鉴权,向后端的请求格式必须为 json 而不能是 urlencoded_form,这样的机制可以有效防止 CSRF 攻击。
- 后端的权限验证将会采用 Django 提供的权限管理机制,并且我们会将默认的API调用权限设置为仅管理员可访问,仅当显式声明某些用户可访问时才可访问(也就是白名单模式),防止编程时意外的权限泄露。
- 后端访问数据库均会通过 Django-ORM 的机制进行,其会对产生的 SQL 语句进行转义,防止 SQL 注入攻击。
- 前端如果需要显示用户发送的富文本内容,将会在前端使用 JavaScript 编写的 xss 插件进行脚本标签白名单过滤,防御 XSS 攻击。
- 用户上传的文件将会直接上传至腾讯云对象存储服务,不会在本机留存,防止用户上传恶意程序。
测试
单元测试
测试会采用 Django 框架的测试模块进行编写,测试各个 API 的安全性与可用性还有代码覆盖率,并且测试工作将会配置于 CI 实现自动化测试。
系统压力测试
为了模拟真实请求场景,计划使用 Python-requests
脚本发送请求进行压力测试。
前端开发目标
代码编写 & 系统设计分析
视图层
微信小程序端使用其特有的视图层描述语言 WXML 和 WXSS,以及小程序的脚本语言 WXS。
Web 前端使用 HTML + CSS + Javascript 完成视图层的描述。
视图模型层
Web 前端 (Nuxt.js 基于 Vue.js):
微信小程序端:
数据模型层
微信小程序端基于 Uni-app 所提供的类 VueX 状态管理框架进行集中状态管理。
Web 端依托 Nuxt.js 集成的 VueX 进行集中的状态管理。
前后端交互
微信小程序端和 Web 端均使用 Axios 与后端进行交互。
错误处理
将 Axios 再封装一层,按照和后端约定的错误码进行相应的逻辑操作。
需求迭代的灵活性
采用 MVVM 架构,通过组件化降低模块间的耦合度,同时提高代码复用率,方便在需求迭代时进行更改。
测试
微信小程序端使用测试工具集 miniprogram-simulate
进行测试。
Web 端使用 Jest
+ Vue-test-utils
进行单元测试,使用 Nightwatch.js
实现端对端的真实测试。
部署
Git仓库与CI/CD
使用GitHub Action运行自动化测试、打包Docker镜像和自动部署。
Docker容器化部署
为了保证部署环境和开发测试环境的一致性,CI 部署的方便性,我们采取 Docker 部署方式。
文档编写
为了避免花费太多时间在文档编写上,我们决定是只编写必要的文档,例如前后端 API 交互文档。同时,我们考虑利用 swagger
等工具自动从后端代码中导出 API 文档,以保证文档和代码的一致性。
除此之外,我们制定了严格的 commit 和提交规范,以保证能够通过 commit 历史以及 issue 历史等对代码提交进行追溯。