这是我参与「第四届青训营」笔记创作活动的的第7天
window11 安装 influxdb
- 通过 官网 下载最新版本的 InfluxDB 。
- 下载压缩包到本地后,解压在 D 盘下:
然后win + R输入 cmd 后,在面板上进入 InfluxDB 的安装目录(或者直接在上图蓝色高亮的地方输入 cmd 并回车),启动 influxd.exe :
- influxdb 启动后可以看到上图所示,接着打开浏览器,输入地址:
http://localhost:8086即可打开 influxdb 的配置页面(第一次登录时界面不是这样的,之后登录才是)。
编写后端服务
influxdb 安装完成后,我们就可以使用时序数据库开发了。不过在开始编码之前,我们还需要理清其中逻辑及打算使用的技术栈:
- 用 nodejs + koa 写服务
- influxdb 存储监控数据,mysql 辅助存储额外的业务数据(如用户登录等)
- 用 influxdb 自带的 web 管理界面辅助查表
- 查表时使用 influxdb 的语法查询(influxdb 可能不能使用 typeorm)
理清这些后,我们终于可以开始愉快地开发后端了。
influxdb 概念类比
Buckets:数据表_measurement:表中的行_field:每一行的键_value:每一行的值_stop:数据查询时间_time:数据写入时间
开发相关
我们使用 influxdb 的 flex 语法操作数据表,相关 API 的使用参考官网即可:使用 Node.js JavaScript 客户端库
需要提醒的是:
- 写入数据时,我们会用到
new Point(),这其实就是创建表中行数据的意思,然后使用.floatField方法创建键值对。如果需要新建 整数型 、浮点型、布尔型 等数据,可以进入Point对象查看源代码(按住 ctrl 键 ,鼠标点击即可跳转): - 查询表数据我们是使用
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 包裹起来后,终于有返回结果了。