好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

详解Spring Boot微服务如何集成fescar解决分布式事务问题

什么是fescar?

关于fescar的详细介绍,请参阅 fescar wiki 。

传统的2pc提交协议,会持有一个全局性的锁,所有局部事务预提交成功后一起提交,或有一个局部事务预提交失败后一起回滚,最后释放全局锁。锁持有的时间较长,会对并发造成较大的影响,死锁的风险也较高。

fescar的创新之处在于,每个局部事务执行完立即提交,释放本地锁;它会去解析你代码中的sql,从数据库中获得事务提交前的事务资源即数据,存放到undo_log中,全局事务协调器在回滚的时候直接使用undo_log中的数据覆盖你提交的数据。

spring boot如何集成fescar?

我们可以从 官方代码库 中看到,fescar目前提供的示例是针对使用dubbo的服务,那spring boot的项目如何集成fescar呢?

  

和很多2pc提交协议(如 tx_lcn )的解决方案一样,fescar也是在数据源处做了代理,和事务协调器进行通信,来决定本地事务是否回滚。所以,第一步,在你的spring boot项目中,首先应使用fescar提供的代理数据源作为你的数据源,例如:

?

1

2

3

druiddatasource datasource = initdatasource(datasourceprops.get( "url" ).tostring(), datasourceprops.get( "username" ).tostring(), datasourceprops.get( "password" ).tostring());

 

datasourceproxy proxy = new datasourceproxy(datasource);

然后,你需要创建一个feign拦截器,把rootcontext中的xid(xid用于标识一个局部事务属于哪个全局事务,需要在调用链路的上下文中传递)传递到上层调用链路。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

@component

 

public class requestheaderinterceptor implements requestinterceptor {

 

   @override

 

   public void apply(requesttemplate template) {

 

     string xid = rootcontext.getxid();

 

     if (stringutils.isnotblank(xid)){

 

       template.header( "fescar-xid" ,xid);

 

     }

 

   }

 

}

最后,你需要创建一个http rest请求拦截器,用于把当前上下文中获取到的xid放到rootcontext。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

import com.alibaba.fescar.core.context.rootcontext;

 

import org.apache.commons.lang.stringutils;

 

import org.slf4j.logger;

 

import org.slf4j.loggerfactory;

 

import org.springframework.web.filter.onceperrequestfilter;

 

 

 

import javax.servlet.filterchain;

 

import javax.servlet.servletexception;

 

import javax.servlet.http.httpservletrequest;

 

import javax.servlet.http.httpservletresponse;

 

import java.io.ioexception;

 

 

 

public class fescarxidfilter extends onceperrequestfilter {

 

   protected logger logger = loggerfactory.getlogger(fescarxidfilter. class );

 

 

 

   @override

 

   protected void dofilterinternal(httpservletrequest request, httpservletresponse response, filterchain filterchain) throws servletexception, ioexception {

 

     string xid = rootcontext.getxid();

 

     string restxid = request.getheader( "fescar-xid" );

 

     boolean bind = false ;

 

     if (stringutils.isblank(xid)&&stringutils.isnotblank(restxid)){

 

       rootcontext.bind(restxid);

 

       bind = true ;

 

       if (logger.isdebugenabled()) {

 

         logger.debug( "bind[" + restxid + "] to rootcontext" );

 

       }

 

     }

 

     try {

 

       filterchain.dofilter(request, response);

 

     } finally {

 

       if (bind) {

 

         string unbindxid = rootcontext.unbind();

 

         if (logger.isdebugenabled()) {

 

           logger.debug( "unbind[" + unbindxid + "] from rootcontext" );

 

         }

 

         if (!restxid.equalsignorecase(unbindxid)) {

 

           logger.warn( "xid in change during http rest from " + restxid + " to " + unbindxid);

 

           if (unbindxid != null ) {

 

             rootcontext.bind(unbindxid);

 

             logger.warn( "bind [" + unbindxid + "] back to rootcontext" );

 

           }

         }

       }

     }

   }

}

这样就完成了fescar的集成。

开始使用吧!

首先在项目中初始化两个bean:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

@bean

 

public fescarxidfilter fescarxidfilter(){

 

   return new fescarxidfilter();

 

}

 

 

 

@bean

 

public globaltransactionscanner scanner(){

 

   globaltransactionscanner scanner = new globaltransactionscanner( "fescar-test" , "my_test_tx_group" );

 

   return scanner;

 

}

然后写两个服务,服务a调用服务b,并在a服务的调用方法上打上@globaltransactional标签:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

@globaltransactional (timeoutmills = 300000 , name = "fescar-test-tx" )

 

public void testfescar() throws businessexception {

 

   dictionvo dictionvo = new dictionvo();

 

   dictionvo.setcode( "simidatest" );

 

   dictionvo.setvalue( "1" );

 

   dictionvo.setdesc( "simidatest" );

 

   dictionvo.setappid( "sso" );

 

   commonservice.creatediction(dictionvo); //远程调用服务b

 

   areamapper.deleteareabysysno( 2 ); //本地事务

 

 

 

   throw new businessexception( "主动报错" );

 

}

最后,两个项目中添加application.conf文件,用于告诉客户端如何与分布式协调器通信,官方示例中有这个文件,就不在此贴代码啦, application.conf传送门

启动事务协调器,sh fescar-server.sh 8091 ~/dksl/git/fescar/data,启动你的项目,开始测试吧!

last thing

分布式事务 作为微服务应用中的老大难问题,在现有的解决方案中,个人认为fescar是目前最轻量并且代价最小的一种解决方案。目前的版本,事务协调器还不能分布式部署,官方给出的路线图是在三月底会有第一个生产可用版本。让我们一起参与到fescar的社区中,共同推动fescar生态建设,让落地微服务不必再担心分布式事务的问题。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

原文链接:http://www.cnblogs.com/DKSL/p/fescar.html

查看更多关于详解Spring Boot微服务如何集成fescar解决分布式事务问题的详细内容...

  阅读:10次