【前端监控系统开发实录】之时序数据库的探索 | 青训营笔记

355 阅读2分钟

这是我参与「第四届青训营」笔记创作活动的的第7天

window11 安装 influxdb

  1. 通过 官网 下载最新版本的 InfluxDB 。

image.png

  1. 下载压缩包到本地后,解压在 D 盘下:

image.png

然后win + R输入 cmd 后,在面板上进入 InfluxDB 的安装目录(或者直接在上图蓝色高亮的地方输入 cmd 并回车),启动 influxd.exe :

image.png

  1. influxdb 启动后可以看到上图所示,接着打开浏览器,输入地址:http://localhost:8086 即可打开 influxdb 的配置页面(第一次登录时界面不是这样的,之后登录才是)。 image.png

编写后端服务

influxdb 安装完成后,我们就可以使用时序数据库开发了。不过在开始编码之前,我们还需要理清其中逻辑及打算使用的技术栈:

  • 用 nodejs + koa 写服务
  • influxdb 存储监控数据,mysql 辅助存储额外的业务数据(如用户登录等)
  • 用 influxdb 自带的 web 管理界面辅助查表
  • 查表时使用 influxdb 的语法查询(influxdb 可能不能使用 typeorm)

理清这些后,我们终于可以开始愉快地开发后端了。

influxdb 概念类比

  • Buckets:数据表 image.png
  • _measurement:表中的行
  • _field:每一行的键
  • _value:每一行的值 image.png
  • _stop:数据查询时间
  • _time:数据写入时间 image.png

开发相关

我们使用 influxdb 的 flex 语法操作数据表,相关 API 的使用参考官网即可:使用 Node.js JavaScript 客户端库

需要提醒的是:

  1. 写入数据时,我们会用到new Point(),这其实就是创建表中行数据的意思,然后使用.floatField方法创建键值对。如果需要新建 整数型浮点型布尔型 等数据,可以进入Point对象查看源代码(按住 ctrl 键 ,鼠标点击即可跳转): image.png
  2. 查询表数据我们是使用const queryApi = new InfluxDB({YOUR_URL, YOUR_API_TOKEN}).getQueryApi(YOUR_ORG)的方式实例化一个InfluxDB客户端,然后调用该实例上的方法查表,如queryApi.queryRows(fluxQuery, fluxObserver)。但我们不仅要查表,还要将查找后的结果响应给前端(这里后端用的是 Node.js + Koa ),但问题是怎么响应,一开始我是这样做的:
const clientDB = new InfluxDB({url: **your_url**, token: **your_token**});
const queryApi = clientDB.getQueryApi(**your_org**);
const query = `from(bucket: "${**your_bucket**}") |> range(start: -1h)`;

let res: any = null;
let isSuccess: boolean = false;
queryApi.queryRows(query, {
    next(row: any, tableMeta: { toObject: (arg0: any) => any }) {
        const o = tableMeta.toObject(row)
        res = o;
        console.log('1', isSuccess); // false
        isSuccess = true;
        console.log('2', isSuccess); // true
    },
    error() {
        isSuccess = false;
    },
    complete() {}
})

console.log('3', isSuccess); // false
if (isSuccess) {
    // 这里为了方便,直接这样写了,正常情况是会对响应数据进行封装的。
    ctx.body = {
        code: 200,
        msg: '查询成功',
        data: {
            status: true,
            response: res
        }
    }; 
} else {
    ctx.body = {
        code: 0,
        msg: '查无此数据',
        data: {
            status: false,
        }
    }
}

但发现行不通,不仅isSuccess修改不成功,而且调用顺序不正确:3false-1false--2true,于是我以为是数据异步了,但再次修改后发现调用顺序虽然正确了,但数据依然没响应。在经过无数文章的翻阅后,我终于找到了解决方法,直接上代码:

const clientDB = new InfluxDB({url: **your_url**, token: **your_token**});
const queryApi = clientDB.getQueryApi(**your_org**);
const query = `from(bucket: "${**your_bucket**}") |> range(start: -1h)`;

return ctx.body = await new Promise((resolve, reject) => {
    let res: any = null;
    let arr: any[] = [];

    queryApi.queryRows(query, {
        next(row: any, tableMeta: { toObject: (arg0: any) => any }) {
            const o = tableMeta.toObject(row)
            arr.push(o);
            if (arr.length > 0) {
                res = {
                    code: 200,
                    msg: '数据查询成功',
                    data: {
                        status: true,
                        response: arr
                    }
                }
            }
        },
        error() {
            res = {
                code: 500,
                msg: '数据查询失败',
                data: {
                    status: false,
                }
            }
            reject(res);
        },
        complete() {
            if (arr.length === 0) {
                res = {
                    code: 0,
                    msg: '查无此数据',
                    data: {
                        status: false,
                    }
                }
            }
            resolve(res);
        }
    })
})

queryApi.queryRows使用 promise 包裹起来后,终于有返回结果了。

image.png