(асинхронная) оптимизация производительности JSON RPC API - PullRequest
0 голосов
/ 10 июля 2019

Мне нужно создать JSON RPC API, который будет поддерживать большой трафик и управлять базой данных postgreSQL.Для этого я выбрал «http» для сервера и pg-prom для базы данных.Моя проблема в том, что у меня есть некоторые трудности с пониманием и использованием обещаний и асинхронностью / ожиданием, поэтому я не уверен, что сделал это правильно

Я поместил код ниже

Что я сделал

  1. . / Server / server.js создает http-сервер с requestHandler() в качестве обработчика запросов.Он выполняет некоторые проверки и затем вызывает async requestProcessor() для выполнения метода
  2. Методы определены в репозиториях (здесь транзакция в devices.js) как async и в моем примере ниже используйте await длядождитесь требуемых результатов

Некоторые вопросы:

  1. Я должен определить как async только методы, которые должны использовать await?
  2. В моем SystemRepository, мне нужно определить 'InsertOneSystem' как async?
  3. Как я могу сделать простой тестовый скрипт для проверки загрузки?Как запросы в секунду, ...?

Заранее спасибо!

Немного кода

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;
}

1 Ответ

0 голосов
/ 10 июля 2019

Я должен определить как async только методы, которые следует использовать await?

Должен - да.Но вы должны использовать async во всех методах, которые возвращают обещание, это просто хороший стиль кодирования, особенно в TypeScript.

В моем SystemRepository мне нужно определить InsertOneSystem какasync?

Нет необходимости, но то же самое, что и выше, это хороший стиль кодирования;)

Как сделать простой тестовый скрипт для тестированияЗагрузка ?Как запросы в секунду, ...?

Сейчас я не отвечаю на это, поскольку это отдельная область, которая заслуживает отдельного вопроса.Вы должны сами разобраться, как проверить загрузку сервисов 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;
  });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...