分布式系列教程(23) -分布式事务解决方案(实践篇)

1. SpringCloud 集成LCN框架

目前LCN版本已经升级为4.0了,但是官方没有SpringCloud2.0的demo案例。

因为LCN本身是开源的,网上有大牛对LCN框架源码做修改,可以支持SpringCloud2.0版本。

下面来讲解下SpringCloud2.0集成LCN框架的步骤:

1.添加maven依赖

<dependency>
	<groupId>com.codingapigroupId>
	<artifactId>transaction-springcloudartifactId>
	<version>4.1.2version>
	<exclusions>
		<exclusion>
			<groupId>org.slf4jgroupId>
			<artifactId>*artifactId>
		exclusion>
	exclusions>
dependency>
<dependency>
	<groupId>com.codingapigroupId>
	<artifactId>tx-plugins-dbartifactId>
	<version>4.1.2version>
	<exclusions>
		<exclusion>
			<groupId>org.slf4jgroupId>
			<artifactId>*artifactId>
		exclusion>
	exclusions>
dependency>
<dependency>
	<groupId>org.springframework.bootgroupId>
	<artifactId>spring-boot-starter-webartifactId>
dependency>

2.applicatoin.yml引入

tm: 
  manager: 
     url: http://127.0.0.1:8899/tx/manager/

3.LCN基本配置代码

@Service
public class TxManagerTxUrlServiceImpl implements TxManagerTxUrlService {

	@Value("${tm.manager.url}")
	private String url;

	@Override
	public String getTxUrl() {
		System.out.println("load tm.manager.url ");
		return url;
	}
}
@Service
public class TxManagerHttpRequestServiceImpl implements TxManagerHttpRequestService {

	@Override
	public String httpGet(String url) {
		System.out.println("httpGet-start");
		String res = HttpUtils.get(url);
		System.out.println("httpGet-end");
		return res;
	}

	@Override
	public String httpPost(String url, String params) {
		System.out.println("httpPost-start");
		String res = HttpUtils.post(url, params);
		System.out.println("httpPost-end");
		return res;
	}
}

4.分布式事务案例

// 下单扣库存
@TxTransaction(isStart = true)
@Transactional
@GetMapping(value = "/addOrderAndStock")
public ResponseBase addOrderAndStock(int i) {
	//1.填写订单信息
	OrderEntity orderEntity = new OrderEntity();
	orderEntity.setName("订单-001");
	orderEntity.setOrderCreatetime(new Date());
	// 价格是300元
	orderEntity.setOrderMoney(300d);
	// 状态为 未支付
	orderEntity.setOrderState(0);
	Long commodityId = 30l;
	// 商品id
	orderEntity.setCommodityId(commodityId);
	
	// 2.先下单,创建订单
	int orderResult = orderMapper.addOrder(orderEntity);
	System.out.println("orderResult:" + orderResult);
	
	// 3.下单成功后,调用库存服务
	ResponseBase inventoryReduction = stockFeign.inventoryReduction(commodityId);
	// if (inventoryReduction.getRtnCode() != 200) {
	// // 手动回滚事务
	// }
	
	//4.模拟异常
	int reuslt = 1 / i;
	return setResultSuccess("下单成功!");
}

使用@TxTransaction解决分布式事务 isStart

  • true :是发起方
  • false :是参与方

同理生产者 同样配置集成即可,只需要把Transaction中的isStart改为fasle即可

2. LCN协调者服务集群

官方文档: https://github.com/codingapi/tx-lcn/wiki/TxManager%E9%9B%86%E7%BE%A4%E8%AF%B4%E6%98%8E

核心原理通过该实现类:NettyDistributeServiceImpl 38行获取服务器集群地址

private void getTxServer() {
    //获取负载均衡服务地址
    String json = null;
    while (StringUtils.isEmpty(json)) {
        json = txManagerService.httpGetServer();
        logger.info("get txManager ->" + json);
        if (StringUtils.isEmpty(json)) {
            logger.error("TxManager服务器无法访问.");
            try {
                Thread.sleep(1000 * 2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    TxServer txServer = TxServer.parser(json);
    if (txServer != null) {
        logger.debug("txServer -> " + txServer);
        logger.info(txServer.toString());
        Constants.txServer = txServer;
        logger.info(Constants.txServer.toString());
        connectCont = 0;
    }

}

LCN协调者服务集群原理:

  1. 首先通过nginx配置多个tm协调者负载均衡配置,然后 LCN客户端启动项目的时候访问Nginx负载均衡地址获取LCN协议通讯IP地址和端口号,并且对该连接保持长连接。
  2. 因为LCN客户端与TM协调者保持的是长连接,当tm协调者宕机之后,LCN会客户端会立即重新进入到获取负载均衡地址LCN协议通讯IP地址和端口号。

Nginx负载均衡配置:

#### 上游服务器 集群 默认轮训机制
    upstream  backServer{
	    server 127.0.0.1:8899;
	    server 127.0.0.1:8898;
	}
    server {
        listen       80;
        server_name  wg.xxx.com;
        location / {
            ### 指定上游服务器负载均衡服务器
		    proxy_pass http://backServer/;
			###nginx与上游服务器(真实访问的服务器)超时时间 后端服务器连接的超时时间_发起握手等候响应超时时间
			proxy_connect_timeout 5s;
			###nginx发送给上游服务器(真实访问的服务器)超时时间
            proxy_send_timeout 5s;
			### nginx接受上游服务器(真实访问的服务器)超时时间
            proxy_read_timeout 5s;
            index  index.html index.htm;
		    

        }     

Yml配置文件连接:

tm: 
  manager: 
      url: http://wg.xxx.com/tx/manager/

你可能感兴趣的:(#,分布式)