多个公证员提高网络吞吐量

您是否需要非常高吞吐量的Corda网络? 网络的吞吐量是否稳定? 您是否已经从其他领域挤出了所有可能的表现? 如果您对这些问题的回答是“是”,那么我可能会为您提供一些有用的信息。 我列出了这些问题,以减少您过早优化Corda网络/应用程序的机会。 如果它是处理请求/事务中最慢的部分之一,则切换到使用多个公证人只会对性能产生显着影响。 在考虑使用多个公证人之前,很可能需要改进其他方面。

在我继续之前。 我真的需要这么说。 在本文中,我并不是在谈论使用公证集群,该公证集群由相互沟通以就是否使用了州达成共识的公证组成。 我说的是拥有多个公证人,每个公证人都有自己的身份,这些公证人仅与向其发送交易以进行验证的节点进行交互。 这种区别必须加以区分,并且应该消除对我将在本文中准确描述的任何混淆。

在撰写本文时,Corda的当前版本为:

  • 开源3.3
  • 企业3.2

我为什么要这样做?

好吧 让我们真正深入探讨为什么要使用多个公证人。 图表最能做到这一点,所以让我们使用一个:

多个公证人

具有一个公证人的网络的简单视图

这种情况看起来不太好。 但是,实际上可能并不那么糟糕。 如果网络的吞吐量不是很高,则此体系结构应该能够处理通过公证人的事务。

如引言中所述。 当发送到公证人的交易率变得很高时,这成为一个问题。 一旦达到这一点,公证人将开始落后。 因为它不能足够快地验证事务中的状态。 如果性能对网络很重要,那么这是检查的好地方。

从代码角度来看,这是您可能已经在编写CorDapps的标准格式。 您可以根据特定条件挑选公证人,然后在其中发送交易。 您所处理的整个网络中甚至可能只有一个公证人。 例如,在编写类似于以下代码的代码之前,在我编写的所有代码示例中,它们仅依赖于网络中的单个公证人,每次都盲目地使用那个公证人。

private fun notary(): Party = serviceHub.networkMapCache.notaryIdentities.first()

切换到多个公证人

从依赖一个公证人的网络过渡到一个由许多公证人组成的设计,从根本上讲,需要两件事:

  • 网络中有多个公证人。
  • 一种选择向哪个公证人发送交易的算法。

此外,如果使用状态,则将来的交易会参考为交易选择的公证人。 如果最终导致消耗了来自不同公证人的输入状态的情况,则必须执行公证人变更事务。 稍后我将讨论这个主题。

下面是如何更改先前的设计以使用一些公证人的方法:

多个公证人

具有多个公证人的网络的简化视图

关于此图的最好之处在于,它说明了向网络添加另一个公证人并在其中重新分配负载是多么简单。 没有什么可以阻止我们向网络中添加越来越多的公证人。 但是,在某些情况下添加更多内容不会导致性能提高。 这一直回到我之前提到的内容。 添加更多的公证人只会在公证人本身达到饱和时增加吞吐量。

为发行交易选择公证人

以下是选择使用哪种公证人的可能算法:

private fun transaction(): TransactionBuilder =TransactionBuilder(notary()).apply {addOutputState(message, MessageContract.CONTRACT_ID)addCommand(Send(), message.participants.map(Party::owningKey))}private fun notary(): Party {val index = message.type.hashCode() % serviceHub.networkMapCache.notaryIdentities.sizereturn serviceHub.networkMapCache.notaryIdentities.single { it.name.organisation == "Notary-$index" }
}

在此示例中,事务根据输入状态的属性之一的hashCode和网络中的公证人数来选择要使用的公证人。

选择公证人的方式可以根据需要简单或复杂。 这将取决于要求,例如,仅一部分公证人的提议交易受信任,或者网络变化中对公证人的弹性。

从同一公证人消费状态时选择公证人

这是很好而且很简单的…如果所有输入状态都引用同一个公证人。 下面是它的外观(此示例仅使用一个输入…,因为我懒于编写另一个版本):

private fun transaction(response: MessageState): TransactionBuilder =TransactionBuilder(notary()).apply {addInputState(message)addOutputState(response, MessageContract.CONTRACT_ID)addCommand(Reply(), response.participants.map(Party::owningKey))}private fun notary(): Party = message.state.notary

如您所见,所有事务要做的就是检索与输入状态相关的公证人,并将其用于自身。 可以提取此信息,因为messageStateAndRef ,访问其state属性将返回TransactionState 。 遵循这种格式。 创建消耗状态并产生大量输出的新事务非常简单。 此格式对于多个输入状态也有效。 当且仅当它们都引用同一个公证人。

因此……讨论所有带有不同公证人的输入状态。 我可能应该进一步讨论。

消费来自不同公证人的状态时选择公证人

在这里我们必须要小心,否则我们将看到类似以下的错误:

java.lang.IllegalArgumentException: Input state requires notary "O=Notary-1, L=London, C=GB" which does not match the transaction notary "O=Notary-0, L=London, C=GB".

该错误表明输入状态与包含它的事务没有相同的公证人。

要解决此错误,我们需要使用公证更改交易。 根据文档:

“用于更改州公证人的流程。 这是必需的,因为事务的所有输入状态必须指向同一公证人。”

我想把它放在那里,以防万一您以为我是个更厉害的人!

执行公证变更交易的代码如下所示:

@Suspendable
private fun notaryChange(message: StateAndRef<MessageState>,notary: Party
): StateAndRef<MessageState> =if (message.state.notary != notary) {subFlow(NotaryChangeFlow(message,notary))} else {message}

我相信您可以弄清楚自己的状况,但是要使自己变得更加聪明……我将告诉您。 message表示输入状态, notary是新交易将使用的公证人。 如果公证人相同,则可以返回状态,因为无需对其进行任何操作。 如果确实不同,则调用NotaryChangeFlow ,它接受传递给原始函数的两个参数。 这将返回一个新的StateAndRef ,然后从函数中返回它。

然后可以将从此函数返回的StateAndRef放入事务中。

如果您不确定传递到事务中的状态是否来自同一公证人,那么建议您坚持使用本节中的代码。 选择事务将使用的公证人(无论是特定的公证人还是从输入状态中获取的公证人),然后对任何需要它的公证人进行变更。 例如,我认为类似于下面的代码将提供一个通用且健壮的解决方案:

@Suspendable
private fun transaction(): TransactionBuilder {val messages = getMessageStates()val notary = notary()return TransactionBuilder(notary).apply {messages.forEach {addInputState(notaryChange(it, notary))}addCommand(Delete(),(messages.flatMap { it.state.data.participants }.toSet() + ourIdentity).map(Party::owningKey))}
}@Suspendable
private fun notaryChange(message: StateAndRef<MessageState>,notary: Party
): StateAndRef<MessageState> =if (message.state.notary != notary) {subFlow(NotaryChangeFlow(message,notary))} else {message}// however you want to choose your specific Notary
private fun notary(): Party =serviceHub.networkMapCache.notaryIdentities.single { it.name.organisation == "Notary-1" }

在这里,为交易选择了一个特定的公证人,如果需要,每个输入的公证人都将更改为所选公证人,并且签名者包括消费状态的所有参与者。 这可能不适合您自己的用例。 很好。 但是,这在为不断变化的公证人服务时(主要是为了提高性能)应该是一个很好的起点。

稍稍更改此解决方案,我们可以改为根据输入状态参考的“公证人”来选择“公证人”。 由于只有notary功能确实需要更改,因此我从示例中排除了其余代码。

private fun notary(messages: List<StateAndRef<MessageState>>): Party =messages.map { it.state.notary }.groupingBy { it }.eachCount().maxBy { (_, size) -> size }?.key ?: throw IllegalStateException("No Notary found")

该功能选择的公证人是根据输入状态共享的最常见的公证人来决定的。 这样一来,所需的公证变更交易就更少了,因为绝大多数输入已经引用了所选的公证。 如果您不知道输入参考的是哪个公证人,这应该提供最佳性能。

结论

在Corda网络中实现高性能取决于消除系统中的瓶颈和其他常规性能调整。 公证人就是这样的瓶颈之一。 在通过公证人的吞吐量非常高的情况下,网络的性能将开始达到平稳状态。 公证人不能以传入的速率足够快地处理请求。移动使用共享请求负载的多个公证人将提高网络的性能。 这在确定使用哪个公证人方面带来了额外的复杂性,并且可能需要公证人变更事务。 但是,如果您的网络确实需要实现高吞吐量。 这将是一个值得研究的领域。

我将在这里发表最后的评论。 随着公证人内部性能的提高,对这种架构的需求将减少。 甚至有一个公证人能够完全处理大量传入请求的情况。 随着Corda不断提高整体性能,这是一个值得关注的领域。

这篇文章中使用的代码可以在我的GitHub上找到 。

翻译自: https://www.javacodegeeks.com/2018/11/increasing-network-multiple-notaries.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/344787.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

初识FPGA(搬运)

原文链接1原文链接2 fpga简介 FPGA&#xff08;Field&#xff0d;Programmable Gate Array&#xff09;&#xff0c; 即现场可编程门阵列&#xff0c;它是在PAL&#xff08;可编程阵列逻辑&#xff09;、GAL&#xff08;通用阵列逻辑器件&#xff09;、CPL&#xff08;复杂可…

蓝桥杯小白系列之汇编点亮led灯

蓝桥杯小白系列之汇编点亮led灯 1、源代码 2、逐条分析 (1)ORG 0000H (2)START: 伪指令,编译器可识别,单片机不可识别,可以随便起。 (3)蜂鸣器设置 蓝桥板插电以后蜂鸣器常会自动响起,故在程序前提前加上如下代码,让蜂鸣器不响: mov P2,#0A0H mov P0,#000H 参照…

带有Oracle Digital Assistant和Fn Project的会话式UI。 第二部分

在上一篇文章中&#xff0c;我使用Oracle Digital Assistant为FlexDeploy实现了一个对话式UI。 今天&#xff0c;我将用Fn Flow丰富它&#xff0c;以便聊天机器人接受发行名称而不是ID来创建快照。 完成后&#xff0c;对话听起来会更加自然&#xff1a; … “您可以建立快照吗…

小白系列之51单片机的入门速成法

51单片机的入门速成法 01-经典51内核资源全览浓缩图 02-重要外设特殊功能寄存器概览 03-程序开发流程与设计要点 04-三大外设的开发与可重用代码 05-应用程序设计入门一例通 01-经典51内核资源全览浓缩图 <1> 四组8位并行I/O端口&#xff1a; P0端口&#xff1a;PC门&a…

蓝桥杯基础模块1:LED跑马灯

一、模块题目 二、原理简述 1、74HC138:三八译码器(3个输入,8个输出) 2、74HC573:锁存器(20个引脚,D1D8是数据输入端,Q1Q8是数据输出端&#

如何使用Hibernate将PostgreSQL枚举映射到JPA实体属性

介绍 开源的hibernate-types项目允许您映射JSON&#xff0c;ARRAY&#xff0c; YearMonth &#xff0c; Month或数据库特定的列&#xff08;例如INET地址&#xff09;。 在本文中&#xff0c;我们将看到使用JPA和Hibernate时如何将PostgreSQL Enum类型映射到Java数组。 Maven…

蓝桥杯基础模块2:蜂鸣器继电器

一、模块题目 二、原理简述 1、74HC138(参见模块1) 2、74HC02(参见模块1) 3、74HC573(参见模块1)

蓝桥杯基础模块3_1:数码管静态显示

一、模块题目 二、原理简述 1、数码管 CT107D单片机综合实训平台上使用的数码管是F3461BH(倒数第二个字母是A则共阴,是B则共阳)。 F3461BH是一个4位8段的数码管,其中a、b、c、d、e、f、g、dp引脚分别对应8个段码,该8个引脚通过74HC573锁存器与单片机的P0端口相连。另外有…

蓝桥杯基础模块3_2:数码管动态显示

一、模块题目 二、原理简述 动态显示的基本原理与实现思路(转载) 动态显示实质上就是轮流点亮单个数码管实现多位数码管整体显示的效果。在轮流显示过程中,每位数码管点亮时间为1~2ms,由于人的视觉暂留现象及发光二极管的余辉效应,尽管实际上各位数码管并非同时点亮,但…

蓝桥杯基础模块4_1:独立按键

一、模块题目 二、原理简述 1、独立按键的处理思路(转载) 一般情况下,独立按键有两个引脚,其中一个通过上拉电阻接到单片机的I/O端口,另外一端接地。也就是说,平时按键没有动作的时候,输出的是高电平,如果有按下动作发生,则输出的是低电平。那么,我们在程序设计的时…

蓝桥杯基础模块4_3:矩阵按键

一、模块题目 二、原理简述 1、矩阵键盘的扫描思想(转载+删减) 与独立按键不同的是,按键的两个引脚都分别连接的单片机的I/O端口,一个作为行信号,另外一个作为列信号。下以4X4的矩阵键盘为例,探讨其工作方式和扫描思路。 要识别出黄色按键的按下状态,逐行扫描,然后读…

蓝桥杯基础模块5:外部中断

一、模块题目 二、原理简述 (转载,删改) 1、什么是中断 你正在追电视剧《神雕侠侣》,正看得入迷的时候,电话响了,你暂停电视剧,去接电话,在接电话的过程中,门铃又响了,你暂时放下电话,去把门打开。如果追电视剧是在执行主程序,那么电话就是中断源,电话铃响了就是中…

蓝桥杯基础模块06_1:定时器计数器

一、模块题目 二、原理简述 &#xff08;转载&#xff0c;删改&#xff09; 1、定时器、计数器定义 在没有钟表的时候&#xff0c;定时的方式通过有一注香的时间&#xff0c;或者一桶水的时间。前者烧香不断减少是减法&#xff0c;后者滴水不断增加是加法。 定时/计数器&#…

structure101_使用structure101分析软件包的依赖关系

structure101稳定应用程序的一个关键是结构良好的代码库。 我们知道我们应该建立尽可能多的黑匣子&#xff0c;因为一旦完成一个黑匣子&#xff0c;我们就不必再考虑其内部了。 您只需要使用您或其他团队成员通过明确定义的界面编写的代码即可。 这使您可以专注于要添加的下一个…

蓝桥杯基础模块6_2:定时器进阶

一、模块题目 二、原理图 1、数码管

蓝桥杯基础模块7:PWM脉宽调制

一、 模块题目 二、 原理简述 脉冲宽度调制是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。随着电子技术的发展,出现了多种脉冲宽度调制(Pulse width modulation,PWM)技术,其中包括:相电压控…

蓝桥杯基础模块8_1:串口通信收发

一、模块题目 二、原理简述 1、串口重要概念概述 <1> 串行通信是指数据一位接一位地顺序发送或接收。 <2> 串行通信有SPI、IIC、UART等多种,最常见最通用的是指UART,无特殊说明,本文指的就是UART。 <3> 串行通信的制式有:单工、半双工、全双工三种。 &l…

蓝桥杯基础模块8_2:串口进阶

一、模块题目 二、原理简述 串行接口作为51单片机的重要外设,编程操作并不复杂,但在实际的项目应用中,由于数据结构和通信规约的不同,其程序逻辑也有各种变化。 一般情况下,上位机的命令可能不是一个字节,而是多个字节组成的命令帧,有的长度固定,有的长度变化;而且要…

蓝桥杯基础模块9:IO口扩展与存储器映射

一、模块题目 二、原理简述 三、源码 (1)I0扩展 //头文件 #include "reg52.h" //延时函数 void Delay(unsigned int t) {