Jiahonzheng's Blog

ToDo-Backend 开发经历

字数统计: 2.7k阅读时长: 9 min
2017/09/23 Share

着笔本系列的首篇博客,我有些尴尬,因为这写博客的时间有些不符常理,因为 ToDo 项目(除 ios 平台)已经快要开发完成,而本系列博客才刚刚开始。这尴尬也让我终于明白了异步和同步操作的区别!

本篇博客,我把它定义为 ToDo 项目的后端 ToDo-Backend 的“开发文档”。

ToDo

ToDo 是一个支持 多人任务同步 的任务清单平台,适用于个人任务备忘、多人任务指派型场景,旨在提高任务管理的效率,运行平台为 iosAndroidWeb 。我们可以把 ToDo 理解为常规的备忘录软件的进化版本, 加入了归档、多人同步功能,当然未来还会加入群组功能。

该项目大体上分三大功能板块:未完成监督全部任务任务发布

未完成

在该板块中,只显示分配给用户的任务,具有 DDL 颜色提醒 功能,如离 DDL 还有一天,则该任务 item 显示为红色;离 DDL 还有两天,则显示黄色;其余时段,为正常显示状态。这里要敲黑板,此处分配动作的执行者可以为用户自己,这样平台就具备了作为个人用户的私人备忘录的功能。

监督

顾名思义,在该板块中,用户可以以任务分发者的视角,监督各种已分配任务的完成情况,以及 编辑删除 已分配任务。这里又得敲黑板了,该板块只显示已分配但又未完成的任务。如果用户想查看已分配且已完成的任务,可以前往 全部任务 板块查看。

全部任务

用户可以在此板块中,查看所有用户的各种任务(包括未完成任务和已完成任务)。在后续的完善过程中,我会给该板块引入 查看权限 的限制,即实现用户只能查看自己所在群组的全部任务。目前没实现该功能,是因为个人开发精力有限,还没着手 群组 模块的开发(该功能需要群组模块的支持)。

任务发布

用户在该板块中,可以给特定用户分配任务,这里的特定用户也叫 任务执行者 。又是一阵敲黑板,任务执行者可以为自己,可以为他人。 用户需要填写 任务执行者 、 截止日期 、 任务内容 , 实现任务的发布。

ToDo-Backend 架构设计

着手 ToDo-Backend 开发之前,需要先考虑大体实践方案以及技术栈。当初起步时,年少轻狂还无知,没有仔细考虑后端要用的技术栈,结果走了很大的弯路,这带来的不仅是时间上的损失,还是心灵上的无情摧残。教训很大,一定铭记!

整体架构设计

Node.js 作为逻辑处理层; MySQL 作为用户、任务存储数据库。

从本质上看,我们要搭建的 ToDo-Backend 是一个中转站,客户端通过中转站的媒介,实现与后端数据库的交互,具有明显的 RESTful 风格。

选用 Node.js 作为逻辑处理层的原因是, RESTful API 是适合 Node 的理想情况。 提供 RESTful APIWeb 服务器接收几个参数,解析它们,组合一个响应,并返回这个响应给用户。在这样的情景,Node 可充分发挥其非阻塞 IO 模型。

API 接口设计

在 API 接口设计 过程中,有个很实用的经验:

设身处地,将自己模拟为用户,然后触发各种情景,也就知道需要为后端设计哪些接口。

OK, 开启导演模式!影片导演兼演员: 佳佳 。

今天是星期六,在接下来的七天里,佳佳要解决许许多多、各种各样的事情,更重要的是他要和女朋友在星期五一起吃饭,他担心自己在繁忙中错过这件要紧事。于是,他打开了 ToDo 平台下的 ToDo-Android , 他输入了账号和密码,登入了管理平台。他打开了 任务发布 板块, 输入了 DDL 日期(星期五) 、 任务执行者(佳佳) 以及任务内容(和女朋友一起吃饭),随后点击了发送键,未完成 板块随即出现一个任务项。 成功发布任务后,佳佳放心地开始了繁忙地工作。 佳佳一直被如山高的书籍、作业折磨到星期二晚上,他收到了来自女朋友的信息:吃饭时间改到星期六。佳佳随即打开了 ToDo-Web ,在 监督 板块找到了那天添加的任务,点击 编辑 按钮,将截止时间修改为星期六,确定修改后,佳佳怕系统出问题,没有更改原来任务,于是打开了 未完成 板块,看到原任务截止日期变为星期六,他放心了。时间过得很快,到了星期六,佳佳在前往女朋友的路上打开了 ToDo-Android ,看到呈红色状态的任务项,他笑着点击按钮,实现了 完成任务 的操作。在吃饭途中,佳佳给她女朋友点开了 全部任务 板块,向她展示这周他做了多少的事情,满满的任务安排。看来这的确是个繁忙的一周,作为鼓励,佳佳得到了一个甜甜的吻。

场景拍摄结束,佳佳可以去拿最佳导演奖了。从佳佳在电影中的行为,我们可以知道我们将要为 ToDo-Backend 实现以下 API 接口:

  • 登录验证 接口
  • 未完成已完成全部任务 板块的任务接收接口
  • 任务发布 接口
  • 任务编辑 接口
  • 任务删除 接口

基本流程

  1. 创建受限制和不受限制的路由。
  2. 客户端通过 post 用户名和密码进行验证,服务端使用 session 策略并返回一个带 tokenjson 字符串。
  3. 客户端将 tokencookies 形式保存在本地,并且每次向服务端发出请求时在 header 加入 token 信息。
  4. 服务端验证 token ,如果一切顺利,则返回对应请求的响应 json 信息。

ToDo-Backend 实现

具体的项目开发过程,必须建立在完整的、周全的项目设计工作上。

如果项目设计工作没有做好,做扎实,那么极其可能会出现所有辛苦打出来的代码被无情删除的情况。

开发工具及环境

Ubuntu 16.04.3 LTS 64bitToDo-Backend 宿主系统

MySQL 5.7.19 : 与 ToDo-Backend 链接的数据库,存储用户账号、用户密码和任务信息

Node.js 6.11.2ToDo-Backend 是基于 Node.js 的服务端应用,所以必须有 Node.js 环境

cnpm :淘宝提供的类似 npmNode.js 包管理器,但由于使用的是淘宝的镜像节点,速度比 npm

WebStorm 2017.2.1 :一款极其好用的 JavaScript IDE

Postman : 一款优秀的 API 测试工具

Navicat for MySQL : MySQL 的可视化工具,支持正版!!!

一些所用模块的介绍

  • express : 一个流行的 Node.js 的框架
  • mysql :与 MySQL 通讯的模块,提供了 pool 工具,优化通讯过程
  • body-parser :实现从 post 请求中解析 url 参数
  • cookie-parser :一个 cookies 管理工具模块
  • express-session :一个服务端 session 管理工具模块
  • morgan :将请求信息输出到服务端的 console

具体实现

点击即可跳转到项目主页 ToDo-Backend ,欢迎各位大侠提出 issues

项目目录

数据库安装与配置

Ubuntu 16.04 上安装 MySQL 、并开启远程访问、设置编码格式、配置 wait_timeout 的教程可参考我的另一篇博文

建立 usertask 数据表

ToDo-Backend 开发过程踩过的坑

本板块主要记录在开发 ToDo-Backend 过程中碰到各种揪心问题,都挺耽误开发时间的,当作提前打预防针吧,如果下次碰到类似的问题,就有经验了。

MySQL 的设置

由于我是 MySQL 的小白,当初入坑时,年少无知,走了不少弯路,用宝贵的时间换来了经验,也算是一种成长吧。

编码格式设置

当初考虑数据库编码时,忘记了自己是中国人的严重事实,使用了默认编码 latin1 ,没有采用 utf8 编码,结果在 API 测试中,服务端因客户端输入了中文字串,结果任务无法入库,出现了宕机事件。结果又花了时间学习如何在 Ubuntu 下修改 MySQL 编码。后来,在查阅一些技术博客,学习到 MySQL 编码应该设置为 utf8mb4 更为合适,该编码时 utf8 的超集,能够支持表情符号的入库。

wait_timeout 设置

在使用 Postman 测试后端性能时,发现在面对大量请求时,服务端会出现无法处理请求的现象。花了将近一下午的时间,从前端查错到后端,最后发现是 MySQL 的连接超时问题,即 “8 小时问题”。查阅 MySQL 5.7 Reference Manual 手,修改了 wait_timeout 的值。最后再次使用 Postman 对后端进行请求轰炸,发现不会出现无法请求的问题。

跨域问题

由于浏览器的同源策略的限制,当 ToDo-WebToDo-Backend 发送请求时,会出现请求未被处理的问题。( ToDo-WebToDo-Backend 分别搭建在同台机器的 port 80port 3000上)

查阅相关资料,刚开始在 express 实例中使用 cors 模块,结果发现不能解决问题(可能我的相关设定没有设置到位)。最后,使用原生方法,解决了跨域问题。

1
2
3
4
5
6
7
8
9
app.all('*', function (req, res, next) {
res.header("Access-Control-Allow-Origin", "http://localhost:80");
res.header("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With");
res.header("Access-Control-Allow-Credentials", true);
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
res.header("X-Powered-By", ' 3.2.1')
res.header("Content-Type", "application/json;charset=utf-8");
next();
});

仍需解决的问题

当在 任务发布 板块中输入表情符号,尽管 MySQL 编码已设置为 utf8mb4 ,但仍然会出现因表情无法入库而出现服务端宕机的问题。对于这个问题,我会抽出空闲时间来解决。

当前版本的服务端,一旦出现错误,就需要手动重启,这是件麻烦的工作。需要引入错误处理方法,以及完善具体业务代码,提高代码健壮性。

CATALOG
  1. 1. ToDo
    1. 1.1. 未完成
    2. 1.2. 监督
    3. 1.3. 全部任务
    4. 1.4. 任务发布
  2. 2. ToDo-Backend 架构设计
    1. 2.1. 整体架构设计
    2. 2.2. API 接口设计
    3. 2.3. 基本流程
  3. 3. ToDo-Backend 实现
    1. 3.1. 开发工具及环境
    2. 3.2. 一些所用模块的介绍
    3. 3.3. 具体实现
      1. 3.3.1. 项目目录
      2. 3.3.2. 数据库安装与配置
      3. 3.3.3. 建立 user 和 task 数据表
  4. 4. ToDo-Backend 开发过程踩过的坑
    1. 4.1. MySQL 的设置
      1. 4.1.1. 编码格式设置
      2. 4.1.2. wait_timeout 设置
    2. 4.2. 跨域问题
  5. 5. 仍需解决的问题