Oracle Blockchain Platform in globale verteilte Transaktionen aufnehmen

Möglicherweise muss Ihre Anwendung Aktualisierungen im gesamten Oracle Blockchain Platform-Ledger und anderen Repositorys wie Datenbanken oder anderen Blockchain-Ledgern atomar vornehmen, wobei entweder alle Aktualisierungen erfolgreich sind oder keine durchgeführt werden.

Um atomare Updates über mehrere Datenbanken hinweg zu ermöglichen, verwenden Entwickler globale Transaktionen, die von verteilten Transaktionskoordinatoren koordiniert werden, wie Oracle WebLogic Server, Oracle Tuxedo, Oracle Transaction Manager for Microservices, JBoss Enterprise Application Platform, IBM WebSphere und anderen Systemen. Alle diese Systeme basieren auf dem X/Open XA-Protokoll, um einen Zwei-Phasen-Commit-Prozess zu orchestrieren, indem sie Standard-APIs verwenden, die von XA Resource Managers (RMs) für jede Datenbank oder andere Ressource bereitgestellt werden. Oracle Blockchain Platform unterstützt Two-Phase Commits und stellt eine eigene XA RM-Bibliothek bereit, mit der externe Transaktionskoordinatoren XA-konforme APIs aufrufen können. Diese globalen Transaktionen können auch eine einzelne Nicht-XA-Ressource (z.B. ein Nicht-Oracle-Blockchain-Ledger oder eine nicht-XA-konforme Datenbank) umfassen, indem eine letzte Ressourcen-Commit-Optimierung verwendet wird.

Die XA-Spezifikation ist Teil der X/Open Distributed Transaction Processing-Architektur, die eine Standardarchitektur definiert, mit der mehrere Anwendungsprogramme Ressourcen gemeinsam nutzen können, die von mehreren Ressourcenmanagern bereitgestellt werden. Das Java XA-Interface selbst wird als Teil der Java-Plattform definiert. Weitere Informationen zur Java-XA-Schnittstelle finden Sie unter Schnittstelle XAResource in der Java-Dokumentation.

Oracle Blockchain Platform stellt eine Library bereit, die der XA-Spezifikation entspricht und die Java-Standardschnittstelle für einen XA-Ressourcenmanager implementiert. Mit der Bibliothek kann ein clientseitiger Transaktionsmanager globale Transaktionen koordinieren. Eine globale Transaktion ist eine einzige Arbeitseinheit, die Vorgänge wie Datenbankaktualisierungen und Blockchain-Transaktionen umfassen kann, die alle atomar festgeschrieben werden müssen. Mit anderen Worten, alle Vorgänge müssen erfolgreich durchgeführt werden. Wenn ein Vorgang, der Teil der globalen Transaktion ist, nicht erfolgreich verläuft, werden alle Vorgänge zurückgesetzt. Die XA-Schnittstelle basiert auf dem Zwei-Phasen-Commit-Protokoll, ähnlich dem Protokoll, das von den REST-Endpunkten für atomare Transaktionen unterstützt wird. Weitere Informationen zu atomaren Transaktionen in Oracle Blockchain Platform finden Sie unter Atomische Updates über Chaincodes und Kanäle hinweg durchführen.

Die XA-Implementierung für Oracle Blockchain Platform wird als Java-Library bereitgestellt und kann über die Registerkarte Entwicklertools im Bereich Anwendungsentwicklung der Oracle Blockchain Platform-Konsole heruntergeladen werden.

Vollständige Details zur Bibliothek sind in den Javadoc-Informationen enthalten, die in der herunterladbaren Datei enthalten sind. Die drei von der Bibliothek unterstützten Schlüsselobjekte sind OBPXAResource, OBPXADataSource und OBPXAConnection.
Objekt Zweck
OBPXAResource In dieser Klasse werden die erforderlichen APIs für einen Transaktionsmanager implementiert, um Oracle Blockchain Platform als Ressourcenmanager für XA-Transaktionen zu koordinieren.
OBPXADataSource Mit diesem Objekt können Sie eine Instanz der OBPXAConnection abrufen und die Authentifizierungs- und Autorisierungszugangsdaten angeben.
OBPXAConnection Mit diesem Objekt können Sie eine Instanz des Objekts OBPXAResource abrufen und die Blockchain-Transaktionen definieren, die als Teil einer XA-Transaktion ausgeführt werden sollen.

Um die XA-Bibliothek mit Oracle Blockchain Platform zu verwenden, muss die Anwendung Zugangsdaten für die Authentifizierung und Autorisierung der angeforderten Vorgänge bereitstellen. Die Bibliothek unterstützt sowohl die Basisauthentifizierung (Benutzer/Kennwort) als auch die Zugriffstoken OAuth 2.0, die Sie beim Erstellen der Instanz OBPXADataSource konfigurieren können. Die beiden Authentifizierungsmethoden sind mit den Authentifizierungsmethoden konsistent, die Sie mit dem Oracle Blockchain Platform-REST-Proxy verwenden. Sie können die Basisauthentifizierung zu Test- und internen Entwicklungszwecken verwenden. Verwenden Sie keine Basisauthentifizierung in Produktionsumgebungen. Weitere Informationen finden Sie unter Authentifizierung in der REST-API-Dokumentation.

Nachdem Sie eine OBPXADataSource-Instanz erstellt haben, können Sie die xaConnection-Instanz mit der Methode obpxaDataSource.getXAConnection() abrufen. Um die Authentifizierung bei Verwendung von OAuth 2.0-Zugriffstoken zu aktualisieren, können Sie die Methode getXAConnection verwenden, wie im folgenden Code gezeigt:
OBPXAConnection xaConnection = obpxaDataSource.getXAConnection(accessToken);      // get an XA connection using an OAuth 2.0 access token
Sie können auch die Methode getXAConnection verwenden, um die Basisauthentifizierung zu aktualisieren.
OBPXAConnection xaConnection = obpxaDataSource.getXAConnection(user, password);   // get an XA connection using username and password for basic authentication
Um eine Blockchain-Transaktion zu definieren, die als Teil einer globalen XA-Transaktion ausgeführt werden soll, verwenden Sie die folgende Methode:
public void createXAInvokeTransaction​(Xid xid, OBPXAInvokeTxRequest invokeTxRequest)
Bei dieser Methode ist xid eine globale Transaktions-ID, und invokeTxRequest ist die Blockchain-Transaktion, die als Teil der globalen XA-Transaktion ausgeführt werden soll. Um eine XA-Aufruftransaktionsanforderung zu erstellen, verwenden Sie die folgende Konstruktormethode:
OBPXAInvokeTxRequest invokeTxRequest = new OBPXAInvokeTxRequest(channel, chaincode, args);
In dieser Konstruktormethode ist channel der Kanal, in dem die Blockchain-Transaktion ausgeführt wird, chaincode der zu verwendende Chaincode und args die Chaincode-Funktion und alle für die Transaktion zu verwendenden Argumente.

Das folgende Code-Snippet veranschaulicht das Erstellen eines OBPXADataSource-Objekts, das Abrufen der OBPXAConnection-Instanz, das Erstellen der Transaktionsanforderung und das Aufrufen der createXAInvokeTransaction-Methode.

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);

Szenario: XA-Transaktionen anhand von Beispielen untersuchen

Das folgende Szenario ähnelt dem für atomare Transaktionen beschriebenen Szenario: Szenario: Atomic Transactions Using Samples, das die in Oracle Blockchain Platform enthaltenen Samples für Balance Transfer und Marbles verwendet.

In diesem Szenario installieren Sie die Balance Transfer- und Marbles-Beispiele auf zwei verschiedenen Instanzen von Oracle Blockchain Platform. Jede Instanz entspricht dann einer XA-Datenquelle:

  • XA-Ressource OBP-1, wobei der Marbles-Chaincode im Kanal goods installiert ist
  • XA-Ressource OBP-2, wobei der Saldentransfer-Chaincode im Kanal wallet installiert ist

In diesem Szenario können Sie eine XA-Transaktion verwenden, die mehrere Datenquellen umfasst, um sicherzustellen, dass der Austausch von Geldern und der Marmortransfer auf atomare Weise erfolgt, wobei entweder alle Vorgänge erfolgreich sind oder keine erfolgreich sind. Der folgende Code veranschaulicht dieses Szenario:

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