升级 Canton 节点
升级 Canton 参与方与同步器二进制及协议版本。
升级 Canton 参与者和同步器二进制文件;更改Canton协议版本。
本节介绍升级 Canton 参与者节点和同步器的过程。升级 Daml 应用程序已在其他地方介绍。
正如版本控制指南中所述,新功能、改进和修复会定期发布。为了从这些变化中受益,必须对广州的系统进行升级。
升级系统时需要解决两个关键方面:
- 升级用于运行节点的 Canton 二进制文件。
- 升级定义节点如何交互的协议版本。
Canton 是一个分布式系统,没有一个操作员控制所有节点。因此,我们必须支持节点单独升级的情况,提供一种安全的升级机制,需要网络内最少的同步操作。
Canton 二进制文件支持多个协议版本,新的协议版本以与新二进制文件向后兼容的方式引入(参见版本表)。因此,分布式 Canton 网络中使用的协议的任何升级都是通过单独升级所有二进制文件并随后将节点之间使用的协议版本更改为所需的版本来完成的。
以下是一般指南。在升级到特定版本之前,请检查每个版本的单独说明。
本指南还假设升级是次要版本或补丁版本。主要版本升级可能有所不同,如有必要,将单独进行介绍。
-
请在升级前备份您的数据。
请注意,备份的顺序很重要。
-
在尝试升级您的生产系统之前,请彻底测试您的升级。
-
迁移一旦开始,就无法中止或回滚。
如果遇到问题,必须使用备份恢复旧版本。
升级 Canton 二进制
一个 Canton 节点由一个或多个进程组成,其中每个进程定义为
- 运行 Canton 版本 JAR 的 Java 虚拟机应用程序。
- 一组描述正在运行的节点的配置文件。
- 通过
--bootstrap传递的可选引导脚本,在启动时运行。 - 一个数据库(具有特定的模式),保存节点的数据。
要升级节点,
- 替换 Canton 二进制文件(其中包含 Canton JAR)。
- 测试配置文件是否仍能被新进程解析。
- 测试您正在使用的引导脚本是否仍然有效。
- 升级数据库架构。
通常,对配置文件的所有更改都应向后兼容,因此不会受到升级过程的影响。在极少数情况下,可能需要对配置文件进行细微更改以支持升级过程。有时,修复重大错误可能需要对 API 进行微小的重大更改。粤文也是如此。
数据库中的模式使用 Flyway 进行版本控制和管理。 Canton 使用该库来检测和应用更改。了解这一背景有助于解决问题。
准备
首先,请下载您想要升级到的新 Canton 二进制文件,并将其存储在您计划测试升级过程的测试系统上。
然后,获取节点数据库的最新备份并将其部署到您方便的数据库服务器上,以便您可以在不影响生产系统的情况下测试升级过程。虽然我们自己对升级过程进行了广泛的测试,但我们不能排除您以非预期方式使用系统的可能性。测试很麻烦,但破坏生产系统更糟糕。
如果您要升级参与者,那么我们建议您还使用内存同步器,您可以在测试参与者的升级正常工作后将其拆除。您可以通过将一个简单的同步器定义作为配置混合添加到您的参与者配置中来实现这一点。
通常,如果您正在运行高可用性设置,请在执行升级之前使所有节点脱机。如果更新需要数据库迁移(请检查发行说明),请避免在复制的设置中运行较旧和较新的二进制文件,因为这两个二进制文件可能需要不同的数据库布局。您可以按任意顺序升级基于微服务的同步器的二进制文件,只要升级同时访问同一数据库的节点的二进制文件即可。例如,您可以在一个周末升级复制中介节点的二进制文件,并在另一个周末升级主动-主动数据库排序器。
备份您的数据库
在升级数据库和二进制文件之前,请确保您已备份数据,以便在出现问题时可以回滚到以前的版本。您可以通过克隆来备份数据。在 Postgres 中,命令是:
CREATE DATABASE newdb WITH TEMPLATE originaldb OWNER dbuser;
执行此操作时,您需要更改上述命令中的数据库名称和用户名以匹配您的设置。
测试你的配置
测试配置是否仍然有效
./bin/canton -v -c storage-for-upgrade-testing.conf -c mynode.conf --manual-start
在这里,需要调整文件storage-for-upgrade-testing.conf和mynode.conf以匹配您的情况。
如果 Canton 启动并显示控制台的命令提示符,则说明配置已成功解析。
命令行选项--manual-start阻止节点自动启动,因为我们首先需要迁移数据库。
迁移数据库
Canton 不会自动执行数据库迁移。必须强制迁移。如果启动需要数据库迁移的节点,您将观察到以下 Flyway 错误:
@ participant.start()
ERROR com.digitalasset.canton.integration.EnvironmentDefinition$$anon$3:UpgradingDocumentationIntegrationTest - failed to initialize participant: There are 5 pending migrations to get to database schema version 4.0. Currently on version 1.1. Please run `participant.db.migrate` to apply pending migrations
Command LocalParticipantReference.start invoked from cmd10000002.sc:1
数据库模式定义经过版本控制和哈希处理。此错误告诉我们当前数据库架构版本以及需要应用多少迁移。此检查在启动时运行,因此如果节点启动,则迁移成功。
我们现在可以使用以下命令强制迁移到新模式:
@ participant.db.migrate()
您还可以将迁移配置为自动应用。请注意,您需要确保节点用于访问数据库的用户帐户允许更改数据库架构。迁移需要多长时间取决于二进制文件的版本(请参阅迁移说明)、数据库的大小和数据库服务器的性能。
我们建议在启动节点之前清理数据库。在 Postgres 上,运行
VACUUM FULL;
否则,在数据库自我清理期间重新启动可能需要很长时间。
随后即可成功启动节点
@ participant.start()
请注意,对于所有其他类型的节点,该过程保持相同,此处以参与者节点为例。
测试您的升级
一旦您的节点启动并运行,您就可以通过运行 ping 来测试它。如果您正在测试参与者节点的升级,那么您可能需要连接到测试同步器
@ participant.同步器s.connect_local(sequencer1, "test同步器")
如果您对生产实例进行了实际升级,那么您只需在运行 ping 之前重新连接到当前同步器:
@ participant.同步器s.reconnect_all()
您可以使用以下命令检查同步器是否已启动并正在运行
@ participant.同步器s.list_connected()
res5: Seq[ListConnected同步器sResult] = Vector(
ListConnected同步器sResult(
同步器Alias = 同步器 'test同步器',
physical同步器Id = testdomain::1220f136debd...::34-0,
healthy = true
)
)
```最后,您可以 ping 参与者以查看系统是否正常运行
```none theme={"theme":{"light":"github-light","dark":"github-dark"}}
@ participant.health.ping(participant)
res6: Duration = 1404 milliseconds
ping 命令在管理方之间创建两个合同,然后执行并存档它们——提供账本功能的端到端测试。
版本特定注释
目前,什么也没有。
更改Canton协议版本
Canton 协议由节点相互通信所使用的语义和线路格式定义。为了处理交易,所有节点必须能够理解并使用相同的协议。
因此,只有在所有节点都升级到可以运行该版本的二进制文件后,才能引入新协议。
将同步器升级到新的协议版本
同步器与协议版本相关联。该协议版本在同步器初始化时配置,之后无法更改。因此,不能升级同步器的协议版本。相反,您可以将新的同步器与旧的同步器进程并排部署。
这适用于所有同步器服务,无论是排序器、中介器还是拓扑管理器。
请注意,目前,升级过程中无法保留同步器 ID。新同步器必须具有不同的同步器 ID,因为参与者将同步器连接与同步器 ID 关联起来,并且该关联必须是唯一的。
因此,协议升级过程归结为:
- 在旧同步器旁边部署一个新同步器。确保新同步器使用所需的协议版本。还要确保同步器服务(中介器、Sequencer节点和拓扑管理器)、通道名称、智能合约地址等使用不同的数据库(或至少同一数据库中的不同模式)。新的同步器必须完全独立,但只要使用不同的Sequencer合约地址或 Fabric 通道,就可以重用 DLT 后端。
- 指导使用硬同步器迁移的参与者单独使用新的同步器。
注意:要为旧同步器和新同步器使用具有不同模式的相同数据库,请在 JDBC URL 中设置 currentSchema 或设置为 storage.config.properties 中的参数。
硬同步器连接升级
可以使用相应的迁移命令执行硬同步器连接升级。再次,请确保您有适当的备份,并且在将其应用到生产系统之前已经测试了此过程。您必须使用特殊的配置开关来启用这些命令:
canton.features.enable-repair-commands=yes
假设您有多个参与者都连接到名为 old同步器 的同步器,请确保没有待处理的事务。您可以通过控制应用程序或将所有参与者的资源限制设置为 0 来做到这一点:
@ participant.resources.set_resource_limits(ResourceLimits(Some(0), Some(0)))
这将拒绝任何新命令并完成处理待处理的命令。一旦确定您的参与者节点空闲,请断开参与者节点与旧同步器的连接:
@ participant.同步器s.disconnect("old同步器")
通过检查活动连接列表来测试同步器是否已断开连接:
@ participant.同步器s.list_connected()
res3: Seq[ListConnected同步器sResult] = Vector()
现在是在继续之前执行数据库备份的好时机:
CREATE DATABASE newdb WITH TEMPLATE originaldb OWNER dbuser;
接下来,我们要运行迁移步骤。为此,我们需要运行repair.migrate_同步器命令。该命令需要两个输入参数:源同步器的别名和描述新同步器的同步器连接配置。
为了构建同步器连接配置,我们只需键入```scala theme={“theme”:{“light”:“github-light”,“dark”:“github-dark”}} @ val config = 同步器ConnectionConfig(“new同步器”, GrpcSequencerConnection.tryCreate(“https://127.0.0.1:5018”)) config : 同步器ConnectionConfig = 同步器ConnectionConfig( 同步器 = 同步器 ‘new同步器’, sequencerConnections = SequencerConnections( connections = Sequencer ‘DefaultSequencer’ -> GrpcSequencerConnection( sequencerAlias = Sequencer ‘DefaultSequencer’, ..
其中 URL 应指向正确的同步器。如果您使用名为 `new同步器` 的目标同步器在单个 Canton 进程中本地测试升级过程(这就是我们在本例中所做的),您可以使用以下命令获取连接详细信息
```none theme={"theme":{"light":"github-light","dark":"github-dark"}}
@ val config = 同步器ConnectionConfig("new同步器", SequencerConnections.single(sequencer3.sequencerConnection))
config : 同步器ConnectionConfig = 同步器ConnectionConfig(
同步器 = 同步器 'new同步器',
sequencerConnections = SequencerConnections(
connections = Sequencer 'DefaultSequencer' -> GrpcSequencerConnection(
sequencerAlias = Sequencer 'DefaultSequencer',
..
现在,使用此配置对象,我们可以使用以下命令触发硬同步器连接迁移
@ participant.repair.migrate_同步器("old同步器", config)
该命令将注册新的同步器,并将与 old同步器 绑定的合约重新关联到新的同步器。
一旦所有参与者都执行了迁移,他们就可以重新连接到同步器
@ participant.同步器s.reconnect_all()
现在,新的同步器应该已连接:
@ participant.同步器s.list_connected()
res8: Seq[ListConnected同步器sResult] = Vector(
ListConnected同步器sResult(
同步器Alias = 同步器 'new同步器',
physical同步器Id = newdomain::1220eecef286...::34-0,
healthy = true
)
)
由于我们之前将资源限制设置为 0,因此我们需要将其重置回来
@ participant.resources.set_resource_limits(ResourceLimits(None, None))
最后,我们可以通过在新同步器上运行 ping 来测试参与者是否可以处理事务
@ participant.health.ping(participant)
res10: Duration = 1256 milliseconds
<注意> 请注意,目前,硬迁移是唯一支持的生产系统迁移方式。这是因为唯一的合约密钥仅限于单个同步器。 </注>
虽然同步器迁移命令主要用于升级,但它也可用于恢复与损坏的同步器相关的合约。同步器迁移可以来回执行,允许您在出现问题时回滚。
升级后,参与者可能会在第一次承诺交换期间报告承诺之间不匹配,因为他们可能在略有不同的时间执行迁移。一旦所有参与者都备份并连接,警告最终应该停止。
预期表现
在性能方面,我们可以注意到以下几点:当我们迁移合约时,我们直接写入相应的事件日志。这意味着,在源同步器上,我们插入转出,同时将转入和合约写入目标同步器。写入此信息比任何类型的事务处理都要快得多(单个 CPU/16 核测试服务器上每秒数千次迁移)。然而,对于非常大的数据集,该过程仍然可能需要相当长的时间。因此,我们建议您在升级测试期间测量迁移所需的时间,以了解迁移所需的必要停机时间。
此外,重新连接后,参与者需要重新计算新的承诺集。对于大量合同,这可能需要一段时间。
软同步器连接升级> 目前仅支持软同步器连接升级作为 Alpha 功能。
硬同步器连接升级需要网络中所有参与者之间的协调。软同步器连接升级在操作上要简单得多,并且可以使用多同步器支持(目前仅作为 pre-alpha 功能存在)来利用。通过关闭非唯一合约密钥,参与者可以连接到多个同步器并在同步器之间传输合约。这使我们能够避免使用 repair.migrate_同步器 步骤。
假设与之前的设置相同,参与者连接到旧的同步器,我们可以将其连接到新的同步器
@ participant.同步器s.connect_local(sequencer3, "new同步器")
通过更改新同步器连接的 priority 标志,使新连接优先于旧连接:
@ participant.同步器s.modify("new同步器", _.copy(priority=10))
您可以使用以下命令检查同步器的优先级设置
@ participant.同步器s.list_registered().map { case (c, _, _) => (c.同步器Alias, c.priority) }
res3: Seq[(同步器Alias, Int)] = Vector((同步器 'new同步器', 10), (同步器 'old同步器', 0))
现有合约不会自动转移到新的同步器。同步器路由器将通过最小化传输数量和优先级来选择同步器。因此,大多数合约将保留在旧同步器上,无需额外操作。然而,通过使用
,合约可以一一移动到新的同步器,这样最终所有合约都与新的同步器关联,从而允许旧的同步器退役并关闭。
软升级路径提供了流畅的用户体验,不需要在所有参与者之间协调同步器连接的硬迁移。相反,参与者只要准备好就可以单独升级,这样他们就可以在需要时逆转该过程。
本文由 CC Privacy Club 根据 Canton Network 官方文档(CC-BY-4.0)整理翻译,仅供学习;实现细节以官方最新版本为准。