Hyperledger Fabric Nodejs SDK Eventhub был закрыт - PullRequest
0 голосов
/ 12 октября 2018

Я развернул пример сети fabcar на платформе IBM Blockchain и использую код из этого репозитория для взаимодействия с ним.Взаимодействие прекрасно работает, когда я вызываю каждую функцию по отдельности.

Проблема возникает, когда я разрабатываю сервер узла и выставляю API для кода вызова invoke.Как только я это делаю, я получаю сообщение об ошибке

Не удалось успешно вызвать :: Ошибка: возникла проблема с концентратором событий :: Ошибка: EventHub был отключен

Любопытно, что когда я отправляю 3 запроса одновременно на вызов POST, я получаю эту ошибку.Но запись вставляется в облако IBM.

Когда я отправляю 100 запросов одновременно, только около 20 вставляются в облако, а остальные показывают эту ошибку и дополнительную ошибку, подобную этой

ошибка: [Orderer.js]: sendBroadcast - при ошибке: «Ошибка: 14 НЕДОСТУПНО: Ошибка подключения \ n при createStatusError (/ home / trs-laptop-20 / Downloads / fabcar-network / node_modules / fabric-client / node_modules /grpc / src / client.js: 64: 15) \ n в ClientDuplexStream._emitStatusIfDone (/home/trs-laptop-20/Downloads/fabcar-network/node_modules/fabric-client/node_modules/grpc/src/client.js:270: 19) \ n в ClientDuplexStream._readsDone (/home/trs-laptop-20/Downloads/fabcar-network/node_modules/fabric-client/node_modules/grpc/src/client.js:236:8)\n в readCallback(/home/trs-laptop-20/Downloads/fabcar-network/node_modules/fabric-client/node_modules/grpc/src/client.js:296:12)"

И это в некоторыхслучаи

ошибка: [client-utils.js]: sendPeersProposal - Promise is reected: Ошибка: 14 НЕДОСТУПЕН: Ошибка подключения при новом createStatusError (/home/trs-laptop-20/Downloads/fabcar-network/node_modules/fabric-client/node_modules/grpc/src/client.js:64:15) в /home / trs-laptop-20 / Загрузки / fabcar-network / node_modules / fabric-client / node_modules / grpc / src / client.js: 583: 15

Я не могу понять, почему эти ошибкипоказ.Мне нужно разработать высокопроизводительное приложение, которое может справиться с нагрузкой, любая помощь и руководство будут очень благодарны.

Это мой код app.js:

'use strict';

//get libraries
const express = require('express');
const bodyParser = require('body-parser');
const request = require('request');
const path = require('path');

//create express web-app
const app = express();
const router = express.Router();
app.use(bodyParser.json());
const invoke = require('./invokeNetwork.js');

//declare port
var port = process.env.PORT || 8000;
if (process.env.VCAP_APPLICATION) {
  port = process.env.PORT;
}

//run app on port
app.listen(port, function() {
  console.log('app running on port: %d', port);
});

app.post('/api/post', async function(req,res){
    var carID = req.body.carID;
    var make = req.body.make;
    var model = req.body.model;
    var color = req.body.color;
    var owner = req.body.owner;

  await invoke.invokeCreate(carID, make, model, color, owner).then((response) => {
    //return error if error in response
    if (response.status == 500) {
      res.status(500).send({ error: response.message });
    } else {
      //else return success
      res.status(200).send({ message: response.message });
    }
  }).catch(err => {
    console.log(err);
  });

});

И этоinvokeNetwork.js код

'use strict';

var Fabric_Client = require('fabric-client');
var path = require('path');
var util = require('util');
var os = require('os');
var fs = require('fs');

var isError = false;
var throwError = "";

//make sure we have the profiles we need
var networkConfig = path.join(__dirname, './config/network-profile.json')
var clientConfig = path.join(__dirname, './config/client-profile.json');

module.exports = {

invokeCreate: async function(carID, make, model, color, owner) {

  isError = false;

//try {

  checkProfilesExist(networkConfig, clientConfig); //terminates early if they are not found

// load the base network profile
var fabric_client = Fabric_Client.loadFromConfig(path.join(__dirname, './config/network-profile.json'));

// overlay the client profile over the network profile
fabric_client.loadFromConfig(path.join(__dirname, './config/client-profile.json'));

// setup the fabric network - get the channel that was loaded from the network profile
var channel = fabric_client.getChannel('defaultchannel');
var tx_id = null;

//load the user who is going to unteract with the network
fabric_client.initCredentialStores().then(() => {
  // get the enrolled user from persistence, this user will sign all requests
  return fabric_client.getUserContext('user1', true);
}).then((user_from_store) => {
  if (user_from_store && user_from_store.isEnrolled()) {
    console.log('Successfully loaded user1 from persistence');

  } else {
    throw new Error('Failed to get user1.... run registerUserNetwork.js');
  }

  // get a transaction id object based on the current user assigned to fabric client
  tx_id = fabric_client.newTransactionID();
  console.log("Assigning transaction_id: ", tx_id._transaction_id);

  // createCar chaincode function - requires 5 args, ex: args: ['CAR11', 'Honda', 'Accord', 'Black', 'Dave'],
  // changeCarOwner chaincode function - requires 2 args , ex: args: ['CAR11', 'MGK'],
    var request = {
        chaincodeId: 'fabcar',
        fcn: 'createCar',
        args: [carID, make, model, color, owner],
        txId: tx_id
  };

  // send the transaction proposal to the endorsing peers
  return channel.sendTransactionProposal(request);
}).then((results) => {
  var proposalResponses = results[0];
  var proposal = results[1];
  let isProposalGood = false;
  if (proposalResponses && proposalResponses[0].response &&
    proposalResponses[0].response.status === 200) {
    isProposalGood = true;
    console.log('Transaction proposal was good');
  } else {
    console.error('Transaction proposal was bad');

  }
  if (isProposalGood) {
    console.log(util.format(
      'Successfully sent Proposal and received ProposalResponse: Status - %s, message - "%s"',
      proposalResponses[0].response.status, proposalResponses[0].response.message));

    // build up the request for the orderer to have the transaction committed
    var request = {
      proposalResponses: proposalResponses,
      proposal: proposal
    };

    // set the transaction listener and set a timeout of 30 sec
    // if the transaction did not get committed within the timeout period,
    // report a TIMEOUT status
    var transaction_id_string = tx_id.getTransactionID(); //Get the transaction ID string to be used by the event processing
    var promises = [];

    var sendPromise = channel.sendTransaction(request);
    promises.push(sendPromise); //we want the send transaction first, so that we know where to check status

    // get an eventhub once the fabric client has a user assigned. The user
    // is required bacause the event registration must be signed
    console.error('Getting event hub');
    let event_hub = fabric_client.getEventHub('org1-peer1');

    // using resolve the promise so that result status may be processed
    // under the then clause rather than having the catch clause process
    // the status
    let txPromise = new Promise((resolve, reject) => {
      let handle = setTimeout(() => {
        event_hub.disconnect();
        resolve({ event_status: 'TIMEOUT' }); //we could use reject(new Error('Trnasaction did not complete within 30 seconds'));
      }, 3000);
      event_hub.connect();
      event_hub.registerTxEvent(transaction_id_string, (tx, code) => {
        // this is the callback for transaction event status
        // first some clean up of event listener
        clearTimeout(handle);
        event_hub.unregisterTxEvent(transaction_id_string);
        event_hub.disconnect();

        // now let the application know what happened
        var return_status = { event_status: code, tx_id: transaction_id_string };
        if (code !== 'VALID') {
          console.error('The transaction was invalid, code = ' + code);
          resolve(return_status); // we could use reject(new Error('Problem with the tranaction, event status ::'+code));
        } else {
          console.log('The transaction has been committed on peer ' + event_hub._ep._endpoint.addr);
          resolve(return_status);
        }
      }, (err) => {
        //this is the callback if something goes wrong with the event registration or processing
        reject(new Error('There was a problem with the eventhub ::' + err));
        throwError += err;
      });
    });
    promises.push(txPromise);

    return Promise.all(promises);
  } else {
    console.error('Failed to send Proposal or receive valid response. Response null or status is not 200. exiting...');
    throw new Error('Failed to send Proposal or receive valid response. Response null or status is not 200. exiting...');
  }
}).then((results) => {
  console.log('Send transaction promise and event listener promise have completed');
  // check the results in the order the promises were added to the promise all list
  if (results && results[0] && results[0].status === 'SUCCESS') {
    console.log('Successfully sent transaction to the orderer.');
  } else {
    console.error('Failed to order the transaction. Error code: ' + response.status);
    throw new exception("Transaction");
  }

  if (results && results[1] && results[1].event_status === 'VALID') {
    console.log('Successfully committed the change to the ledger by the peer');
    return true;
  } else {
    console.log('Transaction failed to be committed to the ledger due to ::' + results[1].event_status);
  }
}).catch((err) => {
  console.error('Failed to invoke successfully :: ' + err);
  isError = true;
  throwError += err;
});

console.log(isError);

return {
  message: (isError) ? throwError : 'Success Transaction'
}

function checkProfilesExist(networkConfig, clientConfig) {
  if (!fs.existsSync(networkConfig)) {
    console.log("Error: config file 'network-profile.json' not found.");
    console.log("Make sure 'network-profile.json' is copied into the './config' folder.");
    process.exit()
  }

  //make sure we have the client profile we need

  if (!fs.existsSync(clientConfig)) {
    console.log("Error: config file 'client-profile.json' not found.");
    console.log("Make sure 'client-profile.json' is copied into the './config' folder.");
    process.exit()
  }
}

}

}
//throw new exception("Exceoption thrown");
//return true;
// }
//   catch(err) {
//     //print and return error
//     console.log(err);
//     var error = {};
//     error.error = err.message;
//     return error;
//     }
//   }
// }

Ответы [ 2 ]

0 голосов
/ 03 апреля 2019

Как очень четко объяснил Прияв Шах, полное исправление требует, чтобы вы изменили свой API, чтобы обойти проблему.

Если вы просто ищете кратковременное решение для повторного запуска приемника событий концентратора наодноранговый узел, простое исправление состоит в том, чтобы повторно запустить одноранговый узел и заставить его повторно присоединиться к каналу и повторно установить на него цепные коды.

0 голосов
/ 12 октября 2018

Итак, мы поэкспериментировали с тканью, пытаясь протестировать некоторые характеристики.У меня были все те же проблемы, с которыми вы сталкивались, поэтому объясню наши проблемы и, надеюсь, они помогут вам.

Завершение Eventhub

Error: There was a problem with the eventhub ::Error: EventHub has been shutdown

Проблема

Заметил, что это произойдет, когда мы отправим большое количество транзакций, а также, когда мы будем использовать хитрое интернет-соединение.Состояние документация фабрики :

События эфемерны, так что, если зарегистрированный слушатель потерпел крах, когда событие опубликовано, слушатель пропустит событие

Я полагаю, что проблема заключалась в том, что концентратор событий пытался подключиться к нашему API, но была проблема с подключением.Это приводит к тому, что для концентратора событий происходит тайм-аут (так как он не получает ответ), что затем приводит к отключению концентратора событий.

Решение

Снова в документах фабрики рекомендуется:

  • прослушивание на уровне блоков, поэтому, даже если вы пропустите блок, вы можете выбрать старые блоки (подробнее см. Ссылку на документацию по ткани выше)
  • Создайте собственную очередь

проверьте этот pastebin для прослушивателя базового блока -> https://pastebin.com/wCd6Ni46

Ошибка: 14 UNAVAILABLE

Проблема

Мы заметили, когда начали отправлять большой объемтранзакций, мы также в конечном итоге с ошибкой: 14 недоступен, но это было после того, как сеть была заполнена большим количеством транзакций.Я думаю, что у нас было 20 штук в партии, но когда мы отправили 50 или более в быстрой последовательности, он не справился.

Помните, что блоки, по крайней мере, при добавлении IBP-стартера, ограничены 10 трансациями на блок, поэтому необходимо дождаться, пока он будет добыт, прежде чем он сможет обработать следующий набор транзакций.Я полагаю, что в этом процессе буфер заполняется, и тогда вы не можете отправить слишком много.

Таким образом, ваши две ошибки связаны с тем, что заказчику заполонили, или к партнеру затопило слишком много транзакций.

Решение

Объедините транзакции в блоки и подождите, пока эти транзакции не будут подтверждены, прежде чем отправлять еще некоторые.Это дает вашим сверстникам и заказчикам некоторое пространство для дыхания.

Надеюсь, это поможет!

...