1. SpringCloud 集成LCN框架
目前LCN版本已经升级为4.0了,但是官方没有SpringCloud2.0的demo案例。
因为LCN本身是开源的,网上有大牛对LCN框架源码做修改,可以支持SpringCloud2.0版本。
下面来讲解下SpringCloud2.0集成LCN框架的步骤:
1.添加maven依赖
<dependency> <groupId>com.codingapi</groupId> <artifactId>transaction-springcloud</artifactId> <version>4.1.2</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>*</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.codingapi</groupId> <artifactId>tx-plugins-db</artifactId> <version>4.1.2</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>*</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </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协调者服务集群原理:
- 首先通过nginx配置多个tm协调者负载均衡配置,然后 LCN客户端启动项目的时候访问Nginx负载均衡地址获取LCN协议通讯IP地址和端口号,并且对该连接保持长连接。
- 因为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/