This saga implementation is basis for the specification fitting to schema of Eclipse MicroProfile. See at https://github.com/eclipse/microprofile-sandbox/tree/master/proposals/0009-LRA.
The communication is done over HTTP in way of REST principles.
The Java EE technologies which the LRA builds upon are CDI and JAX-RS.
Saga - what we are talking about
Before we start talking about LRA let's introduce the term saga.Saga consists from independent set of operations which all together forms one atomic action. The operation can be whatever action you think.
Here we took take the well known example of booking a flight and subsequent services. The operations are booking flight, taxi and hotel and these three forms the atomic action which we want all parts would be processed together.
NOTE: From ACID point of view the Saga transaction relaxes the I (isolation) and because of that gets availability and is representation of BASE principle, see http://queue.acm.org/detail.cfm?id=1394128.
Principle of saga requires existence of a compensations actions invoked in case of failure.
The compensation actions undo work done by the "business" operations. The sequence in case of the flight example is first to book flight. If that success this change is overly visible to all the other parties trying to book the flight too (here it's the relaxation of ACID isolation).
Next is the taxi booking, followed by hotel booking. When there is no hotel available in the area for the particular date the whole saga fails and compensation action for the prior actions are invoked. The responsibility of the compensation action is undoing what was done - in this case canceling flight and taxi booking. How this is exactly done depends on the business logic. It could be updating of some database record, call to some API or sending email to the taxi operator.
In comparison to ACID transaction, where developer makes a SQL insertion to database or sends a message to a broker and the potential undoing such action (rollback) is handled by the transaction manager in the background, here in Saga world the responsibility of undoings completely moved to the developer who has to implement the compensations callback.
Responsibility of the transaction manager is to gather information about what operations are part of particular saga (receives participant enlistment) and ensuring the compensation callback is invoked, even in case of failure (either the participant or the manager itself).
The Narayana LRA implementation also adds way to define a complete callback which is invoked when saga ends successfully. This could be used for confirmation actions e.g. customer could be informed with email that order was processed while passing him details needed for the payment. Or database can be enriched with column informing if order was successfully processed and SQL statements could be created with that taken into account.
In summary using saga transactions is a design pattern which needs to be built to the foundation of the application architecture.
LRA - Long Running Actions
The Narayana LRA is implementation of saga for HTTP transport based on the REST principles.Narayana LRA is represented by coordinator (transaction manager) exposing HTTP endpoint for an incoming remote communication. The coordinator is the core which ensures the LRA saga is processed in atomically. Services enlist to the coordinator, by calling defined REST endpoints. The coordinator calls then back services to confirm saga success or command to undone with compensate.
The coordinator can be placed as separate service or it can be attached to the application too.
For Narayana implementation applies that in case of coordinator packed with the application, the application itself talks to coordinator with in-memory calls.
Let's explain how the LRA communication works on the example. This is diagram showing our usecase.
We can see the LRA coordinator and 4 services talking to each other in the row synchronously (of course your application can be designed in a different way) and communication will looks in following way
- A client makes a call to the first service (Microservice #1)
- The Microservice #1 is responsible for starting LRA (creating the saga). It calls LRA coordinator to endpoint starting LRA. The coordinator announces lra identifier in response.
- The Microservice #1 enlists itself with the created LRA by calling coordinator along with the particular LRA identifier and handing over addresses of REST endpoints for compensation (optionally completion) callbacks. Those are endpoint the coordinator can call back to Microservice #1.
- The Microservice #1 takes the LRA identifier and adds it as an HTTP header (long-running-action) to the REST call to the next service - Microservice #2. If the Microservice #2 distinguishes the LRA header it can enlist itself (by announcing REST endpoints for compensation/completion callbacks) to coordinator.
- On way back the first service is responsible for finishing saga by calling close (when finishing with success) on the LRA coordinator with the saga identifier.
- Some of the other services could fail saga by calling cancel on the LRA coordinator, in which case the close won't succeeds and reports back an error.
Code examples
If you wan to see this example working check out the Red Hat MSA exampleenriched with the LRA capabilities.
Detailed installation steps could be found at the page: https://developer.jboss.org/wiki/MSAQuickstartsWithLRAREST-ATOnMinishift
In the next article we will get into CDI annotations used by LRA and their functionality. Meanwhile you can check out how the WildFly Swarm microservice using LRA described in the example looks like
https://github.com/ochaloup/hola/blob/lra/src/main/java/com/redhat/developers/msa/hola/HolaResource.java#L81
or check other implementations run with Spring, Vert.x and Node.js
12 comments:
Hi!
Could you please clarify how the LRA coordinator manages the SAGAs Log (state)? It uses the same object store used by JTA/JTS in narayana?
Another question is about how can I register/enlist an external service not owned by me in the LRA Coordinator service? (eg. a public remote service API from Google or any other api/service provider)
The Narayana implementation of LRA builds on the same foundation (ArjunaCore) as our other transaction related projects so it does indeed use the same transaction log storage mechanism. Whenever the state of an LRA changes, the new state is made persistent (via the Narayana transaction object store). The store location is configurable via properties (see the Narayana Project Documentation). We have various storage options such as the file system, artemis journal, or a database.
There are two ways to register a service for LRA completion/cancellation notifications:
- create a JAX-RS resource that contains specific Java annotations defined in the MicroProfile LRA specification (minimally @LRA and @Compensate).
- issue an HTTP request to our proprietary LRA coordinator and include endpoints that should be called when the LRA later cancels or closes (you will also need to include the id of the LRA).
So if the external service is not under your control you would need to create a proxy that does know how to enlist with an LRA. If your proxy is asked to compensate then you would need to call the relevant logic in the external service (that executes the appropriate compensation behaviour).
Hi,
I saw, that you have intensive development of the LRA project at GitHub following the current state of the Microprofile LRA.
My question here is when and where you will post documentation about your implementation?
Best Regards,
Mihail
Hi Михаил Мерков,
we are working on finishing the LRA 1.0 spec (https://github.com/eclipse/microprofile-lra/milestone/1) and to align the Narayana implementation (https://github.com/jbosstm/narayana/tree/master/rts/lra) with it.
The Narayana LRA implementation tracks the progress as issues under RedHat Jira issue of project JBTM - see here https://issues.redhat.com/browse/JBTM-3294?jql=project%20%3D%20JBTM%20AND%20resolution%20%3D%20Unresolved%20AND%20component%20%3D%20LRA%20ORDER%20BY%20priority%20DESC. There are few blockers and critical issues which needed to be addressed.
There are not many issues to be finished so we hope this all will be covered soon. Regarding documentation - we've been discussing this on the google forum (https://groups.google.com/g/narayana-users/c/Lmsxt-nGDUk/m/faNbVo8oAgAJ). The current status is that the Narayana documentation will be updated following the LRA 1.0 release.
The LRA specification and Narayana are both open-source projects and the contribution is more than welcomed. That will speed things along.
Kind regards, Ondra
Do we have support for LRA Narayana deployment on AWS EKS? As I need to implement it our environment and we use AWS EKS only, no physical servers or VMs. Please share the manual/guide on how to deploy Narayana LRA coordinator in AWS EKS region.
Hi DeepRaj, Narayana LRA is shipped as part of the WildFly 28 application server (see https://www.wildfly.org/news/2023/04/20/WildFly28-Released/) and Quarkus (see https://quarkus.io/guides/lra).
I would suggest you to ask WildFly (https://wildfly.zulipchat.com/) about if they have any plans to support AWS EKS.
Kind regards, Marco
Thanks Marco for the reply.
So here is little more information about how I am going to use it.
Use Case: We have distributed microservices which are part of same namespace in AWS EKS. We need to execute Saga transactions using these microservices. Saga Orchestrator we are planning to use. Apache camel based DSL we will be using to create our orchestrator class which will take care of Saga transaction then across multiple microservices of ours. So Can I use Wildfly 28 (which includes Narayana LRA) for my use case. AWS EKS support I'll check with Wildfly team then.
Do you have any sample reference code where you are using the Narayana LRA in Saga Orchestrator? Please share github link or wherever you have the complete code (Saga orchestrator using Narayana LRA).
I need to have the .war file of micorprofile-lra. but I am not able to find the running code to create the microprofile-lara.war, I found link in github (https://github.com/eclipse/microprofile-lra) but this code fails during "mvn clean install" command to build the war file. could someone please help?
Sorry we missed this question. We don't provide the war as a maven artifact so you will need to build it:
# Build the LRA war
git clone https://github.com/jbosstm/narayana
cd narayana
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-17.0.11.0.9-1.fc40.x86_64 # or use jdk 11
./build.sh clean install -Prelease,community -DskipTests
cp rts/lra/coordinator-war/target/lra-coordinator.war
# start the application server
# test the endpoint by asking the LRA coordinator to list running LRAs:
curl http://localhost:8080/lra-coordinator/lra-coordinator
# create a new LRA
curl -XPOST http://localhost:8080/lra-coordinator/lra-coordinator/start
etc
If you want alternatives to war files then there are other ways to run a coordinator such as https://github.com/jbosstm/lra-coordinator-quarkus which creates a runnable jar and docker container and native executable that you can probably deploy to AWS EKS and there are various blogs that indicate how to build your own coordinator (such as https://jbossts.blogspot.com/2021/07/how-to-use-long-running-actions-between.html and https://quarkus.io/blog/using-lra/ and plenty of others).
Post a Comment