liuyangming / ByteTCC

ByteTCC is a distributed transaction manager based on the TCC(Try/Confirm/Cancel) mechanism. It’s compatible with the JTA specification. User guide: https://github.com/liuyangming/ByteTCC/wiki
https://www.bytesoft.org/
GNU Lesser General Public License v3.0
2.9k stars 911 forks source link

try阶段完成后没有执行confirm,try阶段异常后也没有回滚之前的feign调用 #72

Open dawe001 opened 6 years ago

dawe001 commented 6 years ago
  1. try阶段完成后没有执行confirm,
  2. 消费端try阶段异常后也没有回滚之前的feign调用, 没有通知生产者执行cancel
liuyangming commented 6 years ago

首先,请确认应用配置的正确性。 其次,如果确定配置没问题,至少也要列一下工程地址,或者简述一下服务关系、调用情况等。不然,什么信息都没有,光说现象,我也无从帮你,不是么?

shaowin16 commented 4 years ago
  1. try阶段完成后没有执行confirm,
  2. 消费端try阶段异常后也没有回滚之前的feign调用, 没有通知生产者执行cancel

我的也是一样的情况

过程如下:

  1. 消费方 controller

    
    @Compensable(interfaceClass = ITransferService.class, confirmableKey = "transferServiceConfirm", cancellableKey = "transferServiceCancel")
    @RestController
    public class TransferController {
    @Autowired
    private TransferServiceTry transferServiceTry;
    
    @Autowired
    private IAccountService acctService;
    
    @ResponseBody
    @RequestMapping(value = "/transfer", method = RequestMethod.POST)
    @Transactional
    public void transfer(@RequestParam("sourceAcctId") String sourceAcctId, @RequestParam("targetAcctId") String targetAcctId,
                         @RequestParam("amount") double amount) throws Exception {
        this.transferServiceTry.transfer(sourceAcctId, targetAcctId, amount);
        this.acctService.decreaseAmount(sourceAcctId, amount);
    }
    }


2. 在acctServiceTry的decreaseAmount方法中执行sql后抛出异常(try阶段)

`@Service("accountServiceTry")
public class AccountServiceTry implements IAccountService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    @Transactional
    public void decreaseAmount(String accountId, double amount) throws Exception {
        this.jdbcTemplate.update("update tb_account_one set amount = amount - ? where acct_id = ?", amount, accountId);
        System.out.printf("try decrease: acct= %s, amount= %7.2f%n", accountId, amount);
        throw new Exception("TEST 事务");
    }

}`

3. 最终结果
accountService 执行了try何cancel阶段,但TransferService只执行了try阶段
shaowin16 commented 4 years ago
  1. try阶段完成后没有执行confirm,
  2. 消费端try阶段异常后也没有回滚之前的feign调用, 没有通知生产者执行cancel

我的也是一样的情况

过程如下:

  1. 消费方 controller
@Compensable(interfaceClass = ITransferService.class, confirmableKey = "transferServiceConfirm", cancellableKey = "transferServiceCancel")
@RestController
public class TransferController {
    @Autowired
    private TransferServiceTry transferServiceTry;

   @Autowired
    private IAccountService acctService;

    @ResponseBody
    @RequestMapping(value = "/transfer", method = RequestMethod.POST)
    @Transactional
    public void transfer(@RequestParam("sourceAcctId") String sourceAcctId, @RequestParam("targetAcctId") String targetAcctId,
                         @RequestParam("amount") double amount) throws Exception {
        this.transferServiceTry.transfer(sourceAcctId, targetAcctId, amount);
        this.acctService.decreaseAmount(sourceAcctId, amount);
    }
}
  1. 在acctServiceTry的decreaseAmount方法中执行sql后抛出异常(try阶段)

`@Service("accountServiceTry") public class AccountServiceTry implements IAccountService {

@Autowired
private JdbcTemplate jdbcTemplate;

@Override
@Transactional
public void decreaseAmount(String accountId, double amount) throws Exception {
  this.jdbcTemplate.update("update tb_account_one set amount = amount - ? where acct_id = ?", amount, accountId);
  System.out.printf("try decrease: acct= %s, amount= %7.2f%n", accountId, amount);
  throw new Exception("TEST 事务");
}

}`

  1. 最终结果 accountService 执行了try何cancel阶段,但TransferService只执行了try阶段

另外,还有另一种情况:

  1. 重新定义了一个web模块的微服务,远程调用transferService和accountService
  2. 最终执行成功,可看打印的日志,只执行了transferService的try阶段,accountService是正常的,执行了try和confirm阶段,可结果是正确的,transferService和accountService的结果都被更改了

所以想问一下,为什么没有执行transferService的confirm阶段?

服务源代码如下: web模块 (1)AggreateController

public class AggreateController {
    @Autowired
    private ITransferService transferService;

    @Autowired
    private IAccountService acctService;

    @ResponseBody
    @RequestMapping(value = "/aggreate", method = RequestMethod.POST)
    @Transactional
    public void transfer(@RequestParam String sourceAcctId, @RequestParam String targetAcctId, @RequestParam double amount) {
        System.out.println("进入测试!!");
        this.acctService.decreaseAmount(sourceAcctId, amount);
        this.transferService.increaseAmount(sourceAcctId, targetAcctId, amount);

    }

}

TransferService对应的微服务 (2)TransferController

@Compensable(interfaceClass = ITransferService.class, confirmableKey = "transferServiceConfirm", cancellableKey = "transferServiceCancel")
@RestController
public class TransferController {
    @Autowired
    private TransferServiceTry transferServiceTry;

    @ResponseBody
    @RequestMapping(value = "/increase", method = RequestMethod.POST)
    @Transactional
    public void increaseAmount(@RequestParam("sourceAcctId") String sourceAcctId, @RequestParam("targetAcctId") String targetAcctId,
                         @RequestParam("amount") double amount) throws Exception {
        System.out.println("consumer进入测试!!");
        this.transferServiceTry.transfer(sourceAcctId, targetAcctId, amount);
    }
}

(3)TransferServiceTry

@Service("transferServiceTry")
public class TransferServiceTry implements ITransferService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Transactional
    @Override
    public void transfer(String sourceAcctId, String targetAcctId, double amount) throws Exception {
//        this.transferDao.increaseAmount(targetAcctId, amount);

        this.jdbcTemplate.update("update tb_account_two set amount = amount + ? where acct_id = ?", amount, targetAcctId);
        System.out.printf("try increase: acct= %s, amount= %7.2f%n", targetAcctId, amount);
//        throw new Exception("TEST 事务");
    }

}

(4)TransferServiceConfirm

public class TransferServiceConfirm implements ITransferService {

    @Autowired
    private TransferDao transferDao;

    @Transactional
    @Override
    public void transfer(String sourceAcctId, String targetAcctId, double amount) {
        // do nothing
        System.out.printf("confirm increase: acct= %s, amount= %7.2f%n", targetAcctId, amount);
    }

}

(5)TransferServiceCancel

public class TransferServiceCancel implements ITransferService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Transactional
    @Override
    public void transfer(String sourceAcctId, String targetAcctId, double amount) {
        this.jdbcTemplate.update("update tb_account_two set amount = amount - ? where acct_id = ?", amount, targetAcctId);
        System.out.printf("cancel increase: acct= %s, amount= %7.2f%n", targetAcctId, amount);
    }

}
liuyangming commented 4 years ago

2. accountService

结果是正确的,说明confirm是应该是执行过了的。 0.5.9版本刚修复了一个bug,在使用hystrix时,会出现远程分支commit/rollback处理异常,现象就是没有执行远程分支的confirm/cancel(但重启后故障恢复时仍然会执行)。你说的这个问题,可能与此相关(故障恢复时打印的日志可能与其他阶段日志并不在一起,所以没有留意到?)。

请使用0.5.9版本再确认一下该问题是否还存在。