Skip to content
No description, website, or topics provided.
Go HTML
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
html
.gitignore
README.md
config.toml.example
main.go

README.md

modao-backend-assignment

环境搭建

  • 安装influxdb 1.7.3,并启动服务:
    $ sudo pacman -S influxdb
    $ sudo systemctl start influxdb
  • 安装go 1.12.7
    $ sudo pacman -S go
  • vscode安装微软的Go插件

验收方式

  • 直接访问已部署的http://120.78.169.154:8880
  • 从Github上下载 Release
    解压后cp config.toml.example config.toml创建配置文件,并修改数据库相关信息
    ./modao-backend-assignment运行可执行文件
  • git clone https://github.com/whoisnian/modao-backend-assignment.git克隆源码
    go build编译出可执行文件
    cp config.toml.example config.toml创建配置文件,并修改数据库相关信息
    ./modao-backend-assignment运行可执行文件

未实现

  • 前端十分简陋
  • 前端向后端通过json形式发送数据,而不是现在的Formdata
  • 后端代码单元测试

其它

  • 初次接触时序型数据库,能感觉到自己对“时序型”的理解还很浅,还会有一些不正确的地方。找一个具体的应用场景,自己尝试对比一下用一般数据库处理和用时序型数据库处理,应该会对理解有很大帮助。
  • influxdb数据库自己只能算是大致知道有这么一个东西,具体的各种特性和高级用法一点都不了解,想要学习的话从官方文档入手很不错。
  • 写简单的前端页面时暴露了自己对前端的不了解,感觉需要适当地关注一下前端的知识,至少要了解常用的框架与后端数据交互的方式,方便与其他人之间的沟通。

任务具体完成过程

一、确定任务方向

查看任务内容,大致就是需要了解influxdb数据库的基础知识,然后使用一门语言提供规定的接口去访问数据库,并使用简单的前端页面进行展示。

二、具体步骤规划

  • 了解一下influxdb数据库,一般被用来做什么,主要特点是什么。
  • 查看influxdb有没有推荐的编程语言绑定,确定自己要用的语言。
  • 了解数据库具体细节,给出详细的表结构。
  • 确定具体的路由,明确要传递什么参数,返回值应该是什么样的。
  • 完成后端代码。
  • 简单的无美化的前端交互页面。
  • 附加功能(时间充裕的话再尝试完善):
    • 美化前端交互页面;
    • 后端单元测试;
    • 后端考虑更多功能,如测试数据库查询速度,判断是否需要缓存;接口调用频率限制等;
    • 在服务器上部署。

三、需要注意的细节

  • 函数命名规范,给出功能描述,具体参数、返回值含义。
  • git commit 信息明确,避免模糊不清。
  • 后端需要注意校验数据的合法性,不要盲目相信前端页面传过来的数据。

四、具体过程

influxdb 数据库简单了解

influxdb官网的介绍页面可以看到,它对自己的定义是InfluxDB is a time series database designed to handle high write and query loads.,时序和高性能是其中的关键字,高性能好理解,而时序型数据库自己还真没接触过。

在谷歌上以时序型为关键字进行搜索,大致理解了时序型的意思,主要目的是为了比传统的数据库更方便地记录数据的“变化”过程。例如想记录几台服务器负载的变化,如果是关系型数据库,要想记录下变化过程至少得单独开一表,表中需要有time,server,load几项,当服务器集群很大,记录间隔又较短时,数据的写入量会十分巨大,查询的耗时也会随之增加,表中的server项也有大量的重复。
时序型数据库主要就是为了应对这种场景:与时间有关的数据大量写入,已写入的数据不需要修改,查询多为区间内信息统计。例如上面提到的服务器集群状态监控,还有物联网设备的传感器需要以很短的时间间隔记录数据,自动驾驶汽车需要一直记录自身的运行状态等。时序型数据库会对相关数据的压缩存储,聚合查询等进行针对性的优化。

PS:因为目的是知道怎么使用,所以没花费更多时间深入了解,更详细的话还可以去了解一下influxdb和一些关系型数据库的性能测试对比,了解一下influxdb跟其它时序型数据库的差异。

确定编程语言

在官方guides的写入数据部分里介绍到:

Write data into InfluxDB using the command line interface, client libraries, and plugins for common data formats such as Graphite.

可以通过命令行接口,编程语言提供的库,或者一些其它软件进行读写。InfluxDB API client libraries里提到了很多编程语言,我最终选择了Golang,原因如下:

  • 之前简单地学习过 Golang;
  • Go版本 InfluxDB Client 由 InfluxData 官方维护;
  • 交叉编译方便,直接编译出多个平台的release,前辈验收时不需要有环境就能运行。

数据库具体细节

官网的介绍页面是提到有两个版本的,同时https://github.com/influxdata/influxdb的README里也有提到:

The latest InfluxDB 1.x is the stable release and recommended for production use. InfluxDB 2.0 (what's in the master branch) is currently in the alpha stage. This means that it is not recommended for production usage. There may be breaking API changes, breaking changes in the Flux language, changes in the underlying storage format that will require you to delete all your data, and significant changes to the UI.

所以我选择了InfluxDB 1.x,直接从源中安装1.7.3版本即可:
$ sudo pacman -S influxdb

MySQL里的database,table,row,column,field一样,influxdb也有自己的一些名词,在InfluxDB key concepts里有具体的解释,其中几个主要的:

  • database:数据库
  • measurement:测量指标,相当于数据库中的表
  • point:一个时间点的数据,包含时间(time),必须有的不被索引的数据(field),可选的被索引的数据(tag
  • retention policy:保留规则,指明数据保存多长时间,集群部署时还负责指明保存几份
  • series:序列,由measurement,retention policytag set确定的数据集合
  • field:存储要收集的数据,类型包括strings, floats, integers, or Booleans
  • tag:一般区分数据的来源,只能是strings

具体语句和SQL非常相似,参考getting-started中链接到的相关内容即可。

现在回过头来看任务,要存储的内容有time, user-id, user-grouptime属于influxdb固有的内容,不需要额外考虑。如果根据后端要提供的接口来看,只需要查询限定时间范围内的数据,所以考虑到性能,user-iduser-group不需要作为tag,当作field即可。但是根据语义来看,使用时序型数据库主要是为了存储变化过程,user-iduser-group之间的变化可能有“用户随着时间其所属用户组的变化”,或者“用户组随着时间其包含用户的变化”,更合适的方法是根据具体场景,确定哪个为tag,哪个为field

因为缺少具体的数据使用场景,所以我选择根据要提供的路由将user-iduser-group都作为field来进行存储,user-id存储为intuser-group存储为string

<measurement>[,<tag-key>=<tag-value>...] <field-key>=<field-value>[,<field2-key>=<field2-value>...] [unix-nano-timestamp]

路由设计

status含义仿照http状态码,各字段保证存在且不为null。
(200请求成功,400请求参数不正确,405请求方法不正确,500服务器内部错误)

  • POST /insert:添加数据
    • 需要user-iduser-groupuser-id范围1-10user-group范围A,B,C,D
    • 返回状态包括200,400,405,500,示例:
      {
          "status": 200
      }
      
  • GET /select-by-time-range:查询限定时间范围的数据
    • 需要start-timeend-time,时间格式为unix时间戳,如1564638480
    • 返回状态包括200,400,405,500,示例:
      {
          "status": 200,
          "data": [
              {
                  "time": 1564638480,
                  "user-id": 1,
                  "user-group": "A"
              },
              {
                  "time": 1564638481,
                  "user-id": 1,
                  "user-group": "B"
              }
          ]
      }
      
  • GET /total-count:返回数据条数
    • 无参数
    • 返回状态包括200,405,500,示例:
      {
          "status": 200,
          "total-count": 5
      }
      

完成后端代码

代码的难度不是很高,但其中也有部分需要注意的细节,如

  • 前后端数据交互中用到的时间格式,可以用字符串,也可以用时间戳,相比之下时间戳传输数据量更小,服务器端不需要额外处理时区问题,因此我选用了时间戳
  • Go 官方提供的json库中使用struct保存json中的数据,要注意json中的整型是64位,而 Go 中的整型int根据平台不同,可能为32位或64位,处理json数据时指定int64更加安全
  • Go 的路由/insert/会匹配/insert/,并且会将/insert302重定向到/insert/,302重定向会改变post和put的method为get。可以手动增加使用307重定向的/insert,或者路由严格匹配/insert
  • github.com/influxdata/influxdb1-client/tree/master/v2尚未支持go mod,pr列表中已有增加go mod支持,但尚未合并,因此只能用传统的Go PATH存放依赖
  • influxdb1-client/v2提供的插入查询方法相当于字符串拼接,注意要校验数据的合法性,防止类似于sql注入的攻击
  • 该后端代码理应有对应的测试部分,但限于对go test的了解,我只是在本地使用postman测试了提交各种非法请求,以及正常请求时返回数据的合法性

前端交互界面

  • 先计划大致需要几个功能:使用表单插入数据,根据时间范围查找数据,显示数据总数,因此单个页面即可。
  • 对前端基本没有了解,所以我只能简单的fetch从后端接口取数据,原样展示出来。
  • 使用fetch的过程中感觉后端也改成处理json会更为统一,现在的后端是接收FormData,返回json,在前端框架中postjson数据会更为方便吧。
  • 前端不做数据范围限制,使得可以在页面上提交非法数据查看后端的返回结果。

附加功能

想在今天之内提交,所以没有太多时间进行拓展,准备就简单地将其部署一下,需要注意默认influxdb数据库未开启认证,需要创建账户后手动修改/etc/influxdb/influxdb.conf中的auth-enable一项进行开启,监听地址改为127.0.0.1也会增加安全性。

You can’t perform that action at this time.