(async) JSON RPC API 性能优化
(async) JSON RPC API performance optimization
我必须制作一个 JSON RPC API,它必须支持大流量并管理 postgreSQL 数据库。
为此,我为服务器选择了 'http',为数据库选择了 pg-promise。
我的问题是我在理解和使用 promises 和 async/wait 时遇到了一些困难,所以我不确定我是否做对了
我在下面放了一些代码
我做了什么
- ./server/server.js 创建一个带有
requestHandler()
作为请求处理程序的 http 服务器。它会做一些检查,然后调用 async requestProcessor()
来执行方法
- 方法在回购协议(这里是 devices.js 中的交易)中定义为
async
,在我下面的示例中使用 await
等待所需的结果
一些问题:
- 我必须将应该使用
await
的方法定义为 async
?
- 在我的 SystemRepository 中,是否需要将 'InsertOneSystem' 定义为
async
?
- 如何做一个简单的测试脚本来测试负载?就像每秒请求一样,... ?
提前致谢!
一点代码
server.js
const http = require('http');
const Database = require('../db');
const path = '/api/v1', port = 9000;
const methods = Database.methods;
/* hidden for brevity */
function sendResponse(res, response) {
if (response) {
const responseStr = JSON.stringify(response);
res.setHeader('Content-Type', 'application/json');
res.setHeader('Content-Length', responseStr.length);
res.write(responseStr);
} else {
/* hidden for brevity */
}
res.end();
}
const requestHandler = (req, res) => {
/* some checks, hidden for brevity */
const body = [];
req.on('data', (chunk) => {
body.push(chunk);
}).on('end', () => {
const bodyStr = Buffer.concat(body).toString();
// parse body en JSON
let request = JSON.parse(bodyStr);
requestProcessor(request).then((response) => {
sendResponse(res, response);
});
});
}
async function requestProcessor(request) {
let response = {
id: request.id,
jsonrpc: '2.0',
};
try {
response.result = await Promise.resolve(methods[request.method](request.params));
} catch (err) {
/* hidden for brevity */
}
return response;
}
const server = http.createServer(requestHandler);
server.listen(port, (err) => { /* hidden for brevity */ });
devices.js
'use strict';
/* hidden for brevity */
async function InsertOne(params) {
return Database.tx('Insert-New-Device', async function(transaction) {
let system = null, disks = null, cpus = null;
const query = pgp.helpers.insert(params.data.device, Collections.insert) + " RETURNING *";
let device = await transaction.one(query);
// if a system is present, insert with diviceId and return
if(params.data.system) {
params.data.system.deviceid = device.deviceid;
system = transaction.systems.InsertOne(params);
}
// same as system
if(params.data.disks) {
params.data.disks.deviceid = device.deviceid;
disks = transaction.disks.InsertOne(params);
}
// same as system
if(params.data.cpus) {
params.data.cpus.deviceid = device.deviceid;
cpus = transaction.cpus.InsertOne(params);
}
return {
device: device,
system: await system,
disks: await disks,
cpus: await cpus
}
})
.then(data => {
return data;
})
.catch(ex => {
console.log(ex)
throw new Error(ex);
});
}
/* hidden for brevity */
const DevicesRepository = {
InsertOne: InsertOne
};
module.exports = (db, pgpLib) => {
/* hidden for brevity */
return DevicesRepository;
}
systems.js
'use strict';
/* hidden for brevity */
async function InsertOneSystem(params) {
var system = params.data.system;
system.archid=2;
system.distributionid=3;
var query = pgp.helpers.insert(system, Collections.insert);
if(params.return) query += " RETURNING *";
return Database.one(query)
.then(data => {
return data;
})
.catch(ex => {
throw new Error(ex);
});
}
/* hidden for brevity */
const SystemsRepository = {
InsertOne: InsertOneSystem
};
module.exports = (db, pgpLib) => {
/* hidden for brevity */
return SystemsRepository;
}
I have to define as async
only the methods that should use await ?
必须-是的。但是你应该在所有 return 承诺的方法上使用 async
,这是一种很好的编码风格,尤其是在 TypeScript 中。
In my SystemRepository
, do I need to define InsertOneSystem
as async ?
你不必,但和上面一样,这是一种很好的编码风格;)
How can I do a simple test script to test the load ? Like requests per second, ... ?
我现在不回答这个问题,因为这是一个完全独立的领域,值得单独提问。你应该自己调查一下,如何测试HTTP服务负载。
一点代码改进,因为你有很多冗余:
async function InsertOne(params) {
return Database.tx('Insert-New-Device', async t => {
let system = null, disks = null, cpus = null;
const query = pgp.helpers.insert(params.data.device, Collections.insert) + " RETURNING *";
let device = await t.one(query);
// if a system is present, insert with diviceId and return
if(params.data.system) {
params.data.system.deviceid = device.deviceid;
system = await t.systems.InsertOne(params);
}
// same as system
if(params.data.disks) {
params.data.disks.deviceid = device.deviceid;
disks = await t.disks.InsertOne(params);
}
// same as system
if(params.data.cpus) {
params.data.cpus.deviceid = device.deviceid;
cpus = await t.cpus.InsertOne(params);
}
return {device, system, disks, cpus};
})
.catch(ex => {
console.log(ex); // it is better use "pg-monitor", or handle events globally
throw ex;
});
}
我必须制作一个 JSON RPC API,它必须支持大流量并管理 postgreSQL 数据库。 为此,我为服务器选择了 'http',为数据库选择了 pg-promise。 我的问题是我在理解和使用 promises 和 async/wait 时遇到了一些困难,所以我不确定我是否做对了
我在下面放了一些代码
我做了什么
- ./server/server.js 创建一个带有
requestHandler()
作为请求处理程序的 http 服务器。它会做一些检查,然后调用async requestProcessor()
来执行方法 - 方法在回购协议(这里是 devices.js 中的交易)中定义为
async
,在我下面的示例中使用await
等待所需的结果
一些问题:
- 我必须将应该使用
await
的方法定义为async
? - 在我的 SystemRepository 中,是否需要将 'InsertOneSystem' 定义为
async
? - 如何做一个简单的测试脚本来测试负载?就像每秒请求一样,... ?
提前致谢!
一点代码
server.js
const http = require('http');
const Database = require('../db');
const path = '/api/v1', port = 9000;
const methods = Database.methods;
/* hidden for brevity */
function sendResponse(res, response) {
if (response) {
const responseStr = JSON.stringify(response);
res.setHeader('Content-Type', 'application/json');
res.setHeader('Content-Length', responseStr.length);
res.write(responseStr);
} else {
/* hidden for brevity */
}
res.end();
}
const requestHandler = (req, res) => {
/* some checks, hidden for brevity */
const body = [];
req.on('data', (chunk) => {
body.push(chunk);
}).on('end', () => {
const bodyStr = Buffer.concat(body).toString();
// parse body en JSON
let request = JSON.parse(bodyStr);
requestProcessor(request).then((response) => {
sendResponse(res, response);
});
});
}
async function requestProcessor(request) {
let response = {
id: request.id,
jsonrpc: '2.0',
};
try {
response.result = await Promise.resolve(methods[request.method](request.params));
} catch (err) {
/* hidden for brevity */
}
return response;
}
const server = http.createServer(requestHandler);
server.listen(port, (err) => { /* hidden for brevity */ });
devices.js
'use strict';
/* hidden for brevity */
async function InsertOne(params) {
return Database.tx('Insert-New-Device', async function(transaction) {
let system = null, disks = null, cpus = null;
const query = pgp.helpers.insert(params.data.device, Collections.insert) + " RETURNING *";
let device = await transaction.one(query);
// if a system is present, insert with diviceId and return
if(params.data.system) {
params.data.system.deviceid = device.deviceid;
system = transaction.systems.InsertOne(params);
}
// same as system
if(params.data.disks) {
params.data.disks.deviceid = device.deviceid;
disks = transaction.disks.InsertOne(params);
}
// same as system
if(params.data.cpus) {
params.data.cpus.deviceid = device.deviceid;
cpus = transaction.cpus.InsertOne(params);
}
return {
device: device,
system: await system,
disks: await disks,
cpus: await cpus
}
})
.then(data => {
return data;
})
.catch(ex => {
console.log(ex)
throw new Error(ex);
});
}
/* hidden for brevity */
const DevicesRepository = {
InsertOne: InsertOne
};
module.exports = (db, pgpLib) => {
/* hidden for brevity */
return DevicesRepository;
}
systems.js
'use strict';
/* hidden for brevity */
async function InsertOneSystem(params) {
var system = params.data.system;
system.archid=2;
system.distributionid=3;
var query = pgp.helpers.insert(system, Collections.insert);
if(params.return) query += " RETURNING *";
return Database.one(query)
.then(data => {
return data;
})
.catch(ex => {
throw new Error(ex);
});
}
/* hidden for brevity */
const SystemsRepository = {
InsertOne: InsertOneSystem
};
module.exports = (db, pgpLib) => {
/* hidden for brevity */
return SystemsRepository;
}
I have to define as
async
only the methods that should use await ?
必须-是的。但是你应该在所有 return 承诺的方法上使用 async
,这是一种很好的编码风格,尤其是在 TypeScript 中。
In my
SystemRepository
, do I need to defineInsertOneSystem
as async ?
你不必,但和上面一样,这是一种很好的编码风格;)
How can I do a simple test script to test the load ? Like requests per second, ... ?
我现在不回答这个问题,因为这是一个完全独立的领域,值得单独提问。你应该自己调查一下,如何测试HTTP服务负载。
一点代码改进,因为你有很多冗余:
async function InsertOne(params) {
return Database.tx('Insert-New-Device', async t => {
let system = null, disks = null, cpus = null;
const query = pgp.helpers.insert(params.data.device, Collections.insert) + " RETURNING *";
let device = await t.one(query);
// if a system is present, insert with diviceId and return
if(params.data.system) {
params.data.system.deviceid = device.deviceid;
system = await t.systems.InsertOne(params);
}
// same as system
if(params.data.disks) {
params.data.disks.deviceid = device.deviceid;
disks = await t.disks.InsertOne(params);
}
// same as system
if(params.data.cpus) {
params.data.cpus.deviceid = device.deviceid;
cpus = await t.cpus.InsertOne(params);
}
return {device, system, disks, cpus};
})
.catch(ex => {
console.log(ex); // it is better use "pg-monitor", or handle events globally
throw ex;
});
}