在全球分布式事务处理中包括 Oracle Blockchain Platform

您的应用可能需要以原子方式对 Oracle Blockchain Platform 分类账和其他存储库(例如数据库或其他区块链分类账)进行更新,其中所有更新都会成功,也可能不会成功。

为了跨多个数据库启用原子更新,开发人员使用由分布式事务协调器(例如 Oracle WebLogic Server、Oracle Tuxedo、Oracle Transaction Manager for Microservices、JBoss Enterprise Application Platform、IBM WebSphere 和其他系统)协调的全局事务。所有这些系统都依赖于 X/Open XA 协议,通过使用 XA 资源管理器 (RM) 为每个数据库或其他资源提供的标准 API 来编排两阶段提交过程。Oracle Blockchain Platform 支持两阶段提交,并提供自己的 XA RM 库,外部事务处理协调程序可以使用该库调用符合 XA 标准的 API。这些全局事务处理还可以使用上次的资源提交优化来包含单个非 XA 资源(例如,非 Oracle 区块链分类账或非 XA 合规数据库)。

XA 规范是 X/Open Distributed Transaction Processing 体系结构的一部分,该体系结构定义了一个标准体系结构,允许多个应用程序共享多个资源管理器提供的资源。Java XA 接口本身被定义为 Java 平台的一部分。有关 Java XA 接口的更多信息,请参见 Java 文档中的 Interface XAResource

Oracle Blockchain Platform 提供了一个符合 XA 规范的库,并为 XA 资源管理器实施了标准 Java 接口。该库使客户端事务管理器能够协调全局事务。全局事务是单个工作单元,其中可能包括数据库更新和区块链事务等操作,所有这些操作都必须以原子方式提交。换言之,所有操作都必须成功提交。如果全局事务处理中的任何操作失败,则将回退所有操作。XA 接口依赖于两阶段提交协议,类似于原子事务处理 REST 端点支持的协议。有关 Oracle Blockchain Platform 中的原子事务处理的更多信息,请参见 Make Atomic Updates Across Chaincodes and Channels

Oracle Blockchain Platform 的 XA 实施以 Java 库形式提供,可从 Oracle Blockchain Platform 控制台的 Application Development 窗格上的 Developer Tools 选项卡下载。

可下载文件中提供的 Javadoc 信息中包括有关磁带库的完整详细信息。库支持的三个关键对象是 OBPXAResourceOBPXADataSourceOBPXAConnection
对象 用途
OBPXAResource 此类实施所需的 API,以便事务处理管理器与 Oracle Blockchain Platform 作为 XA 事务处理的资源管理器进行协调。
OBPXADataSource 使用此对象可获取 OBPXAConnection 的实例并指定验证和授权身份证明。
OBPXAConnection 使用此对象获取 OBPXAResource 对象的实例,并定义要在 XA 事务处理中运行的区块链事务处理。

要将 XA 库与 Oracle Blockchain Platform 一起使用,应用程序必须提供用于验证和授权所请求操作的凭证。该库同时支持基本验证(用户/密码)和 OAuth 2.0 访问令牌,您可以在创建 OBPXADataSource 实例时对其进行配置。这两种验证方法与您用于 Oracle Blockchain Platform REST 代理的验证方法一致。您可以使用基本验证进行测试和内部开发。请勿在生产环境中使用基本验证。有关详细信息,请参阅 REST API 文档中的身份验证

创建 OBPXADataSource 实例后,可以使用 obpxaDataSource.getXAConnection() 方法获取 xaConnection 实例。要在使用 OAuth 2.0 访问令牌时更新验证,可以使用 getXAConnection 方法,如以下代码中所示:
OBPXAConnection xaConnection = obpxaDataSource.getXAConnection(accessToken);      // get an XA connection using an OAuth 2.0 access token
还可以使用 getXAConnection 方法更新基本验证。
OBPXAConnection xaConnection = obpxaDataSource.getXAConnection(user, password);   // get an XA connection using username and password for basic authentication
要定义要在全局 XA 事务处理中运行的区块链事务处理,请使用以下方法:
public void createXAInvokeTransaction​(Xid xid, OBPXAInvokeTxRequest invokeTxRequest)
在此方法中,xid 是全局事务标识符,invokeTxRequest 是作为全局 XA 事务的一部分运行的区块链事务。要创建 XA 调用事务处理请求,请使用以下构造器方法:
OBPXAInvokeTxRequest invokeTxRequest = new OBPXAInvokeTxRequest(channel, chaincode, args);
在此构造器方法中,channel 是将运行区块链事务处理的通道,chaincode 是要使用的链代码,args 包括链代码函数和要用于事务处理的任何参数。

以下代码段演示如何创建 OBPXADataSource 对象、获取 OBPXAConnection 实例,然后创建事务处理请求并调用 createXAInvokeTransaction 方法。

OBPXADataSource obpxaDataSource = OBPXADataSource.builder()
                        .withHost(host)
                        .withPort(port)
                        .withBasicAuth(username, password)
                        .withRole(role)
                        .build();
.
.
.
OBPXAConnection obpxaConnection = obpxaDataSource.getXAConnection();

OBPXAInvokeTxRequest invokeTxRequest = new OBPXAInvokeTxRequest(channel, chaincode, args);
invokeTxRequest.setEndorsers(endorsersArray); // optional blockchain transaction request attributes
invokeTxRequest.setTransientMap(transientMap); // optional blockchain transaction request attributes
invokeTxRequest.setTimeout(60000); // optional blockchain transaction request attributes

obpxaConnection.createXAInvokeTransaction​(xid, invokeTxRequest);

方案:使用样品浏览 XA 事务处理

以下方案与针对原子事务处理描述的方案类似:方案:使用示例浏览原子事务处理,该方案使用 Oracle Blockchain Platform 附带的余额转移和大理石示例。

在此方案中,您可以在 Oracle Blockchain Platform 的两个不同实例上安装余额转移和大理石示例。然后,每个实例都对应于一个 XA 数据源:

  • XA 资源 OBP-1, goods 通道上安装了 Marbles 链代码
  • XA 资源 OBP-2,在 wallet 通道上安装了余额转账链代码

在这种情况下,您可以使用跨多个数据源的 XA 事务处理来确保以原子方式进行资金交换和大理石传输,其中所有操作都成功或均未成功。以下代码说明此方案:

OBPXADataSource obpxaDS1 = ... // create an XA data source, supplying details about the OBP-1 instance
OBPXADataSource obpxaDS2 = ... // create an XA data source, supplying details about the OBP-2 instance

// start a global transaction in the client application
// invoke marble transfer on OBP-1
OBPXAConnection obpxaConn1 = (OBPXAConnection) obpxaDS1.getXAConnection();
OBPXAInvokeTxRequest invokeMarbleTransferReq = new OBPXAInvokeTxRequest("goods", "obcs-marbles", new String[]{"transferMarble", "marble1", "tom"});
obpxaConn1.createXAInvokeTransaction​(xid1, invokeMarbleTransferReq);
.
.
.
// invoke fund transfer on OBP-2
OBPXAConnection obpxaConn2 = (OBPXAConnection) obpxaDS2.getXAConnection();
OBPXAInvokeTxRequest invokeBalanceTransferReq = new OBPXAInvokeTxRequest("wallet", "obcs-example02", new String[]{"invoke", "a", "b", "50"});
obpxaConn2.createXAInvokeTransaction​(xid2, invokeBalanceTransferReq);
.
.
.
// end the global transaction in the client application