Quick Start

Let's begin with a Microservices example.

Use case

A business logic for user purchasing commodities. The whole business logic is powered by 3 microservices:

  • Storage service: deduct storage count on given commodity.
  • Order service: create order according to purchase request.
  • Account service: debit the balance of user's account.

Architecture

Architecture

StorageService

  1. public interface StorageService {
  2.  
  3. /**
  4. * deduct storage count
  5. */
  6. void deduct(String commodityCode, int count);
  7. }

OrderService

  1. public interface OrderService {
  2.  
  3. /**
  4. * create order
  5. */
  6. Order create(String userId, String commodityCode, int orderCount);
  7. }

AccountService

  1. public interface AccountService {
  2.  
  3. /**
  4. * debit balance of user's account
  5. */
  6. void debit(String userId, int money);
  7. }

Main business logic

  1. public class BusinessServiceImpl implements BusinessService {
  2.  
  3. private StorageService storageService;
  4.  
  5. private OrderService orderService;
  6.  
  7. /**
  8. * purchase
  9. */
  10. public void purchase(String userId, String commodityCode, int orderCount) {
  11.  
  12. storageService.deduct(commodityCode, orderCount);
  13.  
  14. orderService.create(userId, commodityCode, orderCount);
  15. }
  16. }
  1. public class OrderServiceImpl implements OrderService {
  2.  
  3. private OrderDAO orderDAO;
  4.  
  5. private AccountService accountService;
  6.  
  7. public Order create(String userId, String commodityCode, int orderCount) {
  8.  
  9. int orderMoney = calculate(commodityCode, orderCount);
  10.  
  11. accountService.debit(userId, orderMoney);
  12.  
  13. Order order = new Order();
  14. order.userId = userId;
  15. order.commodityCode = commodityCode;
  16. order.count = orderCount;
  17. order.money = orderMoney;
  18.  
  19. // INSERT INTO orders ...
  20. return orderDAO.insert(order);
  21. }

Distributed Transaction Solution with FESCAR

undefined

We just need an annotation @GlobalTransactional on business method:

  1. @GlobalTransactional
  2. public void purchase(String userId, String commodityCode, int orderCount) {
  3. ......
  4. }

Example powered by Dubbo + FESCAR

Step 1: Setup database

  • Requirement: MySQL with InnoDB engine.
    Note: In fact, there should be 3 database for the 3 services in the example use case. However, we can just create one database and configure 3 data sources for simple.

Modify Spring XML with the database URL/username/password you just created.

dubbo-account-service.xmldubbo-order-service.xmldubbo-storage-service.xml

  1. <property name="url" value="jdbc:mysql://x.x.x.x:3306/xxx" />
  2. <property name="username" value="xxx" />
  3. <property name="password" value="xxx" />

Step 2: Create UNDO_LOG table

UNDO_LOG table is required by FESCAR AT mode.

  1. -- 注意此处0.3.0+ 增加唯一索引 ux_undo_log
  2. CREATE TABLE `undo_log` (
  3. `id` bigint(20) NOT NULL AUTO_INCREMENT,
  4. `branch_id` bigint(20) NOT NULL,
  5. `xid` varchar(100) NOT NULL,
  6. `rollback_info` longblob NOT NULL,
  7. `log_status` int(11) NOT NULL,
  8. `log_created` datetime NOT NULL,
  9. `log_modified` datetime NOT NULL,
  10. `ext` varchar(100) DEFAULT NULL,
  11. PRIMARY KEY (`id`),
  12. UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
  13. ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

Step 3: Create tables for example business

  1. DROP TABLE IF EXISTS `storage_tbl`;
  2. CREATE TABLE `storage_tbl` (
  3. `id` int(11) NOT NULL AUTO_INCREMENT,
  4. `commodity_code` varchar(255) DEFAULT NULL,
  5. `count` int(11) DEFAULT 0,
  6. PRIMARY KEY (`id`),
  7. UNIQUE KEY (`commodity_code`)
  8. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  9.  
  10.  
  11. DROP TABLE IF EXISTS `order_tbl`;
  12. CREATE TABLE `order_tbl` (
  13. `id` int(11) NOT NULL AUTO_INCREMENT,
  14. `user_id` varchar(255) DEFAULT NULL,
  15. `commodity_code` varchar(255) DEFAULT NULL,
  16. `count` int(11) DEFAULT 0,
  17. `money` int(11) DEFAULT 0,
  18. PRIMARY KEY (`id`)
  19. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  20.  
  21.  
  22. DROP TABLE IF EXISTS `account_tbl`;
  23. CREATE TABLE `account_tbl` (
  24. `id` int(11) NOT NULL AUTO_INCREMENT,
  25. `user_id` varchar(255) DEFAULT NULL,
  26. `money` int(11) DEFAULT 0,
  27. PRIMARY KEY (`id`)
  28. ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Step 4: Start Server

  1. sh fescar-server.sh $LISTEN_PORT $PATH_FOR_PERSISTENT_DATA
  2.  
  3. e.g.
  4.  
  5. sh fescar-server.sh 8091 /home/admin/fescar/data/

Step 5: Run example

Go to samples repo: Fescar-samples

  • Start AccountService
  • Start StorageService
  • Start OrderService
  • Run BusinessService for demo test
    TBD: scripts for run demo applications