Hyperledger Fabric Node.js怎么使用基于通道的事件服务

发布时间:2021-12-06 17:30:57 作者:小新
来源:亿速云 阅读:139

小编给大家分享一下Hyperledger Fabric Node.js怎么使用基于通道的事件服务,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

概述

客户端应用程序可以使用Fabric Node.js客户端注册“侦听器”以在将块添加到通道分类帐时接收块。我们将这些称为“基于通道的事件”,它们允许客户端开始接收来自特定块编号的块,从而允许事件处理在可能已丢失的块上正常运行。Fabric Node.js客户端还可以通过处理传入的块并查找特定的交易或链代码事件来协助客户端应用程序。这允许客户端应用程序被通知交易完成或任意链代码事件,而不必在接收时执行多个查询或搜索块。

该服务允许任何用户接收“过滤的”块事件(换句话说,不包含敏感信息)。接收“未过滤”的块事件需要对通道进行读访问。默认行为是连接以接收过滤的块事件。要连接以接收未过滤的块事件,请调用connect(true)(参见下文)。

请注意,如果你注册块事件然后提交交易,则不应对包含交易的块进行任何假设。特别是,你不应该假设你的交易处于与注册到对等方基于通道的事件服务之后收到的第一个块事件关联的块中。相反,你可以只注册一个交易事件。

通道上的API

在v1.1中新增的ChannelEventHub和API:
节点参数

获取ChannelEventHub的新实例时必须包含此参数。使用连接配置文件时,该值可以是Peer实例或节点的名称,请参阅如何使用公共网络配置文件。

eventCallback参数

必须包含此参数。这是当此通道接收新块时,在侦听特定交易或链代码事件时要通知的回调函数。

errorCallback参数

这是一个可选参数。这是在此通道事件路由关闭时要通知的回调函数。关闭可能是由结构网络错误,网络连接问题或通过调用disconnect()方法引起的。

options参数

这是一个可选参数。此参数将包含以下可选属性:

获取基于通道的事件路由

Fabric Node.js客户端Channel对象中添加了新方法,以简化ChannelEventHub对象的设置。使用以下命令获取将设置为与对等方基于通道的事件服务一起使用的ChannelEventHub实例。ChannelEventHub实例将使用对等实例正在使用的所有相同端点配置设置,例如tls证书以及主机和端口地址。

使用连接配置文件(请参阅参考资料)时,可以使用节点的名称来获取新的通道事件路由。

var channel_event_hub = channel.newChannelEventHub('peer0.org1.example.com');

以下是在使用连接配置文件时如何获取通道事件路由列表的示例。以下内容将根据连接配置文件的当前活动客户端client部分中定义的当前组织获取列表。组织中定义的将eventSource设置为true的对象将添加到列表中。

var channel_event_hubs = channel.getChannelEventHubsForOrg();

创建节点实例时,可以使用节点实例获取ChannelEventHub实例。

let data = fs.readFileSync(path.join(__dirname, 'somepath/tlscacerts/org1.example.com-cert.pem'));
let peer = client.newPeer(
    'grpcs://localhost:7051',
    {
        pem: Buffer.from(data).toString(),
        'ssl-target-name-override': 'peer0.org1.example.com'
    }
);
let channel_event_hub = channel.newChannelEventHub(peer);

区块侦听器

当需要监视要添加到分类帐的新块时,请使用块事件侦听器。当新块被提交给节点上的分类帐时,将通知Fabric客户端Node.js.然后,客户端Node.js将调用应用程序的已注册回调。回调将传递新添加的块的JSON表示。请注意,当未使用true值调用connect()时,回调将接收过滤块。注册接收完整块的用户的访问权限将由节点的基于信道的事件服务检查。当需要查看先前添加的块时,回调的注册可以包括起始块号。回调将开始从此号码接收块,并在添加到分类帐时继续接收新块。这是应用程序resume和replay在应用程序脱机时可能已丢失的事件的一种方法。应用程序应记住它已处理的最后一个块,以避免replay整个分类帐。

以下示例将注册块侦听器以开始接收块。

// keep the block_reg to unregister with later if needed
block_reg = channel_event_hub.registerBlockEvent((block) => {
    console.log('Successfully received the block event');
    <do something with the block>
}, (error)=> {
    console.log('Failed to receive the block event ::'+error);
    <do something with the error>
});

以下示例将使用起始块编号进行注册,因为此应用程序需要在特定块中恢复并replay丢失的块。应用程序回调将像当前事件一样处理同一区域中的replay块。块侦听器将继续接收块,因为它们已提交到节点的分类帐。

// keep the block_reg to unregister with later if needed
block_reg = channel_event_hub.registerBlockEvent((block) => {
    console.log('Successfully received the block event');
    <do something with the block>
}, (error)=> {
    console.log('Failed to receive the block event ::'+error);
    <do something with the error>
},
    {startBlock:23}
);

以下示例将使用起始块编号和结束块进行注册。应用程序需要replay丢失的块。应用程序回调将处理与当前事件相同的区域中的replay块。当侦听器看到结束块事件时,块侦听器将自动取消注册,并且ChannelEventHub将关闭。申请将不必处理此句柄。

block_reg = channel_event_hub.registerBlockEvent((block) => {
    console.log('Successfully received the block event');
    <do something with the block>
}, (error)=> {
    console.log('Failed to receive the block event ::'+error);
    <do something with the error>
},
    // for block listeners, the defaults for unregister and disconnect are true,
    // so the they are not required to be set in the following example
    {startBlock:23, endBlock:30, unregister: true, disconnect: true}
);

交易监听器

当需要监视组织对等方的交易完成时,请使用交易侦听器。当新块被提交给节点上的分类帐时,将通知客户端Node.js.然后,客户端将检查块是否已注册的交易标识符。如果找到交易,则将通过交易ID,交易状态和块编号通知回调。过滤的块包含交易状态,因此无需连接到对等方的基于通道的事件服务即可接收完整的块。由于大多数非管理员用户将无法看到完整的块,因此当这些用户只需要监听其提交的交易时,连接到接收过滤的块将避免访问问题。

以下示例将显示在javascript承诺中注册交易ID并构建另一个将交易发送到订购者的承诺。这两个承诺将一起执行,以便一起收到两个行动的结果。使用交易侦听器,取消注册的默认可选设置为true。因此,在以下示例中,在侦听器看到交易之后,将注册的侦听器将自动取消注册。

let tx_object = client.newTransactionID();

// get the transaction ID string for later use
let tx_id = tx_object.getTransactionID();

let request = {
    targets : targets,
    chaincodeId: 'my_chaincode',
    fcn: 'invoke',
    args: ['doSomething', 'with this data'],
    txId: tx_object
};

return channel.sendTransactionProposal(request);
}).then((results) => {
// a real application would check the proposal results
console.log('Successfully endorsed proposal to invoke chaincode');

// start block may be null if there is no need to resume or replay
let start_block = getBlockFromSomewhere();

let event_monitor = new Promise((resolve, reject) => {
    let handle = setTimeout(() => {
        // do the housekeeping when there is a problem
        channel_event_hub.unregisterTxEvent(tx_id);
        console.log('Timeout - Failed to receive the transaction event');
        reject(new Error('Timed out waiting for block event'));
    }, 20000);

    channel_event_hub.registerTxEvent((event_tx_id, status, block_num) => {
        clearTimeout(handle);
        //channel_event_hub.unregisterTxEvent(event_tx_id); let the default do this
        console.log('Successfully received the transaction event');
        storeBlockNumForLater(block_num);
        resolve(status);
    }, (error)=> {
        clearTimeout(handle);
        console.log('Failed to receive the transaction event ::'+error);
        reject(error);
    },
        // when this `startBlock` is null (the normal case) transaction
        // checking will start with the latest block
        {startBlock:start_block}
        // notice that `unregister` is not specified, so it will default to true
        // `disconnect` is also not specified and will default to false
    );
});
let send_trans = channel.sendTransaction({proposalResponses: results[0], proposal: results[1]});

return Promise.all([event_monitor, send_trans]);
}).then((results) => {

Chaincode事件监听器

当需要监控将在您的链代码中发布的事件时,请使用链代码事件监听器。当新块提交到分类帐时,将通知客户端Node.js.然后,客户端将在链代码事件的名称字段中检查已注册的链代码模式。监听器的注册包括用于检查链代码事件名称的正则表达式。如果发现链代码事件名称与侦听器的正则表达式匹配,则将通过链代码事件,块编号,交易ID和交易状态通知侦听器的回调。过滤的块将不具有链码事件有效载荷信息;它只有chaincode事件名称。如果需要有效载荷信息,则用户必须能够访问完整块,并且通道事件中心必须连接(true)以从对等方的基于通道的事件服务接收完整块事件。

以下示例演示如何在javascript承诺中注册链代码事件侦听器,并构建另一个将交易发送到订购者的承诺。这两个承诺将一起执行,以便一起收到两个行动的结果。如果长期监视需要chaincode事件侦听器,请遵循上面的块侦听器示例。

let tx_object = client.newTransactionID();
let request = {
    targets : targets,
    chaincodeId: 'my_chaincode',
    fcn: 'invoke',
    args: ['doSomething', 'with this data'],
    txId: tx_object
};

return channel.sendTransactionProposal(request);
}).then((results) => {
// a real application would check the proposal results
console.log('Successfully endorsed proposal to invoke chaincode');

// Build the promise to register a event listener with the NodeSDK.
// The NodeSDK will then send a request to the peer's channel-based event
// service to start sending blocks. The blocks will be inspected to see if
// there is a match with a chaincode event listener.
let event_monitor = new Promise((resolve, reject) => {
    let regid = null;
    let handle = setTimeout(() => {
        if (regid) {
            // might need to do the clean up this listener
            channel_event_hub.unregisterChaincodeEvent(regid);
            console.log('Timeout - Failed to receive the chaincode event');
        }
        reject(new Error('Timed out waiting for chaincode event'));
    }, 20000);

    regid = channel_event_hub.registerChaincodeEvent(chaincode_id.toString(), '^evtsender*',
        (event, block_num, txnid, status) => {
        // This callback will be called when there is a chaincode event name
        // within a block that will match on the second parameter in the registration
        // from the chaincode with the ID of the first parameter.
        console.log('Successfully got a chaincode event with transid:'+ txnid + ' with status:'+status);

        // might be good to store the block number to be able to resume if offline
        storeBlockNumForLater(block_num);

        // to see the event payload, the channel_event_hub must be connected(true)
        let event_payload = event.payload.toString('utf8');
        if(event_payload.indexOf('CHAINCODE') > -1) {
            clearTimeout(handle);
            // Chaincode event listeners are meant to run continuously
            // Therefore the default to automatically unregister is false
            // So in this case we want to shutdown the event listener once
            // we see the event with the correct payload
            channel_event_hub.unregisterChaincodeEvent(regid);
            console.log('Successfully received the chaincode event on block number '+ block_num);
            resolve('RECEIVED');
        } else {
            console.log('Successfully got chaincode event ... just not the one we are looking for on block number '+ block_num);
        }
    }, (error)=> {
        clearTimeout(handle);
        console.log('Failed to receive the chaincode event ::'+error);
        reject(error);
    }
        // no options specified
        // startBlock will default to latest
        // endBlock will default to MAX
        // unregister will default to false
        // disconnect will default to false
    );
});

// build the promise to send the proposals to the orderer
let send_trans = channel.sendTransaction({proposalResponses: results[0], proposal: results[1]});

// now that we have two promises all set to go... execute them
return Promise.all([event_monitor, send_trans]);
}).then((results) => {

======================================================================

分享一些比特币、以太坊、EOS、Fabric等区块链相关的交互式在线编程实战教程:

以上是“Hyperledger Fabric Node.js怎么使用基于通道的事件服务”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!

推荐阅读:
  1. Hyperledger Fabric PHP SDK
  2. HyperLedger Fabric 交易流程

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

node.js fabric hyperledger

上一篇:CISCO路由器端口故障的解决办法

下一篇:服务端的多路复用如何解决连接高并发问题

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》