From 25fd4b866f8969bd55b8d922b2476a1234902852 Mon Sep 17 00:00:00 2001 From: ruishansun Date: Sat, 2 Jul 2022 18:33:22 +0800 Subject: [PATCH 1/4] add saga annotation samples --- pom.xml | 2 +- saga/local-saga-annotation-sample/README.MD | 54 +++++++++ saga/local-saga-annotation-sample/pom.xml | 39 +++++++ .../seata/samples/saga/ApplicationKeeper.java | 78 +++++++++++++ .../samples/saga/action/BalanceAction.java | 50 +++++++++ .../samples/saga/action/InventoryAction.java | 42 +++++++ .../samples/saga/action/ResultHolder.java | 72 ++++++++++++ .../saga/action/impl/BalanceActionImpl.java | 55 +++++++++ .../saga/action/impl/InventoryActionImpl.java | 25 +++++ .../SagaAnnotationTransactionService.java | 102 +++++++++++++++++ .../starter/LocalSagaTransactionStarter.java | 105 ++++++++++++++++++ .../src/main/resources/file.conf | 66 +++++++++++ .../src/main/resources/registry.conf | 79 +++++++++++++ .../src/main/resources/spring/seata-saga.xml | 36 ++++++ saga/pom.xml | 1 + tcc/sofarpc-tcc-sample/pom.xml | 6 +- tcc/springboot-tcc-sample/pom.xml | 6 +- 17 files changed, 811 insertions(+), 7 deletions(-) create mode 100644 saga/local-saga-annotation-sample/README.MD create mode 100644 saga/local-saga-annotation-sample/pom.xml create mode 100644 saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/ApplicationKeeper.java create mode 100644 saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/BalanceAction.java create mode 100644 saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/InventoryAction.java create mode 100644 saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/ResultHolder.java create mode 100644 saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/impl/BalanceActionImpl.java create mode 100644 saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/impl/InventoryActionImpl.java create mode 100644 saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/service/SagaAnnotationTransactionService.java create mode 100644 saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/starter/LocalSagaTransactionStarter.java create mode 100644 saga/local-saga-annotation-sample/src/main/resources/file.conf create mode 100644 saga/local-saga-annotation-sample/src/main/resources/registry.conf create mode 100644 saga/local-saga-annotation-sample/src/main/resources/spring/seata-saga.xml diff --git a/pom.xml b/pom.xml index 90d203fb9..3dbe1844b 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ 1.1.0 seata-samples ${project.version} - 1.4.2 + 1.5.2-SNAPSHOT UTF-8 UTF-8 diff --git a/saga/local-saga-annotation-sample/README.MD b/saga/local-saga-annotation-sample/README.MD new file mode 100644 index 000000000..672e0171a --- /dev/null +++ b/saga/local-saga-annotation-sample/README.MD @@ -0,0 +1,54 @@ +# Seata Saga 注解模式 demo 工程 + +[Seata](https://github.com/seata/seata) 是一款开源的分布式事务解决方案,提供高性能和简单易用的分布式事务服务。 + +## demo 说明 + +基于 Seata Saga注解模式,演示分布式事务的提交和回滚; + +本demo中一个分布式事务内会有2个Saga事务参与者,分别是: [InventoryAction](src/main/java/io/seata/samples/saga/action/InventoryAction.java) +和 [BalanceAction](src/main/java/io/seata/samples/saga/action/BalanceAction.java) +;分布式事务提交则两者均提交,分布式事务回滚则两者均回滚; + +这2个Saga参与者均是 本地bean(非远程RPC服务),两个参与都有一个reduce方法,表示库存扣减或余额扣减,还有一个compensateReduce方法,表示补偿扣减操作。 + +- InventoryAction 接口定义如下: + +```java +@LocalService +public interface InventoryAction { + + /** + * reduce + * + * @param count + * @return + */ + @SagaTransactional(name = "InventoryAction", compensationMethod = "compensateReduce", isDelayReport = true, useCommonFence = true) + boolean reduce(String businessKey, int count); + + /** + * increase + * + * @return + */ + boolean compensateReduce(String businessKey); +} +``` + +## demo 运行指南 + +#### step 1 使用 Docker 部署 Seata Server (1.5.0) + +$ docker run --name seata-server -p 8091:8091 -p 7091:7091 seataio/seata-server:1.5.0 + + +#### step 2 启动 Saga Demo + +运行 [LocalSagaTransactionStarter](src/main/java/io/seata/samples/saga/starter/LocalSagaTransactionStarter.java) +, 启动 demo工程; + + + +内含Saga 事务提交场景和Saga事务回滚场景的演示; + diff --git a/saga/local-saga-annotation-sample/pom.xml b/saga/local-saga-annotation-sample/pom.xml new file mode 100644 index 000000000..8c7bcf226 --- /dev/null +++ b/saga/local-saga-annotation-sample/pom.xml @@ -0,0 +1,39 @@ + + + + + io.seata + seata-samples-saga + 1.1.0 + + 4.0.0 + local-saga-annotation-sample + jar + local-saga-annotation-sample ${project.version} + + + + org.slf4j + slf4j-api + 1.7.7 + + + + + \ No newline at end of file diff --git a/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/ApplicationKeeper.java b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/ApplicationKeeper.java new file mode 100644 index 000000000..92c0a2a0d --- /dev/null +++ b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/ApplicationKeeper.java @@ -0,0 +1,78 @@ +/* + * Copyright 1999-2021 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.samples.saga; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.support.AbstractApplicationContext; + +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.ReentrantLock; + +/** + * The type Application keeper. + */ +public class ApplicationKeeper { + + private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationKeeper.class); + + private final ReentrantLock LOCK = new ReentrantLock(); + private final Condition STOP = LOCK.newCondition(); + + /** + * Instantiates a new Application keeper. + * + * @param applicationContext the application context + */ + public ApplicationKeeper(AbstractApplicationContext applicationContext) { + addShutdownHook(applicationContext); + } + + private void addShutdownHook(final AbstractApplicationContext applicationContext) { + Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { + @Override + public void run() { + try { + applicationContext.close(); + LOGGER.info("ApplicationContext " + applicationContext + " is closed."); + } catch (Exception e) { + LOGGER.error("Failed to close ApplicationContext", e); + } + + try { + LOCK.lock(); + STOP.signal(); + } finally { + LOCK.unlock(); + } + } + })); + } + + /** + * Keep. + */ + public void keep() { + synchronized (LOCK) { + try { + LOGGER.info("Application is keep running ... "); + LOCK.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } +} diff --git a/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/BalanceAction.java b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/BalanceAction.java new file mode 100644 index 000000000..b67be6207 --- /dev/null +++ b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/BalanceAction.java @@ -0,0 +1,50 @@ +/* + * Copyright 1999-2021 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.samples.saga.action; + +import io.seata.saga.annotation.api.SagaTransactional; +import io.seata.spring.annotation.LocalService; + +import java.math.BigDecimal; +import java.util.Map; + +/** + * Balance Actions + */ +@LocalService +public interface BalanceAction { + + /** + * reduce + * + * @param businessKey + * @param amount + * @param params + * @return + */ + @SagaTransactional(name = "BalanceAction" , compensationMethod = "compensateReduce", isDelayReport = true, useCommonFence = true) + boolean reduce(String businessKey, BigDecimal amount, Map params); + + /** + * compensateReduce + * + * @param businessKey + * @param params + * @return + */ + boolean compensateReduce(String businessKey, Map params); + +} diff --git a/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/InventoryAction.java b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/InventoryAction.java new file mode 100644 index 000000000..7d2719363 --- /dev/null +++ b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/InventoryAction.java @@ -0,0 +1,42 @@ +/* + * Copyright 1999-2021 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.samples.saga.action; + +import io.seata.saga.annotation.api.SagaTransactional; +import io.seata.spring.annotation.LocalService; + +/** + * Inventory Actions + */ +@LocalService +public interface InventoryAction { + + /** + * reduce + * + * @param count + * @return + */ + @SagaTransactional(name = "InventoryAction", compensationMethod = "compensateReduce", isDelayReport = true, useCommonFence = true) + boolean reduce(String businessKey, int count); + + /** + * increase + * + * @return + */ + boolean compensateReduce(String businessKey); +} diff --git a/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/ResultHolder.java b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/ResultHolder.java new file mode 100644 index 000000000..a849dfeca --- /dev/null +++ b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/ResultHolder.java @@ -0,0 +1,72 @@ +/* + * Copyright 1999-2021 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.samples.saga.action; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * The type Result holder. + * + * @author zhangsen + */ +public class ResultHolder { + + private static Map actionOneResults = new ConcurrentHashMap(); + + private static Map actionTwoResults = new ConcurrentHashMap(); + + /** + * Set action one result. + * + * @param txId the tx id + * @param result the result + */ + public static void setActionOneResult(String txId, String result) { + actionOneResults.put(txId, result); + } + + /** + * Get action one result string. + * + * @param txId the tx id + * @return the string + */ + public static String getActionOneResult(String txId) { + return actionOneResults.get(txId); + } + + /** + * Set action two result. + * + * @param txId the tx id + * @param result the result + */ + public static void setActionTwoResult(String txId, String result) { + actionTwoResults.put(txId, result); + } + + /** + * Get action two result string. + * + * @param txId the tx id + * @return the string + */ + public static String getActionTwoResult(String txId) { + return actionTwoResults.get(txId); + } + +} diff --git a/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/impl/BalanceActionImpl.java b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/impl/BalanceActionImpl.java new file mode 100644 index 000000000..b3112bf3c --- /dev/null +++ b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/impl/BalanceActionImpl.java @@ -0,0 +1,55 @@ +/* + * Copyright 1999-2021 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.samples.saga.action.impl; + +import io.seata.samples.saga.action.BalanceAction; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.math.BigDecimal; +import java.util.Map; + +/** + * @author lorne.cl + */ +public class BalanceActionImpl implements BalanceAction { + + private static final Logger LOGGER = LoggerFactory.getLogger(BalanceActionImpl.class); + + @Override + public boolean reduce(String businessKey, BigDecimal amount, Map params) { + if(params != null) { + Object throwException = params.get("throwException"); + if (throwException != null && "true".equals(throwException.toString())) { + throw new RuntimeException("reduce balance failed"); + } + } + LOGGER.info("reduce balance succeed, amount: " + amount + ", businessKey:" + businessKey); + return true; + } + + @Override + public boolean compensateReduce(String businessKey, Map params) { + if(params != null) { + Object throwException = params.get("throwException"); + if (throwException != null && "true".equals(throwException.toString())) { + throw new RuntimeException("compensate reduce balance failed"); + } + } + LOGGER.info("compensate reduce balance succeed, businessKey:" + businessKey); + return true; + } +} \ No newline at end of file diff --git a/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/impl/InventoryActionImpl.java b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/impl/InventoryActionImpl.java new file mode 100644 index 000000000..aa8d77440 --- /dev/null +++ b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/impl/InventoryActionImpl.java @@ -0,0 +1,25 @@ +package io.seata.samples.saga.action.impl; + +import io.seata.samples.saga.action.InventoryAction; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author lorne.cl + */ +public class InventoryActionImpl implements InventoryAction { + + private static final Logger LOGGER = LoggerFactory.getLogger(InventoryActionImpl.class); + + @Override + public boolean reduce(String businessKey, int count) { + LOGGER.info("reduce inventory succeed, count: " + count + ", businessKey:" + businessKey); + return true; + } + + @Override + public boolean compensateReduce(String businessKey) { + LOGGER.info("compensate reduce inventory succeed, businessKey:" + businessKey); + return true; + } +} \ No newline at end of file diff --git a/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/service/SagaAnnotationTransactionService.java b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/service/SagaAnnotationTransactionService.java new file mode 100644 index 000000000..89b5578de --- /dev/null +++ b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/service/SagaAnnotationTransactionService.java @@ -0,0 +1,102 @@ +/* + * Copyright 1999-2021 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.samples.saga.service; + +import io.seata.core.context.RootContext; +import io.seata.samples.saga.action.BalanceAction; +import io.seata.samples.saga.action.InventoryAction; +import io.seata.spring.annotation.GlobalTransactional; + +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; + +/** + * The type Saga annotation transaction service. + * + * @author ruishansun + */ +public class SagaAnnotationTransactionService { + + + private BalanceAction balanceAction; + + private InventoryAction inventoryAction; + + + /** + * 发起分布式事务 + * + * @return string string + */ + @GlobalTransactional + public String doTransactionCommit() { + + + String businessKey = String.valueOf(System.currentTimeMillis()); + + boolean result = balanceAction.reduce(businessKey, new BigDecimal("100"), null); + if (!result) { + throw new RuntimeException("balanceAction failed."); + } + result = inventoryAction.reduce(businessKey, 10); + if (!result) { + throw new RuntimeException("inventoryAction failed."); + } + return RootContext.getXID(); + } + + /** + * Do transaction rollback string. + * + * @param map the map + * @return the string + */ + @GlobalTransactional + public String doTransactionRollback(Map map) { + Map startParams = new HashMap<>(3); + String businessKey = String.valueOf(System.currentTimeMillis()); + + boolean result = balanceAction.reduce(businessKey, new BigDecimal("100"), null); + if (!result) { + throw new RuntimeException("balanceAction failed."); + } + result = inventoryAction.reduce(businessKey, 10); + if (!result) { + throw new RuntimeException("inventoryAction failed."); + } + map.put("xid", RootContext.getXID()); + throw new RuntimeException("transacton rollback"); + } + + /** + * Sets tcc action one. + * + * @param balanceAction the tcc action one + */ + public void setBalanceAction(BalanceAction balanceAction) { + this.balanceAction = balanceAction; + } + + /** + * Sets tcc action two. + * + * @param inventoryAction the tcc action two + */ + public void setInventoryAction(InventoryAction inventoryAction) { + this.inventoryAction = inventoryAction; + } +} diff --git a/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/starter/LocalSagaTransactionStarter.java b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/starter/LocalSagaTransactionStarter.java new file mode 100644 index 000000000..8247f594e --- /dev/null +++ b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/starter/LocalSagaTransactionStarter.java @@ -0,0 +1,105 @@ +/* + * Copyright 1999-2021 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.seata.samples.saga.starter; + +import io.seata.common.util.StringUtils; +import io.seata.samples.saga.ApplicationKeeper; +import io.seata.samples.saga.action.BalanceAction; +import io.seata.samples.saga.action.InventoryAction; +import io.seata.samples.saga.action.ResultHolder; +import io.seata.samples.saga.service.SagaAnnotationTransactionService; +import org.springframework.context.support.AbstractApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.util.Assert; + +import java.util.HashMap; +import java.util.Map; + +/** + * The type Local saga annotation transaction starter. + * + * @author ruishansun + */ +public class LocalSagaTransactionStarter { + + /** + * The Application context. + */ + static AbstractApplicationContext applicationContext = null; + + /** + * The Tcc transaction service. + */ + static SagaAnnotationTransactionService sagaAnnotationTransactionService = null; + + static BalanceAction balanceAction; + + static InventoryAction inventoryAction; + + /** + * The entry point of application. + * + * @param args the input arguments + * @throws InterruptedException the interrupted exception + */ + public static void main(String[] args) throws InterruptedException { + applicationContext = new ClassPathXmlApplicationContext(new String[] {"spring/seata-saga.xml"}); + + sagaAnnotationTransactionService = (SagaAnnotationTransactionService)applicationContext.getBean("sagaAnnotationTransactionService"); + + balanceAction = (BalanceAction)applicationContext.getBean("balanceAction"); + inventoryAction = (InventoryAction)applicationContext.getBean("inventoryAction"); + + //分布式事务提交demo + transactionCommitDemo(); + + //分布式事务回滚demo + transactionRollbackDemo(); + + new ApplicationKeeper(applicationContext).keep(); + } + + + private static void transactionCommitDemo() throws InterruptedException { + String txId = sagaAnnotationTransactionService.doTransactionCommit(); + System.out.println(txId); + Assert.isTrue(StringUtils.isNotBlank(txId), "事务开启失败"); + + Thread.sleep(1000L); + + Assert.isTrue("T".equals(ResultHolder.getActionOneResult(txId)), "balanceAction commit success"); + Assert.isTrue("T".equals(ResultHolder.getActionTwoResult(txId)), "inventoryAction commit success"); + + System.out.println("transaction commit demo finish."); + } + + private static void transactionRollbackDemo() throws InterruptedException { + Map map = new HashMap(16); + try { + sagaAnnotationTransactionService.doTransactionRollback(map); + Assert.isTrue(false, "分布式事务未回滚"); + } catch (Throwable t) { + Assert.isTrue(true, "分布式事务异常回滚"); + } + String txId = (String)map.get("xid"); + Thread.sleep(1000L); + + Assert.isTrue("R".equals(ResultHolder.getActionOneResult(txId)), "balanceAction commit failed"); + Assert.isTrue("R".equals(ResultHolder.getActionTwoResult(txId)), "inventoryAction commit failed"); + + System.out.println("transaction rollback demo finish."); + } +} diff --git a/saga/local-saga-annotation-sample/src/main/resources/file.conf b/saga/local-saga-annotation-sample/src/main/resources/file.conf new file mode 100644 index 000000000..2a4a972f1 --- /dev/null +++ b/saga/local-saga-annotation-sample/src/main/resources/file.conf @@ -0,0 +1,66 @@ +transport { + # tcp udt unix-domain-socket + type = "TCP" + #NIO NATIVE + server = "NIO" + #enable heartbeat + heartbeat = true + # the client batch send request enable + enableClientBatchSendRequest = true + #thread factory for netty + threadFactory { + bossThreadPrefix = "NettyBoss" + workerThreadPrefix = "NettyServerNIOWorker" + serverExecutorThread-prefix = "NettyServerBizHandler" + shareBossWorker = false + clientSelectorThreadPrefix = "NettyClientSelector" + clientSelectorThreadSize = 1 + clientWorkerThreadPrefix = "NettyClientWorkerThread" + # netty boss thread size,will not be used for UDT + bossThreadSize = 1 + #auto default pin or 8 + workerThreadSize = "default" + } + shutdown { + # when destroy server, wait seconds + wait = 3 + } + serialization = "seata" + compressor = "none" +} +service { + #transaction service group mapping + vgroupMapping.my_test_tx_group_saga = "default" + #only support when registry.type=file, please don't set multiple addresses + default.grouplist = "127.0.0.1:8091" + #degrade, current not support + enableDegrade = false + #disable seata + disableGlobalTransaction = false +} + +client { + rm { + asyncCommitBufferLimit = 10000 + lock { + retryInterval = 10 + retryTimes = 30 + retryPolicyBranchRollbackOnConflict = true + } + reportRetryCount = 5 + tableMetaCheckEnable = false + reportSuccessEnable = false + } + tm { + commitRetryCount = 5 + rollbackRetryCount = 5 + } + undo { + dataValidation = true + logSerialization = "jackson" + logTable = "undo_log" + } + log { + exceptionRate = 100 + } +} \ No newline at end of file diff --git a/saga/local-saga-annotation-sample/src/main/resources/registry.conf b/saga/local-saga-annotation-sample/src/main/resources/registry.conf new file mode 100644 index 000000000..cd2b7ac33 --- /dev/null +++ b/saga/local-saga-annotation-sample/src/main/resources/registry.conf @@ -0,0 +1,79 @@ +registry { + # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa + type = "file" + + nacos { + application = "seata-server" + serverAddr = "localhost" + namespace = "" + username = "" + password = "" + } + eureka { + serviceUrl = "http://localhost:8761/eureka" + weight = "1" + } + redis { + serverAddr = "localhost:6379" + db = "0" + password = "" + timeout = "0" + } + zk { + serverAddr = "127.0.0.1:2181" + sessionTimeout = 6000 + connectTimeout = 2000 + username = "" + password = "" + } + consul { + serverAddr = "127.0.0.1:8500" + } + etcd3 { + serverAddr = "http://localhost:2379" + } + sofa { + serverAddr = "127.0.0.1:9603" + region = "DEFAULT_ZONE" + datacenter = "DefaultDataCenter" + group = "SEATA_GROUP" + addressWaitTime = "3000" + } + file { + name = "file.conf" + } +} + +config { + # file、nacos 、apollo、zk、consul、etcd3、springCloudConfig + type = "file" + + nacos { + serverAddr = "localhost" + namespace = "" + group = "SEATA_GROUP" + username = "" + password = "" + } + consul { + serverAddr = "127.0.0.1:8500" + } + apollo { + appId = "seata-server" + apolloMeta = "http://192.168.1.204:8801" + namespace = "application" + } + zk { + serverAddr = "127.0.0.1:2181" + sessionTimeout = 6000 + connectTimeout = 2000 + username = "" + password = "" + } + etcd3 { + serverAddr = "http://localhost:2379" + } + file { + name = "file.conf" + } +} diff --git a/saga/local-saga-annotation-sample/src/main/resources/spring/seata-saga.xml b/saga/local-saga-annotation-sample/src/main/resources/spring/seata-saga.xml new file mode 100644 index 000000000..65625ea0f --- /dev/null +++ b/saga/local-saga-annotation-sample/src/main/resources/spring/seata-saga.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/saga/pom.xml b/saga/pom.xml index 07d900281..e85708522 100644 --- a/saga/pom.xml +++ b/saga/pom.xml @@ -31,6 +31,7 @@ local-saga-sample sofarpc-saga-sample dubbo-saga-sample + local-saga-annotation-sample diff --git a/tcc/sofarpc-tcc-sample/pom.xml b/tcc/sofarpc-tcc-sample/pom.xml index 4aaf76e4b..0de5c60ee 100644 --- a/tcc/sofarpc-tcc-sample/pom.xml +++ b/tcc/sofarpc-tcc-sample/pom.xml @@ -18,9 +18,9 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - com.alipay.sofa - sofaboot-dependencies - 2.6.1 + io.seata + seata-samples-tcc + 1.1.0 4.0.0 diff --git a/tcc/springboot-tcc-sample/pom.xml b/tcc/springboot-tcc-sample/pom.xml index fe8b17ae8..60d5e629b 100644 --- a/tcc/springboot-tcc-sample/pom.xml +++ b/tcc/springboot-tcc-sample/pom.xml @@ -18,9 +18,9 @@ xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - org.springframework.boot - spring-boot-starter-parent - 1.5.16.RELEASE + io.seata + seata-samples-tcc + 1.1.0 4.0.0 From c0c6b21fe8a0edb2c05a3f2bccde5d8d9e722047 Mon Sep 17 00:00:00 2001 From: ruishansun Date: Sat, 9 Jul 2022 16:41:41 +0800 Subject: [PATCH 2/4] add Copy right --- .../saga/action/impl/InventoryActionImpl.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/impl/InventoryActionImpl.java b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/impl/InventoryActionImpl.java index aa8d77440..9e92d2031 100644 --- a/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/impl/InventoryActionImpl.java +++ b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/impl/InventoryActionImpl.java @@ -1,3 +1,18 @@ +/* + * Copyright 1999-2021 Seata.io Group. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package io.seata.samples.saga.action.impl; import io.seata.samples.saga.action.InventoryAction; From 00ec772396169c364d148fcc21d5c16d3d3050af Mon Sep 17 00:00:00 2001 From: ruishansun Date: Sat, 23 Jul 2022 18:37:33 +0800 Subject: [PATCH 3/4] saga test update --- pom.xml | 2 +- .../samples/saga/action/BalanceAction.java | 10 +++++----- .../samples/saga/action/InventoryAction.java | 7 ++++--- .../saga/action/impl/BalanceActionImpl.java | 17 ++++++++--------- .../saga/action/impl/InventoryActionImpl.java | 11 ++++++++--- .../SagaAnnotationTransactionService.java | 8 ++++---- saga/pom.xml | 6 +++++- tcc/pom.xml | 6 +++++- tcc/springboot-tcc-sample/pom.xml | 8 ++++---- 9 files changed, 44 insertions(+), 31 deletions(-) diff --git a/pom.xml b/pom.xml index 3dbe1844b..90d203fb9 100644 --- a/pom.xml +++ b/pom.xml @@ -24,7 +24,7 @@ 1.1.0 seata-samples ${project.version} - 1.5.2-SNAPSHOT + 1.4.2 UTF-8 UTF-8 diff --git a/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/BalanceAction.java b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/BalanceAction.java index b67be6207..a8acbbd3a 100644 --- a/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/BalanceAction.java +++ b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/BalanceAction.java @@ -15,6 +15,7 @@ */ package io.seata.samples.saga.action; +import io.seata.rm.tcc.api.BusinessActionContext; import io.seata.saga.annotation.api.SagaTransactional; import io.seata.spring.annotation.LocalService; @@ -35,16 +36,15 @@ public interface BalanceAction { * @param params * @return */ - @SagaTransactional(name = "BalanceAction" , compensationMethod = "compensateReduce", isDelayReport = true, useCommonFence = true) - boolean reduce(String businessKey, BigDecimal amount, Map params); + @SagaTransactional(name = "BalanceAction" , compensationMethod = "compensateReduce", isDelayReport = true, useCommonFence = false) + boolean reduce(BusinessActionContext actionContext, String businessKey, BigDecimal amount, Map params); /** * compensateReduce * - * @param businessKey - * @param params + * @param actionContext * @return */ - boolean compensateReduce(String businessKey, Map params); + boolean compensateReduce(BusinessActionContext actionContext); } diff --git a/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/InventoryAction.java b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/InventoryAction.java index 7d2719363..1467b7559 100644 --- a/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/InventoryAction.java +++ b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/InventoryAction.java @@ -15,6 +15,7 @@ */ package io.seata.samples.saga.action; +import io.seata.rm.tcc.api.BusinessActionContext; import io.seata.saga.annotation.api.SagaTransactional; import io.seata.spring.annotation.LocalService; @@ -30,13 +31,13 @@ public interface InventoryAction { * @param count * @return */ - @SagaTransactional(name = "InventoryAction", compensationMethod = "compensateReduce", isDelayReport = true, useCommonFence = true) - boolean reduce(String businessKey, int count); + @SagaTransactional(name = "InventoryAction", compensationMethod = "compensateReduce", isDelayReport = true, useCommonFence = false) + boolean reduce(BusinessActionContext actionContext, String businessKey, int count); /** * increase * * @return */ - boolean compensateReduce(String businessKey); + boolean compensateReduce(BusinessActionContext actionContext); } diff --git a/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/impl/BalanceActionImpl.java b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/impl/BalanceActionImpl.java index b3112bf3c..207551a62 100644 --- a/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/impl/BalanceActionImpl.java +++ b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/impl/BalanceActionImpl.java @@ -15,7 +15,9 @@ */ package io.seata.samples.saga.action.impl; +import io.seata.rm.tcc.api.BusinessActionContext; import io.seata.samples.saga.action.BalanceAction; +import io.seata.samples.saga.action.ResultHolder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -30,7 +32,7 @@ public class BalanceActionImpl implements BalanceAction { private static final Logger LOGGER = LoggerFactory.getLogger(BalanceActionImpl.class); @Override - public boolean reduce(String businessKey, BigDecimal amount, Map params) { + public boolean reduce(BusinessActionContext actionContext, String businessKey, BigDecimal amount, Map params) { if(params != null) { Object throwException = params.get("throwException"); if (throwException != null && "true".equals(throwException.toString())) { @@ -38,18 +40,15 @@ public boolean reduce(String businessKey, BigDecimal amount, Map } } LOGGER.info("reduce balance succeed, amount: " + amount + ", businessKey:" + businessKey); + ResultHolder.setActionOneResult(actionContext.getXid(), "T"); return true; } @Override - public boolean compensateReduce(String businessKey, Map params) { - if(params != null) { - Object throwException = params.get("throwException"); - if (throwException != null && "true".equals(throwException.toString())) { - throw new RuntimeException("compensate reduce balance failed"); - } - } - LOGGER.info("compensate reduce balance succeed, businessKey:" + businessKey); + public boolean compensateReduce(BusinessActionContext actionContext) { + String xid = actionContext.getXid(); + System.out.println("Balance compensate Reduce, xid:" + xid); + ResultHolder.setActionOneResult(xid, "R"); return true; } } \ No newline at end of file diff --git a/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/impl/InventoryActionImpl.java b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/impl/InventoryActionImpl.java index 9e92d2031..456cd9c7f 100644 --- a/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/impl/InventoryActionImpl.java +++ b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/action/impl/InventoryActionImpl.java @@ -15,7 +15,9 @@ */ package io.seata.samples.saga.action.impl; +import io.seata.rm.tcc.api.BusinessActionContext; import io.seata.samples.saga.action.InventoryAction; +import io.seata.samples.saga.action.ResultHolder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -27,14 +29,17 @@ public class InventoryActionImpl implements InventoryAction { private static final Logger LOGGER = LoggerFactory.getLogger(InventoryActionImpl.class); @Override - public boolean reduce(String businessKey, int count) { + public boolean reduce(BusinessActionContext actionContext, String businessKey, int count) { LOGGER.info("reduce inventory succeed, count: " + count + ", businessKey:" + businessKey); + ResultHolder.setActionTwoResult(actionContext.getXid(), "T"); return true; } @Override - public boolean compensateReduce(String businessKey) { - LOGGER.info("compensate reduce inventory succeed, businessKey:" + businessKey); + public boolean compensateReduce(BusinessActionContext actionContext) { + String xid = actionContext.getXid(); + System.out.println("Inventory compensate Reduce, xid:" + xid); + ResultHolder.setActionTwoResult(xid, "R"); return true; } } \ No newline at end of file diff --git a/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/service/SagaAnnotationTransactionService.java b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/service/SagaAnnotationTransactionService.java index 89b5578de..93a6bc6c0 100644 --- a/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/service/SagaAnnotationTransactionService.java +++ b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/service/SagaAnnotationTransactionService.java @@ -48,11 +48,11 @@ public String doTransactionCommit() { String businessKey = String.valueOf(System.currentTimeMillis()); - boolean result = balanceAction.reduce(businessKey, new BigDecimal("100"), null); + boolean result = balanceAction.reduce(null, businessKey, new BigDecimal("100"), null); if (!result) { throw new RuntimeException("balanceAction failed."); } - result = inventoryAction.reduce(businessKey, 10); + result = inventoryAction.reduce(null, businessKey, 10); if (!result) { throw new RuntimeException("inventoryAction failed."); } @@ -70,11 +70,11 @@ public String doTransactionRollback(Map map) { Map startParams = new HashMap<>(3); String businessKey = String.valueOf(System.currentTimeMillis()); - boolean result = balanceAction.reduce(businessKey, new BigDecimal("100"), null); + boolean result = balanceAction.reduce(null, businessKey, new BigDecimal("100"), null); if (!result) { throw new RuntimeException("balanceAction failed."); } - result = inventoryAction.reduce(businessKey, 10); + result = inventoryAction.reduce(null, businessKey, 10); if (!result) { throw new RuntimeException("inventoryAction failed."); } diff --git a/saga/pom.xml b/saga/pom.xml index e85708522..0d7142b08 100644 --- a/saga/pom.xml +++ b/saga/pom.xml @@ -34,6 +34,10 @@ local-saga-annotation-sample + + 1.6.0-SNAPSHOT + + @@ -67,7 +71,7 @@ io.seata seata-all - ${seata.version} + ${seata.all.version} io.seata diff --git a/tcc/pom.xml b/tcc/pom.xml index 6abd2657d..b36b68feb 100644 --- a/tcc/pom.xml +++ b/tcc/pom.xml @@ -36,6 +36,10 @@ hsf-tcc-sample + + 1.6.0-SNAPSHOT + + @@ -80,7 +84,7 @@ io.seata seata-all - ${seata.version} + ${seata.all.version} io.seata diff --git a/tcc/springboot-tcc-sample/pom.xml b/tcc/springboot-tcc-sample/pom.xml index 60d5e629b..510123d4d 100644 --- a/tcc/springboot-tcc-sample/pom.xml +++ b/tcc/springboot-tcc-sample/pom.xml @@ -18,9 +18,9 @@ xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - io.seata - seata-samples-tcc - 1.1.0 + org.springframework.boot + spring-boot-starter-parent + 1.5.16.RELEASE 4.0.0 @@ -95,7 +95,7 @@ io.seata seata-all - ${seata.version} + 1.6.0-SNAPSHOT From 104a47f75564ceca598d4e01e0faaa7bd94042d1 Mon Sep 17 00:00:00 2001 From: rainshell Date: Sat, 30 Jul 2022 17:22:29 +0800 Subject: [PATCH 4/4] log update --- .../samples/saga/starter/LocalSagaTransactionStarter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/starter/LocalSagaTransactionStarter.java b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/starter/LocalSagaTransactionStarter.java index 8247f594e..fbfa2524d 100644 --- a/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/starter/LocalSagaTransactionStarter.java +++ b/saga/local-saga-annotation-sample/src/main/java/io/seata/samples/saga/starter/LocalSagaTransactionStarter.java @@ -97,8 +97,8 @@ private static void transactionRollbackDemo() throws InterruptedException { String txId = (String)map.get("xid"); Thread.sleep(1000L); - Assert.isTrue("R".equals(ResultHolder.getActionOneResult(txId)), "balanceAction commit failed"); - Assert.isTrue("R".equals(ResultHolder.getActionTwoResult(txId)), "inventoryAction commit failed"); + Assert.isTrue("R".equals(ResultHolder.getActionOneResult(txId)), "balanceAction rollback failed"); + Assert.isTrue("R".equals(ResultHolder.getActionTwoResult(txId)), "inventoryAction rollback failed"); System.out.println("transaction rollback demo finish."); }