转载

GitHub - berndruecker/trip-booking-saga-java:使用轻量级开源工作流引擎(Camunda) 实现Saga模式...

Saga模式描述了如何在没有两阶段提交的情况下解决分布式(业务)事务,因为这不能在分布式系统中扩展。基本思路是将整个交易分解为多个步骤或活动。只有内部的步骤可以在原子事务中执行,但整体的一致性由Saga处理。Saga有责任完成整个业务交易或使系统处于已知的终止状态。因此,如果出现错误,则应用业务回滚过程,该过程通过以相反顺序调用补偿步骤或活动来实现。可以更详细地了解Sagas :如何在没有两阶段提交的情况下实现复杂的业务交易

在该Github示例的酒店案例中(点击标题),汽车和航班预订可能由不同的远程服务完成。所以没有技术事务,而只有商业事务。如果无法成功进行航班预订,您需要取消酒店和汽车。

GitHub - berndruecker/trip-booking-saga-java:使用轻量级开源工作流引擎(Camunda) 实现Saga模式...

使用 Camunda, 您可以使用图形建模或称为Model-API的Java DSL来实现Saga。由于Camunda非常轻量级,您可以启动所谓的流程引擎,定义Saga并通过几行Java代码运行实例(如果使用默认配置和内存中的H2数据库),请参阅 TripBookingSaga.java :

<b>public</b> <b>class</b> TripBookingSaga {

  <b>public</b> <b>static</b> <b>void</b> main(String args) {
    <font><i>// Configure and startup (in memory) engine</i></font><font>
    ProcessEngine camunda = 
        <b>new</b> StandaloneInMemProcessEngineConfiguration()
          .buildProcessEngine();
    
    </font><font><i>// define saga as BPMN process</i></font><font>
    ProcessBuilder saga = Bpmn.createExecutableProcess(</font><font>"trip"</font><font>);
    
    </font><font><i>// - flow of activities and compensating actions</i></font><font>
    saga.startEvent()
        .serviceTask(</font><font>"car"</font><font>).name(</font><font>"Reserve car"</font><font>).camundaClass(ReserveCarAdapter.<b>class</b>)
          .boundaryEvent().compensateEventDefinition().compensateEventDefinitionDone()
          .compensationStart().serviceTask(</font><font>"car-compensate"</font><font>).name(</font><font>"Cancel car"</font><font>).camundaClass(CancelCarAdapter.<b>class</b>).compensationDone()
        .serviceTask(</font><font>"hotel"</font><font>).name(</font><font>"Book hotel"</font><font>).camundaClass(BookHotelAdapter.<b>class</b>)
          .boundaryEvent().compensateEventDefinition().compensateEventDefinitionDone()
          .compensationStart().serviceTask(</font><font>"hotel-compensate"</font><font>).name(</font><font>"Hotel car"</font><font>).camundaClass(CancelCarAdapter.<b>class</b>).compensationDone()
        .serviceTask(</font><font>"flight"</font><font>).name(</font><font>"Book flight"</font><font>).camundaClass(BookFlightAdapter.<b>class</b>)
          .boundaryEvent().compensateEventDefinition().compensateEventDefinitionDone()
          .compensationStart().serviceTask(</font><font>"flight-compensate"</font><font>).name(</font><font>"Cancel flight"</font><font>).camundaClass(CancelCarAdapter.<b>class</b>).compensationDone()
        .endEvent();
    
    </font><font><i>// - trigger compensation in case of any exception (other triggers are possible)</i></font><font>
    saga.eventSubProcess()
        .startEvent().error(</font><font>"java.lang.Throwable"</font><font>)
        .intermediateThrowEvent().compensateEventDefinition().compensateEventDefinitionDone()
        .endEvent();     

    </font><font><i>// finish Saga and deploy it to Camunda</i></font><font>
    camunda.getRepositoryService().createDeployment() </font><font><i>//</i></font><font>
        .addModelInstance(</font><font>"trip.bpmn"</font><font>, saga.done()) </font><font><i>//</i></font><font>
        .deploy();
    
    </font><font><i>// now we can start running instances of our saga - its state will be persisted</i></font><font>
    camunda.getRuntimeService().startProcessInstanceByKey(</font><font>"trip"</font><font>, Variables.putValue(</font><font>"name"</font><font>, </font><font>"trip1"</font><font>));
    camunda.getRuntimeService().startProcessInstanceByKey(</font><font>"trip"</font><font>, Variables.putValue(</font><font>"name"</font><font>, </font><font>"trip2"</font><font>));
  }

}
</font>

真正业务逻辑在适配器类,如 BookHotelAdapter .

上述定义可能看起来有点冗长,因为您必须使用BPMN术语。但是你可以编写一个瘦的 SagaBuilder 来提高Saga定义的可读性:

SagaBuilder saga = SagaBuilder.newSaga(<font>"trip"</font><font>)
        .activity(</font><font>"Reserve car"</font><font>, ReserveCarAdapter.<b>class</b>) 
        .compensationActivity(</font><font>"Cancel car"</font><font>, CancelCarAdapter.<b>class</b>) 
        .activity(</font><font>"Book hotel"</font><font>, BookHotelAdapter.<b>class</b>) 
        .compensationActivity(</font><font>"Cancel hotel"</font><font>, CancelHotelAdapter.<b>class</b>) 
        .activity(</font><font>"Book flight"</font><font>, BookFlightAdapter.<b>class</b>) 
        .compensationActivity(</font><font>"Cancel flight"</font><font>, CancelFlightAdapter.<b>class</b>) 
        .end()
        .triggerCompensationOnAnyError();

camunda.getRepositoryService().createDeployment() 
        .addModelInstance(saga.getModel()) 
        .deploy();
</font>

引擎将负责状态处理,补偿,还可以处理超时和升级。

在现实场景中,您可以以不同方式配置和运行Camunda引擎,例如使用Spring或Spring Boot。在这个例子中,您还可以使用 Spring Boot应用程序 来 启动应用 程序 - 之后甚至可以连接Camundas可视化工具。

GitHub - berndruecker/trip-booking-saga-java:使用轻量级开源工作流引擎(Camunda) 实现Saga模式...

原文  https://www.jdon.com/52866
正文到此结束
Loading...