Browse Source

:sparkles: 添加新特性。 扩展LCN ,支持分布式事务

冷冷 7 years ago
parent
commit
7bd84378b2
100 changed files with 16183 additions and 0 deletions
  1. 16 0
      pigx-common/pigx-common-core/src/main/resources/banner.txt
  2. 30 0
      pigx-common/pigx-common-transaction/pom.xml
  3. 6 0
      pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/pack-info.md
  4. 111 0
      pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/ribbon/loadbalancer/LcnLoadBalancerRule.java
  5. 51 0
      pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/ribbon/loadbalancer/LcnNoOpLoadBalancerProxy.java
  6. 52 0
      pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/ribbon/loadbalancer/LcnRibbonConfiguration.java
  7. 59 0
      pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/ribbon/loadbalancer/LcnZoneAwareLoadBalancerProxy.java
  8. 38 0
      pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/tx/RequestInterceptorConfiguration.java
  9. 38 0
      pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/tx/TransactionConfiguration.java
  10. 49 0
      pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/tx/springcloud/feign/TransactionRestTemplateInterceptor.java
  11. 50 0
      pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/tx/springcloud/http/TransactionHttpRequestInterceptor.java
  12. 68 0
      pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/tx/springcloud/interceptor/TransactionAspect.java
  13. 53 0
      pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/tx/springcloud/interceptor/TxManagerInterceptor.java
  14. 52 0
      pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/tx/springcloud/listener/ServerListener.java
  15. 98 0
      pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/tx/springcloud/service/impl/ModelNameServiceImpl.java
  16. 1 0
      pigx-common/pigx-common-transaction/src/main/resources/META-INF/spring.factories
  17. 1 0
      pigx-common/pom.xml
  18. 16 0
      pigx-config/src/main/resources/banner.txt
  19. 24 0
      pigx-config/src/main/resources/config/pigx-tx-manager-dev.yml
  20. 16 0
      pigx-eureka/src/main/resources/banner.txt
  21. 83 0
      pigx-visual/pigx-tx-manager/pom.xml
  22. 34 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/PigxTxManagerApplication.java
  23. 95 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/api/controller/AdminController.java
  24. 72 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/api/controller/TxManagerController.java
  25. 49 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/api/service/ApiAdminService.java
  26. 32 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/api/service/ApiModelService.java
  27. 81 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/api/service/ApiTxManagerService.java
  28. 90 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/api/service/impl/ApiAdminServiceImpl.java
  29. 40 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/api/service/impl/ApiModelServiceImpl.java
  30. 85 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/api/service/impl/ApiTxManagerServiceImpl.java
  31. 46 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/compensate/dao/CompensateDao.java
  32. 127 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/compensate/dao/impl/CompensateDaoImpl.java
  33. 155 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/compensate/model/TransactionCompensateMsg.java
  34. 104 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/compensate/model/TxModel.java
  35. 52 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/compensate/service/CompensateService.java
  36. 351 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/compensate/service/impl/CompensateServiceImpl.java
  37. 109 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/config/ConfigReader.java
  38. 57 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/config/CorsConfig.java
  39. 41 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/config/RestConfig.java
  40. 32 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/framework/utils/Constants.java
  41. 120 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/framework/utils/SocketManager.java
  42. 53 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/framework/utils/SocketUtils.java
  43. 52 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/listener/ApplicationStartListener.java
  44. 55 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/listener/ServerListener.java
  45. 29 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/listener/service/InitService.java
  46. 54 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/listener/service/impl/InitServiceImpl.java
  47. 88 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/manager/ModelInfoManager.java
  48. 35 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/manager/service/LoadBalanceService.java
  49. 33 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/manager/service/MicroService.java
  50. 32 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/manager/service/TxManagerSenderService.java
  51. 102 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/manager/service/TxManagerService.java
  52. 71 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/manager/service/impl/LoadBalanceServiceImpl.java
  53. 141 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/manager/service/impl/MicroServiceImpl.java
  54. 335 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/manager/service/impl/TxManagerSenderServiceImpl.java
  55. 226 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/manager/service/impl/TxManagerServiceImpl.java
  56. 89 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/model/ChannelSender.java
  57. 56 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/model/LoadBalanceInfo.java
  58. 65 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/model/ModelInfo.java
  59. 45 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/model/ModelName.java
  60. 86 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/model/TxServer.java
  61. 187 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/model/TxState.java
  62. 140 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/handler/TxCoreServerHandler.java
  63. 199 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/model/TxGroup.java
  64. 191 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/model/TxInfo.java
  65. 30 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/IActionService.java
  66. 30 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/NettyServerService.java
  67. 27 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/NettyService.java
  68. 56 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/ActionATGServiceImpl.java
  69. 51 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/ActionCGServiceImpl.java
  70. 47 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/ActionCKGServiceImpl.java
  71. 31 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/ActionCServiceImpl.java
  72. 44 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/ActionCTGServiceImpl.java
  73. 53 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/ActionGLBServiceImpl.java
  74. 41 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/ActionHServiceImpl.java
  75. 54 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/ActionPLBServiceImpl.java
  76. 45 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/ActionRGServiceImpl.java
  77. 31 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/ActionTServiceImpl.java
  78. 56 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/ActionUMIServiceImpl.java
  79. 45 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/BaseSignalTaskService.java
  80. 120 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/NettyServerServiceImpl.java
  81. 39 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/NettyServiceImpl.java
  82. 6 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/pack-info.md
  83. 52 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/redis/RedisServerService.java
  84. 132 0
      pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/redis/impl/RedisServerServiceImpl.java
  85. 24 0
      pigx-visual/pigx-tx-manager/src/main/resources/bootstrap.yml
  86. 139 0
      pigx-visual/pigx-tx-manager/src/main/resources/static/index.html
  87. 192 0
      pigx-visual/pigx-tx-manager/src/main/resources/static/log.html
  88. 65 0
      pigx-visual/pigx-tx-manager/src/main/resources/static/model.html
  89. 650 0
      pigx-visual/pigx-tx-manager/src/main/resources/static/static/bootstrap/css/bootstrap-theme.css
  90. 20 0
      pigx-visual/pigx-tx-manager/src/main/resources/static/static/bootstrap/css/bootstrap-theme.css.map
  91. 6 0
      pigx-visual/pigx-tx-manager/src/main/resources/static/static/bootstrap/css/bootstrap-theme.min.css
  92. 17 0
      pigx-visual/pigx-tx-manager/src/main/resources/static/static/bootstrap/css/bootstrap-theme.min.css.map
  93. 8198 0
      pigx-visual/pigx-tx-manager/src/main/resources/static/static/bootstrap/css/bootstrap.css
  94. 142 0
      pigx-visual/pigx-tx-manager/src/main/resources/static/static/bootstrap/css/bootstrap.css.map
  95. 6 0
      pigx-visual/pigx-tx-manager/src/main/resources/static/static/bootstrap/css/bootstrap.min.css
  96. 143 0
      pigx-visual/pigx-tx-manager/src/main/resources/static/static/bootstrap/css/bootstrap.min.css.map
  97. BIN
      pigx-visual/pigx-tx-manager/src/main/resources/static/static/bootstrap/fonts/glyphicons-halflings-regular.eot
  98. 543 0
      pigx-visual/pigx-tx-manager/src/main/resources/static/static/bootstrap/fonts/glyphicons-halflings-regular.svg
  99. BIN
      pigx-visual/pigx-tx-manager/src/main/resources/static/static/bootstrap/fonts/glyphicons-halflings-regular.ttf
  100. 0 0
      pigx-visual/pigx-tx-manager/src/main/resources/static/static/bootstrap/fonts/glyphicons-halflings-regular.woff

+ 16 - 0
pigx-common/pigx-common-core/src/main/resources/banner.txt

@@ -0,0 +1,16 @@
+${AnsiColor.BRIGHT_YELLOW}
+
+          :::::::::       :::::::::::       ::::::::       :::    :::
+         :+:    :+:          :+:          :+:    :+:      :+:    :+:
+        +:+    +:+          +:+          +:+              +:+  +:+
+       +#++:++#+           +#+          :#:               +#++:+
+      +#+                 +#+          +#+   +#+#       +#+  +#+
+     #+#                 #+#          #+#    #+#      #+#    #+#
+    ###             ###########       ########       ###    ###
+
+                       www.pig4cloud.com
+
+                  Pig Microservice Architecture
+
+
+

+ 30 - 0
pigx-common/pigx-common-transaction/pom.xml

@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>com.pig4cloud</groupId>
+		<artifactId>pigx-common</artifactId>
+		<version>${pigx.version}</version>
+	</parent>
+
+	<artifactId>pigx-common-transaction</artifactId>
+	<version>${pigx.version}</version>
+	<packaging>jar</packaging>
+	<name>pigx-common-transaction</name>
+	<description>pigx lcn transaction</description>
+
+	<dependencies>
+		<!--lcn 模块端控制依赖-->
+		<dependency>
+			<groupId>com.codingapi</groupId>
+			<artifactId>tx-client</artifactId>
+			<version>${lcn.version}</version>
+		</dependency>
+		<!--feign 依赖-->
+		<dependency>
+			<groupId>org.springframework.cloud</groupId>
+			<artifactId>spring-cloud-starter-openfeign</artifactId>
+		</dependency>
+	</dependencies>
+</project>

+ 6 - 0
pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/pack-info.md

@@ -0,0 +1,6 @@
+由于LCN 暂未发布适配 2.0 版本  
+当前包是根据TCN transaction-springcloud 模块修改而来  
+解决LCN 不兼容 Spring Cloud Finchley 问题
+
+关于LCN  
+https://github.com/codingapi/tx-lcn

+ 111 - 0
pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/ribbon/loadbalancer/LcnLoadBalancerRule.java

@@ -0,0 +1,111 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.common.transaction.ribbon.loadbalancer;
+
+
+import com.codingapi.tx.aop.bean.TxTransactionLocal;
+import com.lorne.core.framework.utils.encode.MD5Util;
+import com.netflix.loadbalancer.Server;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
+
+import java.util.List;
+
+/**
+ * created by foxdd 2017-12-05
+ *
+ * @author LCN
+ * @since 4.1.0
+ */
+@Slf4j
+public class LcnLoadBalancerRule {
+
+	public Server proxy(List<Server> servers, Server server) {
+
+		TxTransactionLocal txTransactionLocal = TxTransactionLocal.current();
+		if (txTransactionLocal == null) {
+			return server;
+		}
+
+		try {
+			log.debug("LCNBalanceProxy - > start");
+
+			String groupId = txTransactionLocal.getGroupId();
+
+			//取出组件的appName
+			String appName = server.getMetaInfo().getAppName();
+
+
+			String key = MD5Util.md5((groupId + "_" + appName).getBytes());
+
+			//如果只有一个可调用模块,则用当前的,且需要将数据记录到redis中
+			if (servers.size() == 1) {
+				putServer(key, txTransactionLocal, server);
+				log.debug("LCNBalanceProxy -> only one server available");
+				return server;
+			}
+
+			Server oldServer = getServer(txTransactionLocal, servers, key);
+			if (oldServer != null) {
+				log.debug("LCNBalanceProxy - > load old server ");
+				return server;
+			}
+
+			putServer(key, txTransactionLocal, server);
+			log.debug("LCNBalanceProxy - > load new server ");
+
+			return server;
+		} finally {
+			log.debug("LCNBalanceProxy - > end");
+		}
+	}
+
+
+	private void putServer(String key, TxTransactionLocal txTransactionLocal, Server server) {
+		String serviceName = server.getMetaInfo().getAppName();
+		String address = server.getHostPort();
+
+		String md5 = MD5Util.md5((address + serviceName).getBytes());
+
+		log.debug("putServer->address->" + address + ",md5-->" + md5);
+
+		txTransactionLocal.putLoadBalance(key, md5);
+	}
+
+
+	private Server getServer(TxTransactionLocal txTransactionLocal, List<Server> servers, String key) {
+		String val = txTransactionLocal.getLoadBalance(key);
+		if (StringUtils.isEmpty(val)) {
+			return null;
+		}
+		for (Server server : servers) {
+			String serviceName = server.getMetaInfo().getAppName();
+			String address = server.getHostPort();
+
+			String md5 = MD5Util.md5((address + serviceName).getBytes());
+
+			log.debug("getServer->address->" + address + ",md5-->" + md5);
+
+			if (val.equals(md5)) {
+				return server;
+			}
+		}
+		return null;
+	}
+
+}

+ 51 - 0
pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/ribbon/loadbalancer/LcnNoOpLoadBalancerProxy.java

@@ -0,0 +1,51 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.common.transaction.ribbon.loadbalancer;
+
+import com.netflix.loadbalancer.NoOpLoadBalancer;
+import com.netflix.loadbalancer.Server;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * created by foxdd 2017-12-05
+ *
+ * @author LCN
+ * @since 4.1.0
+ */
+@Slf4j
+public class LcnNoOpLoadBalancerProxy extends NoOpLoadBalancer {
+
+	private LcnLoadBalancerRule lcnLoadBalancerRule = new LcnLoadBalancerRule();
+
+	public LcnNoOpLoadBalancerProxy() {
+		super();
+	}
+
+	@Override
+	public Server chooseServer(Object key) {
+		log.debug("enter chooseServer method, key:" + key);
+
+		List<Server> serverList = new ArrayList<Server>();
+		return lcnLoadBalancerRule.proxy(serverList, super.chooseServer(key));
+
+	}
+
+}

+ 52 - 0
pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/ribbon/loadbalancer/LcnRibbonConfiguration.java

@@ -0,0 +1,52 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.common.transaction.ribbon.loadbalancer;
+
+import com.netflix.client.config.IClientConfig;
+import com.netflix.loadbalancer.*;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author LCN
+ * @since 4.1.0
+ */
+@Configuration
+public class LcnRibbonConfiguration {
+
+	/**
+	 * 为ribbon的loadbalancer做代理,相比于重写IRULE,重写loadbalancer更有利于用户自选LB算法,而且有默认LB算法可用
+	 *
+	 * @param config
+	 * @param serverList
+	 * @param serverListFilter
+	 * @param rule
+	 * @param ping
+	 * @param serverListUpdater
+	 * @return
+	 */
+	@Bean
+	public ILoadBalancer ribbonLoadBalancer(IClientConfig config,
+											ServerList<Server> serverList, ServerListFilter<Server> serverListFilter,
+											IRule rule, IPing ping, ServerListUpdater serverListUpdater) {
+		return new LcnZoneAwareLoadBalancerProxy(config, rule, ping, serverList,
+			serverListFilter, serverListUpdater);
+	}
+
+
+}

+ 59 - 0
pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/ribbon/loadbalancer/LcnZoneAwareLoadBalancerProxy.java

@@ -0,0 +1,59 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.common.transaction.ribbon.loadbalancer;
+
+import com.netflix.client.config.IClientConfig;
+import com.netflix.loadbalancer.*;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.List;
+
+/**
+ * created by foxdd 2017-12-05
+ *
+ * @author LCN
+ * @since 4.1.0
+ */
+@Slf4j
+public class LcnZoneAwareLoadBalancerProxy extends ZoneAwareLoadBalancer<Server> {
+
+	LcnLoadBalancerRule lcnLoadBalancerRule = new LcnLoadBalancerRule();
+
+	public LcnZoneAwareLoadBalancerProxy(IClientConfig clientConfig, IRule rule,
+										 IPing ping, ServerList<Server> serverList, ServerListFilter<Server> filter,
+										 ServerListUpdater serverListUpdater) {
+		super(clientConfig, rule, ping, serverList, filter, serverListUpdater);
+	}
+
+	@Override
+	public Server chooseServer(Object key) {
+		log.info("enter chooseServer method, key:" + key);
+		//利用Dynamic负载类中的方法,可以在运行时更新服务实例清单
+		List<Server> serverList;
+		//获取处理之后的serverlist
+		serverList = super.getServerListImpl().getUpdatedListOfServers();
+		//获取过滤之后的serverlist
+		serverList = super.getFilter().getFilteredListOfServers(serverList);
+		if (null == serverList || serverList.isEmpty()) {
+			return super.chooseServer(key);
+		}
+		return lcnLoadBalancerRule.proxy(serverList, super.chooseServer(key));
+
+	}
+
+}

+ 38 - 0
pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/tx/RequestInterceptorConfiguration.java

@@ -0,0 +1,38 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.common.transaction.tx;
+
+import com.pig4cloud.pigx.common.transaction.tx.springcloud.feign.TransactionRestTemplateInterceptor;
+import feign.RequestInterceptor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * create by lorne on 2018/1/18
+ *
+ * @author LCN
+ * @since 4.1.0
+ */
+@Configuration
+public class RequestInterceptorConfiguration {
+
+	@Bean
+	public RequestInterceptor requestInterceptor() {
+		return new TransactionRestTemplateInterceptor();
+	}
+}

+ 38 - 0
pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/tx/TransactionConfiguration.java

@@ -0,0 +1,38 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.common.transaction.tx;
+
+import com.pig4cloud.pigx.common.transaction.ribbon.loadbalancer.LcnRibbonConfiguration;
+import org.springframework.cloud.netflix.ribbon.RibbonClients;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * Created by lorne on 2017/6/26.
+ *
+ * @author LCN
+ * @since 4.1.0
+ */
+
+@Configuration
+@ComponentScan
+@RibbonClients(defaultConfiguration = LcnRibbonConfiguration.class)
+public class TransactionConfiguration {
+
+
+}

+ 49 - 0
pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/tx/springcloud/feign/TransactionRestTemplateInterceptor.java

@@ -0,0 +1,49 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.common.transaction.tx.springcloud.feign;
+
+import com.codingapi.tx.aop.bean.TxTransactionLocal;
+import feign.RequestInterceptor;
+import feign.RequestTemplate;
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Created by lorne on 2017/6/26.
+ *
+ * @author LCN
+ * @since 4.1.0
+ */
+@Slf4j
+public class TransactionRestTemplateInterceptor implements RequestInterceptor {
+
+	@Override
+	public void apply(RequestTemplate requestTemplate) {
+
+		TxTransactionLocal txTransactionLocal = TxTransactionLocal.current();
+		String groupId = txTransactionLocal == null ? null : txTransactionLocal.getGroupId();
+
+		log.info("LCN-SpringCloud TxGroup info -> groupId:" + groupId);
+
+		if (txTransactionLocal != null) {
+			requestTemplate.header("tx-group", groupId);
+		}
+	}
+
+}

+ 50 - 0
pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/tx/springcloud/http/TransactionHttpRequestInterceptor.java

@@ -0,0 +1,50 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.common.transaction.tx.springcloud.http;
+
+import com.codingapi.tx.aop.bean.TxTransactionLocal;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.http.HttpRequest;
+import org.springframework.http.client.ClientHttpRequestExecution;
+import org.springframework.http.client.ClientHttpRequestInterceptor;
+import org.springframework.http.client.ClientHttpResponse;
+
+import java.io.IOException;
+
+/**
+ * Created by lorne on 2017/7/3.
+ *
+ * @author LCN
+ * @since 4.1.0
+ */
+@Slf4j
+public class TransactionHttpRequestInterceptor implements ClientHttpRequestInterceptor {
+	@Override
+	public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
+
+		TxTransactionLocal txTransactionLocal = TxTransactionLocal.current();
+		String groupId = txTransactionLocal == null ? null : txTransactionLocal.getGroupId();
+
+		log.info("LCN-SpringCloud TxGroup info -> groupId:" + groupId);
+
+		if (txTransactionLocal != null) {
+			request.getHeaders().add("tx-group", groupId);
+		}
+		return execution.execute(request, body);
+	}
+}

+ 68 - 0
pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/tx/springcloud/interceptor/TransactionAspect.java

@@ -0,0 +1,68 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.common.transaction.tx.springcloud.interceptor;
+
+import lombok.extern.slf4j.Slf4j;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.Ordered;
+import org.springframework.stereotype.Component;
+
+/**
+ * LCN 事务拦截器
+ * create by lorne on 2018/1/5
+ *
+ * @author LCN
+ * @since 4.1.0
+ */
+
+@Slf4j
+@Aspect
+@Component
+public class TransactionAspect implements Ordered {
+
+	@Autowired
+	private TxManagerInterceptor txManagerInterceptor;
+
+
+	@Around("@annotation(com.codingapi.tx.annotation.TxTransaction)")
+	public Object transactionRunning(ProceedingJoinPoint point) throws Throwable {
+		log.debug("annotation-TransactionRunning-start---->");
+		Object obj = txManagerInterceptor.around(point);
+		log.debug("annotation-TransactionRunning-end---->");
+		return obj;
+	}
+
+	@Around("this(com.codingapi.tx.annotation.ITxTransaction) && execution( * *(..))")
+	public Object around(ProceedingJoinPoint point) throws Throwable {
+		log.debug("interface-ITransactionRunning-start---->");
+		Object obj = txManagerInterceptor.around(point);
+		log.debug("interface-ITransactionRunning-end---->");
+		return obj;
+	}
+
+
+	@Override
+	public int getOrder() {
+		return HIGHEST_PRECEDENCE;
+	}
+
+
+}

+ 53 - 0
pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/tx/springcloud/interceptor/TxManagerInterceptor.java

@@ -0,0 +1,53 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.common.transaction.tx.springcloud.interceptor;
+
+import com.codingapi.tx.aop.service.AspectBeforeService;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Created by lorne on 2017/6/7.
+ *
+ * @author LCN
+ * @since 4.1.0
+ */
+
+@Component
+public class TxManagerInterceptor {
+
+	@Autowired
+	private AspectBeforeService aspectBeforeService;
+
+	public Object around(ProceedingJoinPoint point) throws Throwable {
+		String groupId = null;
+		try {
+			RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
+			HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
+			groupId = request.getHeader("tx-group");
+		} catch (Exception e) {
+		}
+		return aspectBeforeService.around(groupId, point);
+	}
+}

+ 52 - 0
pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/tx/springcloud/listener/ServerListener.java

@@ -0,0 +1,52 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.common.transaction.tx.springcloud.listener;
+
+import com.codingapi.tx.listener.service.InitService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.web.context.WebServerInitializedEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author LCN
+ * @since 4.1.0
+ */
+@Component
+public class ServerListener implements ApplicationListener<WebServerInitializedEvent> {
+
+	private Logger logger = LoggerFactory.getLogger(ServerListener.class);
+
+	private int serverPort;
+
+	@Autowired
+	private InitService initService;
+
+	@Override
+	public void onApplicationEvent(WebServerInitializedEvent event) {
+		logger.info("onApplicationEvent -> onApplicationEvent. " + event.getWebServer());
+		this.serverPort = event.getWebServer().getPort();
+		initService.start();
+	}
+
+	public int getPort() {
+		return this.serverPort;
+	}
+}

+ 98 - 0
pigx-common/pigx-common-transaction/src/main/java/com/pig4cloud/pigx/common/transaction/tx/springcloud/service/impl/ModelNameServiceImpl.java

@@ -0,0 +1,98 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.common.transaction.tx.springcloud.service.impl;
+
+import com.codingapi.tx.listener.service.ModelNameService;
+import com.lorne.core.framework.utils.encode.MD5Util;
+import com.pig4cloud.pigx.common.transaction.tx.springcloud.listener.ServerListener;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.stereotype.Service;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * Created by lorne on 2017/7/12.
+ *
+ * @author LCN
+ * @since 4.1.0
+ */
+@Service
+@Configuration
+public class ModelNameServiceImpl implements ModelNameService {
+
+	@Value("${spring.application.name}")
+	private String modelName;
+
+	@Autowired
+	private ServerListener serverListener;
+
+
+	private String host = null;
+
+	@Override
+	public String getModelName() {
+		return modelName;
+	}
+
+	private String getIp() {
+		if (host == null) {
+			try {
+				host = InetAddress.getLocalHost().getHostAddress();
+			} catch (UnknownHostException e) {
+				e.printStackTrace();
+			}
+		}
+		return host;
+	}
+
+	private int getPort() {
+		int port = serverListener.getPort();
+		int count = 0;
+		while (port == 0) {
+			try {
+				Thread.sleep(10);
+			} catch (InterruptedException e) {
+				e.printStackTrace();
+			}
+			port = serverListener.getPort();
+			count++;
+
+			if (count == 2000) {
+				throw new RuntimeException("get server port error.");
+			}
+		}
+
+		return port;
+	}
+
+	@Override
+	public String getUniqueKey() {
+		String address = getIp() + getPort();
+		return MD5Util.md5(address.getBytes());
+	}
+
+
+	@Override
+	public String getIpAddress() {
+		String address = getIp() + ":" + getPort();
+		return address;
+	}
+}

+ 1 - 0
pigx-common/pigx-common-transaction/src/main/resources/META-INF/spring.factories

@@ -0,0 +1 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.pig4cloud.pigx.common.transaction.tx.TransactionConfiguration

+ 1 - 0
pigx-common/pom.xml

@@ -39,5 +39,6 @@
 		<module>pigx-common-log</module>
 		<module>pigx-common-security</module>
 		<module>pigx-common-swagger</module>
+		<module>pigx-common-transaction</module>
 	</modules>
 </project>

+ 16 - 0
pigx-config/src/main/resources/banner.txt

@@ -0,0 +1,16 @@
+${AnsiColor.BRIGHT_YELLOW}
+
+          :::::::::       :::::::::::       ::::::::       :::    :::
+         :+:    :+:          :+:          :+:    :+:      :+:    :+:
+        +:+    +:+          +:+          +:+              +:+  +:+
+       +#++:++#+           +#+          :#:               +#++:+
+      +#+                 +#+          +#+   +#+#       +#+  +#+
+     #+#                 #+#          #+#    #+#      #+#    #+#
+    ###             ###########       ########       ###    ###
+
+                       www.pig4cloud.com
+
+                  Pig Microservice Architecture
+
+
+

+ 24 - 0
pigx-config/src/main/resources/config/pigx-tx-manager-dev.yml

@@ -0,0 +1,24 @@
+# 页面配置
+spring:
+  mvc:
+    static-path-pattern: /**
+  resources:
+    static-locations: classpath:/static/
+
+
+# LCN 配置
+tm:
+  transaction:
+    netty:
+      delaytime: 5   # 客户端链接最大通讯时间 (秒)
+      hearttime: 15  # 客户端心跳时间   (秒)
+  redis:
+    savemaxtime: 30  # redis 保存时间  (秒)
+  socket:
+    port: 9998       # 通讯端口
+    maxconnection: 1000  #最大链接数
+  compensate:
+    auto: false   #是否自动补偿
+    notifyUrl: http://ip:port/path #补偿结果通知(配消息总线里面)
+    tryTime: 30     # z再次重试时间间隔
+    maxWaitTime: 5000   # 请求超时的最大时间 (毫秒)

+ 16 - 0
pigx-eureka/src/main/resources/banner.txt

@@ -0,0 +1,16 @@
+${AnsiColor.BRIGHT_YELLOW}
+
+          :::::::::       :::::::::::       ::::::::       :::    :::
+         :+:    :+:          :+:          :+:    :+:      :+:    :+:
+        +:+    +:+          +:+          +:+              +:+  +:+
+       +#++:++#+           +#+          :#:               +#++:+
+      +#+                 +#+          +#+   +#+#       +#+  +#+
+     #+#                 #+#          #+#    #+#      #+#    #+#
+    ###             ###########       ########       ###    ###
+
+                       www.pig4cloud.com
+
+                  Pig Microservice Architecture
+
+
+

+ 83 - 0
pigx-visual/pigx-tx-manager/pom.xml

@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>com.pig4cloud</groupId>
+		<artifactId>pigx-visual</artifactId>
+		<version>${pigx.version}</version>
+	</parent>
+
+	<artifactId>pigx-tx-manager</artifactId>
+	<version>${pigx.version}</version>
+	<packaging>jar</packaging>
+
+	<name>pigx-tx-manager</name>
+	<description>pigx lcn tx manager</description>
+
+	<dependencies>
+		<!--web 模块-->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-web</artifactId>
+			<exclusions>
+				<!--排除tomcat依赖-->
+				<exclusion>
+					<artifactId>spring-boot-starter-tomcat</artifactId>
+					<groupId>org.springframework.boot</groupId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+		<!--undertow容器-->
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-undertow</artifactId>
+		</dependency>
+		<!--配置中心客户端-->
+		<dependency>
+			<groupId>org.springframework.cloud</groupId>
+			<artifactId>spring-cloud-starter-config</artifactId>
+		</dependency>
+		<!--LCN-->
+		<dependency>
+			<groupId>com.github.1991wangliang</groupId>
+			<artifactId>lorne_core</artifactId>
+			<version>1.0.0</version>
+			<exclusions>
+				<exclusion>
+					<groupId>org.slf4j</groupId>
+					<artifactId>*</artifactId>
+				</exclusion>
+			</exclusions>
+		</dependency>
+		<!--netty-->
+		<dependency>
+			<groupId>io.netty</groupId>
+			<artifactId>netty-all</artifactId>
+			<version>4.1.12.Final</version>
+		</dependency>
+		<!--eureka-->
+		<dependency>
+			<groupId>org.springframework.cloud</groupId>
+			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
+		</dependency>
+		<!--工具类核心包-->
+		<dependency>
+			<groupId>com.pig4cloud</groupId>
+			<artifactId>pigx-common-core</artifactId>
+			<version>${pigx.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>javax.servlet</groupId>
+			<artifactId>javax.servlet-api</artifactId>
+		</dependency>
+	</dependencies>
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.springframework.boot</groupId>
+				<artifactId>spring-boot-maven-plugin</artifactId>
+			</plugin>
+		</plugins>
+	</build>
+</project>

+ 34 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/PigxTxManagerApplication.java

@@ -0,0 +1,34 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+
+
+@SpringBootApplication
+@EnableDiscoveryClient
+public class PigxTxManagerApplication {
+
+
+	public static void main(String[] args) {
+		SpringApplication.run(PigxTxManagerApplication.class, args);
+	}
+
+}

+ 95 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/api/controller/AdminController.java

@@ -0,0 +1,95 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.api.controller;
+
+import com.lorne.core.framework.exception.ServiceException;
+import com.pig4cloud.pigx.manager.api.service.ApiAdminService;
+import com.pig4cloud.pigx.manager.api.service.ApiModelService;
+import com.pig4cloud.pigx.manager.compensate.model.TxModel;
+import com.pig4cloud.pigx.manager.model.ModelInfo;
+import com.pig4cloud.pigx.manager.model.ModelName;
+import com.pig4cloud.pigx.manager.model.TxState;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/**
+ * Created by lorne on 2017/7/1.
+ */
+@RestController
+@RequestMapping("/admin")
+public class AdminController {
+
+	@Autowired
+	private ApiAdminService apiAdminService;
+
+	@Autowired
+	private ApiModelService apiModelService;
+
+
+	@RequestMapping(value = "/onlines", method = RequestMethod.GET)
+	public List<ModelInfo> onlines() {
+		return apiModelService.onlines();
+	}
+
+
+	@RequestMapping(value = "/setting", method = RequestMethod.GET)
+	public TxState setting() {
+		return apiAdminService.getState();
+	}
+
+	@RequestMapping(value = "/json", method = RequestMethod.GET)
+	public String json() {
+		return apiAdminService.loadNotifyJson();
+	}
+
+	@RequestMapping(value = "/modelList", method = RequestMethod.GET)
+	public List<ModelName> modelList() {
+		return apiAdminService.modelList();
+	}
+
+	@RequestMapping(value = "/modelTimes", method = RequestMethod.GET)
+	public List<String> modelTimes(@RequestParam("model") String model) {
+		return apiAdminService.modelTimes(model);
+	}
+
+
+	@RequestMapping(value = "/modelInfos", method = RequestMethod.GET)
+	public List<TxModel> modelInfos(@RequestParam("path") String path) {
+		return apiAdminService.modelInfos(path);
+	}
+
+	@RequestMapping(value = "/compensate", method = RequestMethod.GET)
+	public boolean compensate(@RequestParam("path") String path) throws ServiceException {
+		return apiAdminService.compensate(path);
+	}
+
+	@RequestMapping(value = "/delCompensate", method = RequestMethod.GET)
+	public boolean delCompensate(@RequestParam("path") String path) throws ServiceException {
+		return apiAdminService.delCompensate(path);
+	}
+
+	@RequestMapping(value = "/hasCompensate", method = RequestMethod.GET)
+	public boolean hasCompensate() throws ServiceException {
+		return apiAdminService.hasCompensate();
+	}
+}

+ 72 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/api/controller/TxManagerController.java

@@ -0,0 +1,72 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.api.controller;
+
+import com.pig4cloud.pigx.manager.api.service.ApiTxManagerService;
+import com.pig4cloud.pigx.manager.model.TxServer;
+import com.pig4cloud.pigx.manager.model.TxState;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * Created by lorne on 2017/7/1.
+ */
+@RestController
+@RequestMapping("/tx/manager")
+public class TxManagerController {
+
+	@Autowired
+	private ApiTxManagerService apiTxManagerService;
+
+
+	@RequestMapping("/getServer")
+	public TxServer getServer() {
+		return apiTxManagerService.getServer();
+	}
+
+
+	@RequestMapping("/cleanNotifyTransaction")
+	public int cleanNotifyTransaction(@RequestParam("groupId") String groupId, @RequestParam("taskId") String taskId) {
+		return apiTxManagerService.cleanNotifyTransaction(groupId, taskId);
+	}
+
+
+	@RequestMapping("/sendMsg")
+	public String sendMsg(@RequestParam("msg") String msg, @RequestParam("model") String model) {
+		return apiTxManagerService.sendMsg(model, msg);
+	}
+
+
+	@RequestMapping("/sendCompensateMsg")
+	public boolean sendCompensateMsg(@RequestParam("model") String model, @RequestParam("uniqueKey") String uniqueKey,
+									 @RequestParam("currentTime") long currentTime,
+									 @RequestParam("groupId") String groupId, @RequestParam("className") String className,
+									 @RequestParam("time") int time, @RequestParam("data") String data,
+									 @RequestParam("methodStr") String methodStr, @RequestParam("address") String address,
+									 @RequestParam("startError") int startError) {
+		return apiTxManagerService.sendCompensateMsg(currentTime, groupId, model, address, uniqueKey, className, methodStr, data, time, startError);
+	}
+
+
+	@RequestMapping("/state")
+	public TxState state() {
+		return apiTxManagerService.getState();
+	}
+}

+ 49 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/api/service/ApiAdminService.java

@@ -0,0 +1,49 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.api.service;
+
+import com.lorne.core.framework.exception.ServiceException;
+import com.pig4cloud.pigx.manager.compensate.model.TxModel;
+import com.pig4cloud.pigx.manager.model.ModelName;
+import com.pig4cloud.pigx.manager.model.TxState;
+
+import java.util.List;
+
+/**
+ * create by lorne on 2017/11/12
+ */
+public interface ApiAdminService {
+
+	TxState getState();
+
+	String loadNotifyJson();
+
+	List<ModelName> modelList();
+
+
+	List<String> modelTimes(String model);
+
+	List<TxModel> modelInfos(String path);
+
+	boolean compensate(String path) throws ServiceException;
+
+	boolean hasCompensate();
+
+	boolean delCompensate(String path);
+
+}

+ 32 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/api/service/ApiModelService.java

@@ -0,0 +1,32 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.api.service;
+
+import com.pig4cloud.pigx.manager.model.ModelInfo;
+
+import java.util.List;
+
+/**
+ * create by lorne on 2017/11/13
+ */
+public interface ApiModelService {
+
+	List<ModelInfo> onlines();
+
+
+}

+ 81 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/api/service/ApiTxManagerService.java

@@ -0,0 +1,81 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.api.service;
+
+import com.pig4cloud.pigx.manager.model.TxServer;
+import com.pig4cloud.pigx.manager.model.TxState;
+
+/**
+ * Created by lorne on 2017/7/1.
+ */
+public interface ApiTxManagerService {
+
+
+	/**
+	 * 获取本服务的信息
+	 *
+	 * @return 服务信息
+	 */
+	TxServer getServer();
+
+
+	/**
+	 * 给 tx模块发送指令
+	 *
+	 * @param model 模块名称
+	 * @param msg   指令
+	 * @return 指令返回结果
+	 */
+	String sendMsg(String model, String msg);
+
+	/**
+	 * 检查并清理事务数据
+	 *
+	 * @param groupId 事务组Id
+	 * @param taskId  任务Id
+	 * @param isGroup 是否合并事务
+	 * @return 事务状态
+	 */
+	int cleanNotifyTransaction(String groupId, String taskId);
+
+
+	/**
+	 * 保存事务补偿日志信息
+	 *
+	 * @param currentTime 时间
+	 * @param groupId     事务组id
+	 * @param model       模块名称
+	 * @param address     模块地址
+	 * @param uniqueKey   唯一标示
+	 * @param className   事务启动类
+	 * @param methodStr   事务启动方法
+	 * @param data        切面数据
+	 * @param time        执行时间
+	 * @param startError  启动模块异常
+	 * @return 是否保存成功
+	 */
+	boolean sendCompensateMsg(long currentTime, String groupId, String model, String address, String uniqueKey, String className, String methodStr, String data, int time, int startError);
+
+	/**
+	 * 获取服务器状态
+	 *
+	 * @return 状态
+	 */
+	TxState getState();
+
+}

+ 90 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/api/service/impl/ApiAdminServiceImpl.java

@@ -0,0 +1,90 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.api.service.impl;
+
+
+import com.lorne.core.framework.exception.ServiceException;
+import com.pig4cloud.pigx.manager.api.service.ApiAdminService;
+import com.pig4cloud.pigx.manager.compensate.model.TxModel;
+import com.pig4cloud.pigx.manager.compensate.service.CompensateService;
+import com.pig4cloud.pigx.manager.manager.service.MicroService;
+import com.pig4cloud.pigx.manager.model.ModelName;
+import com.pig4cloud.pigx.manager.model.TxState;
+import com.pig4cloud.pigx.manager.redis.RedisServerService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * create by lorne on 2017/11/12
+ */
+@Service
+public class ApiAdminServiceImpl implements ApiAdminService {
+
+
+	@Autowired
+	private MicroService eurekaService;
+
+	@Autowired
+	private RedisServerService redisServerService;
+
+	@Autowired
+	private CompensateService compensateService;
+
+	@Override
+	public TxState getState() {
+		return eurekaService.getState();
+	}
+
+	@Override
+	public String loadNotifyJson() {
+		return redisServerService.loadNotifyJson();
+	}
+
+	@Override
+	public List<ModelName> modelList() {
+		return compensateService.loadModelList();
+	}
+
+
+	@Override
+	public List<String> modelTimes(String model) {
+		return compensateService.loadCompensateTimes(model);
+	}
+
+	@Override
+	public List<TxModel> modelInfos(String path) {
+		return compensateService.loadCompensateByModelAndTime(path);
+	}
+
+	@Override
+	public boolean compensate(String path) throws ServiceException {
+		return compensateService.executeCompensate(path);
+	}
+
+	@Override
+	public boolean delCompensate(String path) {
+		return compensateService.delCompensate(path);
+	}
+
+	@Override
+	public boolean hasCompensate() {
+		return compensateService.hasCompensate();
+	}
+}

+ 40 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/api/service/impl/ApiModelServiceImpl.java

@@ -0,0 +1,40 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.api.service.impl;
+
+import com.pig4cloud.pigx.manager.api.service.ApiModelService;
+import com.pig4cloud.pigx.manager.manager.ModelInfoManager;
+import com.pig4cloud.pigx.manager.model.ModelInfo;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * create by lorne on 2017/11/13
+ */
+@Service
+public class ApiModelServiceImpl implements ApiModelService {
+
+
+	@Override
+	public List<ModelInfo> onlines() {
+		return ModelInfoManager.getInstance().getOnlines();
+	}
+
+
+}

+ 85 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/api/service/impl/ApiTxManagerServiceImpl.java

@@ -0,0 +1,85 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.api.service.impl;
+
+
+import com.pig4cloud.pigx.manager.api.service.ApiTxManagerService;
+import com.pig4cloud.pigx.manager.compensate.model.TransactionCompensateMsg;
+import com.pig4cloud.pigx.manager.compensate.service.CompensateService;
+import com.pig4cloud.pigx.manager.config.ConfigReader;
+import com.pig4cloud.pigx.manager.manager.service.MicroService;
+import com.pig4cloud.pigx.manager.manager.service.TxManagerSenderService;
+import com.pig4cloud.pigx.manager.manager.service.TxManagerService;
+import com.pig4cloud.pigx.manager.model.TxServer;
+import com.pig4cloud.pigx.manager.model.TxState;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * Created by lorne on 2017/7/1.
+ */
+@Service
+public class ApiTxManagerServiceImpl implements ApiTxManagerService {
+
+
+	@Autowired
+	private TxManagerService managerService;
+
+	@Autowired
+	private MicroService eurekaService;
+
+	@Autowired
+	private CompensateService compensateService;
+
+
+	@Autowired
+	private TxManagerSenderService txManagerSenderService;
+
+	@Autowired
+	private ConfigReader configReader;
+
+
+	@Override
+	public TxServer getServer() {
+		return eurekaService.getServer();
+	}
+
+
+	@Override
+	public int cleanNotifyTransaction(String groupId, String taskId) {
+		return managerService.cleanNotifyTransaction(groupId, taskId);
+	}
+
+
+	@Override
+	public boolean sendCompensateMsg(long currentTime, String groupId, String model, String address, String uniqueKey, String className, String methodStr, String data, int time, int startError) {
+		TransactionCompensateMsg transactionCompensateMsg = new TransactionCompensateMsg(currentTime, groupId, model, address, uniqueKey, className, methodStr, data, time, 0, startError);
+		return compensateService.saveCompensateMsg(transactionCompensateMsg);
+	}
+
+	@Override
+	public String sendMsg(String model, String msg) {
+		return txManagerSenderService.sendMsg(model, msg, configReader.getTransactionNettyDelayTime());
+	}
+
+
+	@Override
+	public TxState getState() {
+		return eurekaService.getState();
+	}
+}

+ 46 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/compensate/dao/CompensateDao.java

@@ -0,0 +1,46 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.compensate.dao;
+
+import com.pig4cloud.pigx.manager.compensate.model.TransactionCompensateMsg;
+
+import java.util.List;
+
+/**
+ * create by lorne on 2017/11/11
+ */
+public interface CompensateDao {
+
+	String saveCompensateMsg(TransactionCompensateMsg transactionCompensateMsg);
+
+	List<String> loadCompensateKeys();
+
+	List<String> loadCompensateTimes(String model);
+
+	List<String> loadCompensateByModelAndTime(String path);
+
+	String getCompensate(String key);
+
+	String getCompensateByGroupId(String groupId);
+
+	void deleteCompensateByPath(String path);
+
+	void deleteCompensateByKey(String key);
+
+	boolean hasCompensate();
+}

+ 127 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/compensate/dao/impl/CompensateDaoImpl.java

@@ -0,0 +1,127 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.compensate.dao.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.lorne.core.framework.utils.DateUtil;
+import com.pig4cloud.pigx.manager.compensate.dao.CompensateDao;
+import com.pig4cloud.pigx.manager.compensate.model.TransactionCompensateMsg;
+import com.pig4cloud.pigx.manager.config.ConfigReader;
+import com.pig4cloud.pigx.manager.redis.RedisServerService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * create by lorne on 2017/11/11
+ */
+@Service
+public class CompensateDaoImpl implements CompensateDao {
+
+
+	@Autowired
+	private RedisServerService redisServerService;
+
+	@Autowired
+	private ConfigReader configReader;
+
+
+	@Override
+	public String saveCompensateMsg(TransactionCompensateMsg transactionCompensateMsg) {
+
+		String name = String.format("%s%s:%s:%s.json", configReader.getKeyPrefixCompensate(), transactionCompensateMsg.getModel(), DateUtil.getCurrentDateFormat(), transactionCompensateMsg.getGroupId());
+
+		String json = JSON.toJSONString(transactionCompensateMsg);
+
+		redisServerService.saveCompensateMsg(name, json);
+
+		return name;
+	}
+
+
+	@Override
+	public List<String> loadCompensateKeys() {
+		String key = configReader.getKeyPrefixCompensate() + "*";
+		return redisServerService.getKeys(key);
+	}
+
+
+	@Override
+	public boolean hasCompensate() {
+		String key = configReader.getKeyPrefixCompensate() + "*";
+		List<String> keys = redisServerService.getKeys(key);
+		return keys != null && keys.size() > 0;
+	}
+
+	@Override
+	public List<String> loadCompensateTimes(String model) {
+		String key = configReader.getKeyPrefixCompensate() + model + ":*";
+		List<String> keys = redisServerService.getKeys(key);
+		List<String> times = new ArrayList<String>();
+		for (String k : keys) {
+			if (k.length() > 36) {
+				String time = k.substring(k.length() - 24, k.length() - 14);
+				if (!times.contains(time)) {
+					times.add(time);
+				}
+			}
+		}
+		return times;
+	}
+
+
+	@Override
+	public List<String> loadCompensateByModelAndTime(String path) {
+		String key = String.format("%s%s*", configReader.getKeyPrefixCompensate(), path);
+		List<String> keys = redisServerService.getKeys(key);
+		List<String> values = redisServerService.getValuesByKeys(keys);
+		return values;
+	}
+
+	@Override
+	public String getCompensate(String path) {
+		String key = String.format("%s%s.json", configReader.getKeyPrefixCompensate(), path);
+		return redisServerService.getValueByKey(key);
+	}
+
+
+	@Override
+	public void deleteCompensateByPath(String path) {
+		String key = String.format("%s%s.json", configReader.getKeyPrefixCompensate(), path);
+		redisServerService.deleteKey(key);
+	}
+
+
+	@Override
+	public void deleteCompensateByKey(String key) {
+		redisServerService.deleteKey(key);
+	}
+
+	@Override
+	public String getCompensateByGroupId(String groupId) {
+		String key = String.format("%s*%s.json", configReader.getKeyPrefixCompensate(), groupId);
+		List<String> keys = redisServerService.getKeys(key);
+		if (keys != null && keys.size() == 1) {
+			String k = keys.get(0);
+			return redisServerService.getValueByKey(k);
+		}
+		return null;
+	}
+}

+ 155 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/compensate/model/TransactionCompensateMsg.java

@@ -0,0 +1,155 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.compensate.model;
+
+import com.pig4cloud.pigx.manager.netty.model.TxGroup;
+
+/**
+ * create by lorne on 2017/11/11
+ */
+public class TransactionCompensateMsg {
+
+	private long currentTime;
+	private String groupId;
+	private String model;
+	private String address;
+	private String uniqueKey;
+	private String className;
+	private String methodStr;
+	private String data;
+	private int time;
+	private int startError;
+
+	private TxGroup txGroup;
+
+	private int state;
+
+
+	public TransactionCompensateMsg(long currentTime, String groupId, String model, String address,
+									String uniqueKey, String className,
+									String methodStr, String data, int time, int state, int startError) {
+		this.currentTime = currentTime;
+		this.groupId = groupId;
+		this.model = model;
+		this.uniqueKey = uniqueKey;
+		this.className = className;
+		this.methodStr = methodStr;
+		this.data = data;
+		this.time = time;
+		this.address = address;
+		this.state = state;
+		this.startError = startError;
+	}
+
+	public int getStartError() {
+		return startError;
+	}
+
+	public void setStartError(int startError) {
+		this.startError = startError;
+	}
+
+	public int getState() {
+		return state;
+	}
+
+	public void setState(int state) {
+		this.state = state;
+	}
+
+	public long getCurrentTime() {
+		return currentTime;
+	}
+
+	public void setCurrentTime(long currentTime) {
+		this.currentTime = currentTime;
+	}
+
+	public String getAddress() {
+		return address;
+	}
+
+	public void setAddress(String address) {
+		this.address = address;
+	}
+
+	public TxGroup getTxGroup() {
+		return txGroup;
+	}
+
+	public void setTxGroup(TxGroup txGroup) {
+		this.txGroup = txGroup;
+	}
+
+	public String getGroupId() {
+		return groupId;
+	}
+
+	public void setGroupId(String groupId) {
+		this.groupId = groupId;
+	}
+
+	public String getModel() {
+		return model;
+	}
+
+	public void setModel(String model) {
+		this.model = model;
+	}
+
+	public String getUniqueKey() {
+		return uniqueKey;
+	}
+
+	public void setUniqueKey(String uniqueKey) {
+		this.uniqueKey = uniqueKey;
+	}
+
+	public String getClassName() {
+		return className;
+	}
+
+	public void setClassName(String className) {
+		this.className = className;
+	}
+
+
+	public String getMethodStr() {
+		return methodStr;
+	}
+
+	public void setMethodStr(String methodStr) {
+		this.methodStr = methodStr;
+	}
+
+	public String getData() {
+		return data;
+	}
+
+	public void setData(String data) {
+		this.data = data;
+	}
+
+	public int getTime() {
+		return time;
+	}
+
+	public void setTime(int time) {
+		this.time = time;
+	}
+}

+ 104 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/compensate/model/TxModel.java

@@ -0,0 +1,104 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.compensate.model;
+
+/**
+ * create by lorne on 2017/11/12
+ */
+public class TxModel {
+
+	private String time;
+
+	private String className;
+
+	private String method;
+
+	private int executeTime;
+
+	private String base64;
+
+	private int state;
+
+	private long order;
+
+	private String key;
+
+	public String getKey() {
+		return key;
+	}
+
+	public void setKey(String key) {
+		this.key = key;
+	}
+
+	public long getOrder() {
+		return order;
+	}
+
+	public void setOrder(long order) {
+		this.order = order;
+	}
+
+	public String getBase64() {
+		return base64;
+	}
+
+	public void setBase64(String base64) {
+		this.base64 = base64;
+	}
+
+	public String getClassName() {
+		return className;
+	}
+
+	public void setClassName(String className) {
+		this.className = className;
+	}
+
+	public String getMethod() {
+		return method;
+	}
+
+	public void setMethod(String method) {
+		this.method = method;
+	}
+
+	public int getExecuteTime() {
+		return executeTime;
+	}
+
+	public void setExecuteTime(int executeTime) {
+		this.executeTime = executeTime;
+	}
+
+	public String getTime() {
+		return time;
+	}
+
+	public void setTime(String time) {
+		this.time = time;
+	}
+
+	public int getState() {
+		return state;
+	}
+
+	public void setState(int state) {
+		this.state = state;
+	}
+}

+ 52 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/compensate/service/CompensateService.java

@@ -0,0 +1,52 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.compensate.service;
+
+import com.lorne.core.framework.exception.ServiceException;
+import com.pig4cloud.pigx.manager.compensate.model.TransactionCompensateMsg;
+import com.pig4cloud.pigx.manager.compensate.model.TxModel;
+import com.pig4cloud.pigx.manager.model.ModelName;
+import com.pig4cloud.pigx.manager.netty.model.TxGroup;
+
+import java.util.List;
+
+/**
+ * create by lorne on 2017/11/11
+ */
+public interface CompensateService {
+
+	boolean saveCompensateMsg(TransactionCompensateMsg transactionCompensateMsg);
+
+	List<ModelName> loadModelList();
+
+	List<String> loadCompensateTimes(String model);
+
+	List<TxModel> loadCompensateByModelAndTime(String path);
+
+	void autoCompensate(String compensateKey, TransactionCompensateMsg transactionCompensateMsg);
+
+	boolean executeCompensate(String key) throws ServiceException;
+
+	void reloadCompensate(TxGroup txGroup);
+
+	boolean hasCompensate();
+
+	boolean delCompensate(String path);
+
+	TxGroup getCompensateByGroupId(String groupId);
+}

+ 351 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/compensate/service/impl/CompensateServiceImpl.java

@@ -0,0 +1,351 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.compensate.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.google.common.collect.Lists;
+import com.lorne.core.framework.exception.ServiceException;
+import com.lorne.core.framework.utils.DateUtil;
+import com.lorne.core.framework.utils.encode.Base64Utils;
+import com.lorne.core.framework.utils.http.HttpUtils;
+import com.pig4cloud.pigx.manager.compensate.dao.CompensateDao;
+import com.pig4cloud.pigx.manager.compensate.model.TransactionCompensateMsg;
+import com.pig4cloud.pigx.manager.compensate.model.TxModel;
+import com.pig4cloud.pigx.manager.compensate.service.CompensateService;
+import com.pig4cloud.pigx.manager.config.ConfigReader;
+import com.pig4cloud.pigx.manager.manager.ModelInfoManager;
+import com.pig4cloud.pigx.manager.manager.service.TxManagerSenderService;
+import com.pig4cloud.pigx.manager.manager.service.TxManagerService;
+import com.pig4cloud.pigx.manager.model.ModelInfo;
+import com.pig4cloud.pigx.manager.model.ModelName;
+import com.pig4cloud.pigx.manager.netty.model.TxGroup;
+import com.pig4cloud.pigx.manager.netty.model.TxInfo;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.*;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+/**
+ * create by lorne on 2017/11/11
+ */
+@Service
+public class CompensateServiceImpl implements CompensateService {
+
+
+	private Logger logger = LoggerFactory.getLogger(CompensateServiceImpl.class);
+
+	@Autowired
+	private CompensateDao compensateDao;
+
+	@Autowired
+	private ConfigReader configReader;
+
+	@Autowired
+	private TxManagerSenderService managerSenderService;
+
+	@Autowired
+	private TxManagerService managerService;
+
+
+	private Executor threadPool = Executors.newFixedThreadPool(20);
+
+	@Override
+	public boolean saveCompensateMsg(final TransactionCompensateMsg transactionCompensateMsg) {
+
+		TxGroup txGroup = managerService.getTxGroup(transactionCompensateMsg.getGroupId());
+		if (txGroup == null) {
+			//仅发起方异常,其他模块正常
+			txGroup = new TxGroup();
+			txGroup.setNowTime(System.currentTimeMillis());
+			txGroup.setGroupId(transactionCompensateMsg.getGroupId());
+			txGroup.setIsCompensate(1);
+		} else {
+			managerService.deleteTxGroup(txGroup);
+		}
+
+		transactionCompensateMsg.setTxGroup(txGroup);
+
+		final String json = JSON.toJSONString(transactionCompensateMsg);
+
+		logger.info("Compensate->" + json);
+
+		final String compensateKey = compensateDao.saveCompensateMsg(transactionCompensateMsg);
+
+		//调整自动补偿机制,若开启了自动补偿,需要通知业务返回success,方可执行自动补偿
+		threadPool.execute(new Runnable() {
+			@Override
+			public void run() {
+				try {
+					String groupId = transactionCompensateMsg.getGroupId();
+					JSONObject requestJson = new JSONObject();
+					requestJson.put("action", "compensate");
+					requestJson.put("groupId", groupId);
+					requestJson.put("json", json);
+
+					String url = configReader.getCompensateNotifyUrl();
+					logger.error("Compensate Callback Address->" + url);
+					String res = HttpUtils.postJson(url, requestJson.toJSONString());
+					logger.error("Compensate Callback Result->" + res);
+					if (configReader.isCompensateAuto()) {
+						//自动补偿,是否自动执行补偿
+						if (res.contains("success") || res.contains("SUCCESS")) {
+							//自动补偿
+							autoCompensate(compensateKey, transactionCompensateMsg);
+						}
+					}
+				} catch (Exception e) {
+					logger.error("Compensate Callback Fails->" + e.getMessage());
+				}
+			}
+		});
+
+		return StringUtils.isNotEmpty(compensateKey);
+
+
+	}
+
+	@Override
+	public void autoCompensate(final String compensateKey, TransactionCompensateMsg transactionCompensateMsg) {
+		final String json = JSON.toJSONString(transactionCompensateMsg);
+		logger.info("Auto Compensate->" + json);
+		//自动补偿业务执行...
+		final int tryTime = configReader.getCompensateTryTime();
+		boolean autoExecuteRes = false;
+		try {
+			int executeCount = 0;
+			autoExecuteRes = _executeCompensate(json);
+			logger.info("Automatic Compensate Result->" + autoExecuteRes + ",json->" + json);
+			while (!autoExecuteRes) {
+				logger.info("Compensate Failure, Entering Compensate Queue->" + autoExecuteRes + ",json->" + json);
+				executeCount++;
+				if (executeCount == 3) {
+					autoExecuteRes = false;
+					break;
+				}
+				try {
+					Thread.sleep(tryTime * 1000);
+				} catch (InterruptedException e) {
+					e.printStackTrace();
+				}
+				autoExecuteRes = _executeCompensate(json);
+			}
+
+			//执行成功删除数据
+			if (autoExecuteRes) {
+				compensateDao.deleteCompensateByKey(compensateKey);
+			}
+
+		} catch (Exception e) {
+			logger.error("Auto Compensate Fails,msg:" + e.getLocalizedMessage());
+			//推送数据给第三方通知
+			autoExecuteRes = false;
+		}
+
+		//执行补偿以后通知给业务方
+		String groupId = transactionCompensateMsg.getGroupId();
+		JSONObject requestJson = new JSONObject();
+		requestJson.put("action", "notify");
+		requestJson.put("groupId", groupId);
+		requestJson.put("resState", autoExecuteRes);
+
+		String url = configReader.getCompensateNotifyUrl();
+		logger.error("Compensate Result Callback Address->" + url);
+		String res = HttpUtils.postJson(url, requestJson.toJSONString());
+		logger.error("Compensate Result Callback Result->" + res);
+
+	}
+
+
+	@Override
+	public List<ModelName> loadModelList() {
+		List<String> keys = compensateDao.loadCompensateKeys();
+
+		Map<String, Integer> models = new HashMap<String, Integer>();
+
+		for (String key : keys) {
+			if (key.length() > 36) {
+				String name = key.substring(11, key.length() - 25);
+				int v = 1;
+				if (models.containsKey(name)) {
+					v = models.get(name) + 1;
+				}
+				models.put(name, v);
+			}
+		}
+		List<ModelName> names = new ArrayList<>();
+
+		for (String key : models.keySet()) {
+			int v = models.get(key);
+			ModelName modelName = new ModelName();
+			modelName.setName(key);
+			modelName.setCount(v);
+			names.add(modelName);
+		}
+		return names;
+	}
+
+	@Override
+	public List<String> loadCompensateTimes(String model) {
+		return compensateDao.loadCompensateTimes(model);
+	}
+
+	@Override
+	public List<TxModel> loadCompensateByModelAndTime(String path) {
+		List<String> logs = compensateDao.loadCompensateByModelAndTime(path);
+
+		List<TxModel> models = new ArrayList<>();
+		for (String json : logs) {
+			JSONObject jsonObject = JSON.parseObject(json);
+			TxModel model = new TxModel();
+			long currentTime = jsonObject.getLong("currentTime");
+			model.setTime(DateUtil.formatDate(new Date(currentTime), DateUtil.FULL_DATE_TIME_FORMAT));
+			model.setClassName(jsonObject.getString("className"));
+			model.setMethod(jsonObject.getString("methodStr"));
+			model.setExecuteTime(jsonObject.getInteger("time"));
+			model.setBase64(Base64Utils.encode(json.getBytes()));
+			model.setState(jsonObject.getInteger("state"));
+			model.setOrder(currentTime);
+
+			String groupId = jsonObject.getString("groupId");
+
+			String key = path + ":" + groupId;
+			model.setKey(key);
+
+			models.add(model);
+		}
+		Collections.sort(models, new Comparator<TxModel>() {
+			@Override
+			public int compare(TxModel o1, TxModel o2) {
+				if (o2.getOrder() > o1.getOrder()) {
+					return 1;
+				} else {
+					return -1;
+				}
+			}
+		});
+		return models;
+	}
+
+	@Override
+	public boolean hasCompensate() {
+		return compensateDao.hasCompensate();
+	}
+
+	@Override
+	public boolean delCompensate(String path) {
+		compensateDao.deleteCompensateByPath(path);
+		return true;
+	}
+
+	@Override
+	public void reloadCompensate(TxGroup txGroup) {
+		TxGroup compensateGroup = getCompensateByGroupId(txGroup.getGroupId());
+		if (compensateGroup != null) {
+
+			if (compensateGroup.getList() != null && !compensateGroup.getList().isEmpty()) {
+				//引用集合 iterator,方便匹配后剔除列表
+				Iterator<TxInfo> iterator = Lists.newArrayList(compensateGroup.getList()).iterator();
+				for (TxInfo txInfo : txGroup.getList()) {
+					while (iterator.hasNext()) {
+						TxInfo cinfo = iterator.next();
+						if (cinfo.getModel().equals(txInfo.getModel()) && cinfo.getMethodStr().equals(txInfo.getMethodStr())) {
+							//根据之前的数据补偿现在的事务
+							int oldNotify = cinfo.getNotify();
+
+							if (oldNotify == 1) {
+								//本次回滚
+								txInfo.setIsCommit(0);
+							} else {
+								//本次提交
+								txInfo.setIsCommit(1);
+							}
+							//匹配后剔除列表
+							iterator.remove();
+							break;
+						}
+					}
+				}
+			} else {//当没有List数据只记录了补偿数据时,理解问仅发起方提交其他均回滚
+				for (TxInfo txInfo : txGroup.getList()) {
+					//本次回滚
+					txInfo.setIsCommit(0);
+				}
+			}
+		}
+		logger.info("Compensate Loaded->" + JSON.toJSONString(txGroup));
+	}
+
+	public TxGroup getCompensateByGroupId(String groupId) {
+		String json = compensateDao.getCompensateByGroupId(groupId);
+		if (json == null) {
+			return null;
+		}
+		JSONObject jsonObject = JSON.parseObject(json);
+		String txGroup = jsonObject.getString("txGroup");
+		return JSON.parseObject(txGroup, TxGroup.class);
+	}
+
+
+	@Override
+	public boolean executeCompensate(String path) throws ServiceException {
+
+		String json = compensateDao.getCompensate(path);
+		if (json == null) {
+			throw new ServiceException("no data existing");
+		}
+
+		boolean hasOk = _executeCompensate(json);
+		if (hasOk) {
+			// 删除本地补偿数据
+			compensateDao.deleteCompensateByPath(path);
+
+			return true;
+		}
+		return false;
+	}
+
+
+	private boolean _executeCompensate(String json) throws ServiceException {
+		JSONObject jsonObject = JSON.parseObject(json);
+
+		String model = jsonObject.getString("model");
+
+		int startError = jsonObject.getInteger("startError");
+
+		ModelInfo modelInfo = ModelInfoManager.getInstance().getModelByModel(model);
+		if (modelInfo == null) {
+			throw new ServiceException("current model offline.");
+		}
+
+		String data = jsonObject.getString("data");
+
+		String groupId = jsonObject.getString("groupId");
+
+		String res = managerSenderService.sendCompensateMsg(modelInfo.getChannelName(), groupId, data, startError);
+
+		logger.debug("executeCompensate->" + json + ",@@->" + res);
+
+		return "1".equals(res);
+	}
+}

+ 109 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/config/ConfigReader.java

@@ -0,0 +1,109 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+/**
+ * create by lorne on 2017/11/11
+ */
+@Component
+public class ConfigReader {
+
+	/**
+	 * 事务默认数据的位置,有最大时间
+	 */
+	private final String key_prefix = "tx:manager:default:";
+	/**
+	 * 负载均衡模块存储信息
+	 */
+	private final String key_prefix_loadbalance = "tx:manager:loadbalance:";
+	/**
+	 * 补偿事务永久存储数据
+	 */
+	private final String key_prefix_compensate = "tx:manager:compensate:";
+	@Value("${tm.socket.port}")
+	private int socketPort;
+	@Value("${tm.socket.maxconnection}")
+	private int socketMaxConnection;
+	@Value("${tm.transaction.netty.hearttime}")
+	private int transactionNettyHeartTime;
+	@Value("${tm.transaction.netty.delaytime}")
+	private int transactionNettyDelayTime;
+	@Value("${tm.redis.savemaxtime}")
+	private int redisSaveMaxTime;
+	@Value("${tm.compensate.notifyUrl}")
+	private String compensateNotifyUrl;
+	@Value("${tm.compensate.auto}")
+	private boolean isCompensateAuto;
+	@Value("${tm.compensate.tryTime}")
+	private int compensateTryTime;
+	@Value("${tm.compensate.maxWaitTime}")
+	private int compensateMaxWaitTime;
+
+	public String getKeyPrefixLoadbalance() {
+		return key_prefix_loadbalance;
+	}
+
+	public String getCompensateNotifyUrl() {
+		return compensateNotifyUrl;
+	}
+
+	public String getKeyPrefix() {
+		return key_prefix;
+	}
+
+	public String getKeyPrefixCompensate() {
+		return key_prefix_compensate;
+	}
+
+	public int getSocketPort() {
+		return socketPort;
+	}
+
+	public int getSocketMaxConnection() {
+		return socketMaxConnection;
+	}
+
+	public int getTransactionNettyHeartTime() {
+		return transactionNettyHeartTime;
+	}
+
+	public int getRedisSaveMaxTime() {
+		return redisSaveMaxTime;
+	}
+
+	public int getTransactionNettyDelayTime() {
+		return transactionNettyDelayTime;
+	}
+
+	public boolean isCompensateAuto() {
+		return isCompensateAuto;
+	}
+
+	public int getCompensateTryTime() {
+		return compensateTryTime;
+	}
+
+	public int getCompensateMaxWaitTime() {
+		return compensateMaxWaitTime;
+	}
+
+
+}

+ 57 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/config/CorsConfig.java

@@ -0,0 +1,57 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+/**
+ * create by lorne on 2017/8/17
+ */
+@Configuration
+public class CorsConfig {
+
+	/**
+	 * 跨域过滤器
+	 *
+	 * @return
+	 */
+	private CorsConfiguration buildConfig() {
+		CorsConfiguration corsConfiguration = new CorsConfiguration();
+		corsConfiguration.addAllowedOrigin("*");
+		corsConfiguration.addAllowedHeader("*");
+		corsConfiguration.addAllowedMethod("*");
+		return corsConfiguration;
+	}
+
+
+	/**
+	 * 跨域过滤器
+	 *
+	 * @return
+	 */
+	@Bean
+	public CorsFilter corsFilter() {
+		UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+		source.registerCorsConfiguration("/**", buildConfig());
+		return new CorsFilter(source);
+	}
+}

+ 41 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/config/RestConfig.java

@@ -0,0 +1,41 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.config;
+
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * Created by lorne on 2017/7/5.
+ */
+
+@Configuration
+@EnableAutoConfiguration
+public class RestConfig {
+
+
+	@Bean
+	public RestTemplate getRestTemplate() {
+		RestTemplate restTemplate = new RestTemplate();
+		return restTemplate;
+	}
+
+
+}

+ 32 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/framework/utils/Constants.java

@@ -0,0 +1,32 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.framework.utils;
+
+/**
+ * Created by lorne on 2017/6/8.
+ */
+public class Constants {
+
+
+	public static int maxConnection;
+
+	public static int socketPort;
+
+	public static String address;
+
+}

+ 120 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/framework/utils/SocketManager.java

@@ -0,0 +1,120 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.framework.utils;
+
+import io.netty.channel.Channel;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * Created by lorne on 2017/6/30.
+ */
+public class SocketManager {
+
+	private static SocketManager manager = null;
+	/**
+	 * 最大连接数
+	 */
+	private int maxConnection = Constants.maxConnection;
+	/**
+	 * 当前连接数
+	 */
+	private int nowConnection;
+	/**
+	 * 允许连接请求 true允许 false拒绝
+	 */
+	private boolean allowConnection = true;
+	private List<Channel> clients = null;
+	private Map<String, String> lines = null;
+
+	private SocketManager() {
+		clients = new CopyOnWriteArrayList<Channel>();
+		lines = new ConcurrentHashMap<String, String>();
+	}
+
+	public static SocketManager getInstance() {
+		if (manager == null) {
+			synchronized (SocketManager.class) {
+				if (manager == null) {
+					manager = new SocketManager();
+				}
+			}
+		}
+		return manager;
+	}
+
+	public Channel getChannelByModelName(String name) {
+		for (Channel channel : clients) {
+			String modelName = channel.remoteAddress().toString();
+
+			if (modelName.equals(name)) {
+				return channel;
+			}
+		}
+		return null;
+	}
+
+	public void addClient(Channel client) {
+		clients.add(client);
+		nowConnection = clients.size();
+
+		allowConnection = (maxConnection != nowConnection);
+	}
+
+	public void removeClient(Channel client) {
+		clients.remove(client);
+		nowConnection = clients.size();
+
+		allowConnection = (maxConnection != nowConnection);
+	}
+
+
+	public int getMaxConnection() {
+		return maxConnection;
+	}
+
+	public int getNowConnection() {
+		return nowConnection;
+	}
+
+	public boolean isAllowConnection() {
+		return allowConnection;
+	}
+
+	public void outLine(String modelName) {
+		lines.remove(modelName);
+	}
+
+	public void onLine(String modelName, String uniqueKey) {
+		lines.put(modelName, uniqueKey);
+	}
+
+	public Channel getChannelByUniqueKey(String uniqueKey) {
+		for (Channel channel : clients) {
+			String modelName = channel.remoteAddress().toString();
+			String value = lines.get(modelName);
+			if (uniqueKey.equals(value)) {
+				return channel;
+			}
+		}
+		return null;
+	}
+}

+ 53 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/framework/utils/SocketUtils.java

@@ -0,0 +1,53 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.framework.utils;
+
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.Unpooled;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.util.ReferenceCountUtil;
+
+/**
+ * Created by lorne on 2017/7/6.
+ */
+public class SocketUtils {
+
+	public static String getJson(Object msg) {
+		String json;
+		try {
+			ByteBuf buf = (ByteBuf) msg;
+			byte[] bytes = new byte[buf.readableBytes()];
+			buf.readBytes(bytes);
+			json = new String(bytes);
+		} finally {
+			ReferenceCountUtil.release(msg);
+		}
+		return json;
+
+	}
+
+	public static void sendMsg(ChannelHandlerContext ctx, String msg) {
+		ctx.writeAndFlush(Unpooled.buffer().writeBytes(msg.getBytes()));
+	}
+
+
+	public static void sendMsg(Channel ctx, String msg) {
+		ctx.writeAndFlush(Unpooled.buffer().writeBytes(msg.getBytes()));
+	}
+}

+ 52 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/listener/ApplicationStartListener.java

@@ -0,0 +1,52 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.listener;
+
+import com.pig4cloud.pigx.manager.framework.utils.Constants;
+import org.springframework.boot.web.context.WebServerInitializedEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.stereotype.Component;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * create by lorne on 2017/8/7
+ */
+@Component
+public class ApplicationStartListener implements ApplicationListener<WebServerInitializedEvent> {
+
+
+	@Override
+	public void onApplicationEvent(WebServerInitializedEvent event) {
+		int serverPort = event.getWebServer().getPort();
+		String ip = getIp();
+		Constants.address = ip + ":" + serverPort;
+	}
+
+
+	private String getIp() {
+		String host = null;
+		try {
+			host = InetAddress.getLocalHost().getHostAddress();
+		} catch (UnknownHostException e) {
+			e.printStackTrace();
+		}
+		return host;
+	}
+}

+ 55 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/listener/ServerListener.java

@@ -0,0 +1,55 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.listener;
+
+import com.pig4cloud.pigx.manager.listener.service.InitService;
+import org.springframework.stereotype.Component;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.WebApplicationContextUtils;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+
+/**
+ * Created by lorne on 2017/7/1.
+ */
+
+@Component
+public class ServerListener implements ServletContextListener {
+
+	private WebApplicationContext springContext;
+
+
+	private InitService initService;
+
+	@Override
+	public void contextInitialized(ServletContextEvent event) {
+		springContext = WebApplicationContextUtils
+			.getWebApplicationContext(event.getServletContext());
+		initService = springContext.getBean(InitService.class);
+		initService.start();
+	}
+
+
+	@Override
+	public void contextDestroyed(ServletContextEvent event) {
+		initService.close();
+	}
+
+}

+ 29 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/listener/service/InitService.java

@@ -0,0 +1,29 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.listener.service;
+
+/**
+ * Created by lorne on 2017/7/4.
+ */
+public interface InitService {
+
+	void start();
+
+
+	void close();
+}

+ 54 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/listener/service/impl/InitServiceImpl.java

@@ -0,0 +1,54 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.listener.service.impl;
+
+import com.pig4cloud.pigx.manager.config.ConfigReader;
+import com.pig4cloud.pigx.manager.framework.utils.Constants;
+import com.pig4cloud.pigx.manager.listener.service.InitService;
+import com.pig4cloud.pigx.manager.netty.service.NettyServerService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+
+/**
+ * Created by lorne on 2017/7/4.
+ */
+@Service
+public class InitServiceImpl implements InitService {
+
+	@Autowired
+	private NettyServerService nettyServerService;
+
+	@Autowired
+	private ConfigReader configReader;
+
+
+	@Override
+	public void start() {
+		/**加载本地服务信息**/
+
+		Constants.socketPort = configReader.getSocketPort();
+		Constants.maxConnection = configReader.getSocketMaxConnection();
+		nettyServerService.start();
+	}
+
+	@Override
+	public void close() {
+		nettyServerService.close();
+	}
+}

+ 88 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/manager/ModelInfoManager.java

@@ -0,0 +1,88 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.manager;
+
+import com.pig4cloud.pigx.manager.model.ModelInfo;
+
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * create by lorne on 2017/11/13
+ */
+public class ModelInfoManager {
+
+
+	private static ModelInfoManager manager = null;
+	private List<ModelInfo> modelInfos = new CopyOnWriteArrayList<ModelInfo>();
+
+	public static ModelInfoManager getInstance() {
+		if (manager == null) {
+			synchronized (ModelInfoManager.class) {
+				if (manager == null) {
+					manager = new ModelInfoManager();
+				}
+			}
+		}
+		return manager;
+	}
+
+	public void removeModelInfo(String channelName) {
+		for (ModelInfo modelInfo : modelInfos) {
+			if (channelName.equalsIgnoreCase(modelInfo.getChannelName())) {
+				modelInfos.remove(modelInfo);
+			}
+		}
+	}
+
+
+	public void addModelInfo(ModelInfo minfo) {
+		for (ModelInfo modelInfo : modelInfos) {
+			if (minfo.getChannelName().equalsIgnoreCase(modelInfo.getChannelName())) {
+				return;
+			}
+
+			if (minfo.getIpAddress().equalsIgnoreCase(modelInfo.getIpAddress())) {
+				return;
+			}
+		}
+		modelInfos.add(minfo);
+	}
+
+	public List<ModelInfo> getOnlines() {
+		return modelInfos;
+	}
+
+	public ModelInfo getModelByChannelName(String channelName) {
+		for (ModelInfo modelInfo : modelInfos) {
+			if (channelName.equalsIgnoreCase(modelInfo.getChannelName())) {
+				return modelInfo;
+			}
+		}
+		return null;
+	}
+
+	public ModelInfo getModelByModel(String model) {
+		for (ModelInfo modelInfo : modelInfos) {
+			if (model.equalsIgnoreCase(modelInfo.getModel())) {
+				return modelInfo;
+			}
+		}
+		return null;
+	}
+}

+ 35 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/manager/service/LoadBalanceService.java

@@ -0,0 +1,35 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.manager.service;
+
+import com.pig4cloud.pigx.manager.model.LoadBalanceInfo;
+
+/**
+ * create by lorne on 2017/12/5
+ */
+public interface LoadBalanceService {
+
+	boolean put(LoadBalanceInfo loadBalanceInfo);
+
+	LoadBalanceInfo get(String groupId, String key);
+
+	boolean remove(String groupId);
+
+	String getLoadBalanceGroupName(String groupId);
+
+}

+ 33 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/manager/service/MicroService.java

@@ -0,0 +1,33 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.manager.service;
+
+import com.pig4cloud.pigx.manager.model.TxServer;
+import com.pig4cloud.pigx.manager.model.TxState;
+
+/**
+ * create by lorne on 2017/11/11
+ */
+public interface MicroService {
+
+	String tmKey = "tx-manager";
+
+	TxServer getServer();
+
+	TxState getState();
+}

+ 32 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/manager/service/TxManagerSenderService.java

@@ -0,0 +1,32 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.manager.service;
+
+import com.pig4cloud.pigx.manager.netty.model.TxGroup;
+
+/**
+ * Created by lorne on 2017/6/9.
+ */
+public interface TxManagerSenderService {
+
+	int confirm(TxGroup group);
+
+	String sendMsg(String model, String msg, int delay);
+
+	String sendCompensateMsg(String model, String groupId, String data, int startState);
+}

+ 102 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/manager/service/TxManagerService.java

@@ -0,0 +1,102 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.manager.service;
+
+import com.pig4cloud.pigx.manager.netty.model.TxGroup;
+
+/**
+ * Created by lorne on 2017/6/7.
+ */
+
+public interface TxManagerService {
+
+
+	/**
+	 * 创建事物组
+	 *
+	 * @param groupId 补偿事务组id
+	 */
+	TxGroup createTransactionGroup(String groupId);
+
+
+	/**
+	 * 添加事务组子对象
+	 *
+	 * @return
+	 */
+
+	TxGroup addTransactionGroup(String groupId, String taskId, int isGroup, String channelAddress, String methodStr);
+
+
+	/**
+	 * 关闭事务组
+	 *
+	 * @param groupId 事务组id
+	 * @param state   事务状态
+	 * @return 0 事务存在补偿 1 事务正常  -1 事务强制回滚
+	 */
+	int closeTransactionGroup(String groupId, int state);
+
+
+	void dealTxGroup(TxGroup txGroup, boolean hasOk);
+
+
+	/**
+	 * 删除事务组
+	 *
+	 * @param txGroup 事务组
+	 */
+	void deleteTxGroup(TxGroup txGroup);
+
+
+	/**
+	 * 获取事务组信息
+	 *
+	 * @param groupId 事务组id
+	 * @return 事务组
+	 */
+	TxGroup getTxGroup(String groupId);
+
+
+	/**
+	 * 获取事务组的key
+	 *
+	 * @param groupId 事务组id
+	 * @return key
+	 */
+	String getTxGroupKey(String groupId);
+
+
+	/**
+	 * 检查事务组数据
+	 *
+	 * @param groupId 事务组id
+	 * @param taskId  任务id
+	 * @return 本次请求的是否提交 1提交 0回滚
+	 */
+	int cleanNotifyTransaction(String groupId, String taskId);
+
+
+	/**
+	 * 设置强制回滚事务
+	 *
+	 * @param groupId 事务组id
+	 * @return true 成功 false 失败
+	 */
+	boolean rollbackTransactionGroup(String groupId);
+}

+ 71 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/manager/service/impl/LoadBalanceServiceImpl.java

@@ -0,0 +1,71 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.manager.service.impl;
+
+import com.pig4cloud.pigx.manager.config.ConfigReader;
+import com.pig4cloud.pigx.manager.manager.service.LoadBalanceService;
+import com.pig4cloud.pigx.manager.model.LoadBalanceInfo;
+import com.pig4cloud.pigx.manager.redis.RedisServerService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * create by lorne on 2017/12/5
+ */
+@Service
+public class LoadBalanceServiceImpl implements LoadBalanceService {
+
+	@Autowired
+	private RedisServerService redisServerService;
+
+	@Autowired
+	private ConfigReader configReader;
+
+	@Override
+	public boolean put(LoadBalanceInfo loadBalanceInfo) {
+		String groupName = getLoadBalanceGroupName(loadBalanceInfo.getGroupId());
+		redisServerService.saveLoadBalance(groupName, loadBalanceInfo.getKey(), loadBalanceInfo.getData());
+		return true;
+	}
+
+	@Override
+	public LoadBalanceInfo get(String groupId, String key) {
+		String groupName = getLoadBalanceGroupName(groupId);
+		String bytes = redisServerService.getLoadBalance(groupName, key);
+		if (bytes == null) {
+			return null;
+		}
+
+		LoadBalanceInfo loadBalanceInfo = new LoadBalanceInfo();
+		loadBalanceInfo.setGroupId(groupId);
+		loadBalanceInfo.setKey(key);
+		loadBalanceInfo.setData(bytes);
+		return loadBalanceInfo;
+	}
+
+	@Override
+	public boolean remove(String groupId) {
+		redisServerService.deleteKey(getLoadBalanceGroupName(groupId));
+		return true;
+	}
+
+	@Override
+	public String getLoadBalanceGroupName(String groupId) {
+		return configReader.getKeyPrefixLoadbalance() + groupId;
+	}
+}

+ 141 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/manager/service/impl/MicroServiceImpl.java

@@ -0,0 +1,141 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.manager.service.impl;
+
+import com.pig4cloud.pigx.manager.config.ConfigReader;
+import com.pig4cloud.pigx.manager.framework.utils.Constants;
+import com.pig4cloud.pigx.manager.framework.utils.SocketManager;
+import com.pig4cloud.pigx.manager.manager.service.MicroService;
+import com.pig4cloud.pigx.manager.model.TxServer;
+import com.pig4cloud.pigx.manager.model.TxState;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cloud.client.ServiceInstance;
+import org.springframework.cloud.client.discovery.DiscoveryClient;
+import org.springframework.cloud.client.serviceregistry.Registration;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * create by lorne on 2017/11/11
+ */
+@Service
+public class MicroServiceImpl implements MicroService {
+
+
+	@Autowired
+	private RestTemplate restTemplate;
+
+	@Autowired
+	private ConfigReader configReader;
+
+
+	@Autowired
+	private DiscoveryClient discoveryClient;
+
+	@Autowired
+	private Registration registration;
+
+	private boolean isIp(String ipAddress) {
+		String ip = "([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}";
+		Pattern pattern = Pattern.compile(ip);
+		Matcher matcher = pattern.matcher(ipAddress);
+		return matcher.matches();
+	}
+
+
+	@Override
+	public TxState getState() {
+		TxState state = new TxState();
+		String ipAddress = registration.getHost();
+		if (!isIp(ipAddress)) {
+			ipAddress = "127.0.0.1";
+		}
+		state.setIp(ipAddress);
+		state.setPort(Constants.socketPort);
+		state.setMaxConnection(SocketManager.getInstance().getMaxConnection());
+		state.setNowConnection(SocketManager.getInstance().getNowConnection());
+		state.setRedisSaveMaxTime(configReader.getRedisSaveMaxTime());
+		state.setTransactionNettyDelayTime(configReader.getTransactionNettyDelayTime());
+		state.setTransactionNettyHeartTime(configReader.getTransactionNettyHeartTime());
+		state.setNotifyUrl(configReader.getCompensateNotifyUrl());
+		state.setCompensate(configReader.isCompensateAuto());
+		state.setCompensateTryTime(configReader.getCompensateTryTime());
+		state.setCompensateMaxWaitTime(configReader.getCompensateMaxWaitTime());
+		state.setSlbList(getServices());
+		return state;
+	}
+
+	private List<String> getServices() {
+		List<String> urls = new ArrayList<>();
+		List<ServiceInstance> serviceInstances = discoveryClient.getInstances(tmKey);
+		for (ServiceInstance instanceInfo : serviceInstances) {
+			urls.add(instanceInfo.getUri().toASCIIString());
+		}
+		return urls;
+	}
+
+	@Override
+	public TxServer getServer() {
+		List<String> urls = getServices();
+		List<TxState> states = new ArrayList<>();
+		for (String url : urls) {
+			try {
+				TxState state = restTemplate.getForObject(url + "/tx/manager/state", TxState.class);
+				states.add(state);
+			} catch (Exception e) {
+			}
+
+		}
+		if (states.size() <= 1) {
+			TxState state = getState();
+			if (state.getMaxConnection() > state.getNowConnection()) {
+				return TxServer.format(state);
+			} else {
+				return null;
+			}
+		} else {
+			//找默认数据
+			TxState state = getDefault(states, 0);
+			if (state == null) {
+				//没有满足的默认数据
+				return null;
+			}
+			return TxServer.format(state);
+		}
+	}
+
+	private TxState getDefault(List<TxState> states, int index) {
+		TxState state = states.get(index);
+		if (state.getMaxConnection() == state.getNowConnection()) {
+			index++;
+			if (states.size() - 1 >= index) {
+				return getDefault(states, index);
+			} else {
+				return null;
+			}
+		} else {
+			return state;
+		}
+	}
+
+}

+ 335 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/manager/service/impl/TxManagerSenderServiceImpl.java

@@ -0,0 +1,335 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.manager.service.impl;
+
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.lorne.core.framework.utils.KidUtils;
+import com.lorne.core.framework.utils.task.ConditionUtils;
+import com.lorne.core.framework.utils.task.IBack;
+import com.lorne.core.framework.utils.task.Task;
+import com.lorne.core.framework.utils.thread.CountDownLatchHelper;
+import com.lorne.core.framework.utils.thread.IExecute;
+import com.pig4cloud.pigx.manager.compensate.service.CompensateService;
+import com.pig4cloud.pigx.manager.config.ConfigReader;
+import com.pig4cloud.pigx.manager.framework.utils.Constants;
+import com.pig4cloud.pigx.manager.framework.utils.SocketManager;
+import com.pig4cloud.pigx.manager.framework.utils.SocketUtils;
+import com.pig4cloud.pigx.manager.manager.service.TxManagerSenderService;
+import com.pig4cloud.pigx.manager.manager.service.TxManagerService;
+import com.pig4cloud.pigx.manager.model.ChannelSender;
+import com.pig4cloud.pigx.manager.netty.model.TxGroup;
+import com.pig4cloud.pigx.manager.netty.model.TxInfo;
+import com.pig4cloud.pigx.manager.redis.RedisServerService;
+import io.netty.channel.Channel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.concurrent.*;
+
+
+/**
+ * Created by lorne on 2017/6/9.
+ */
+@Service
+public class TxManagerSenderServiceImpl implements TxManagerSenderService {
+
+
+	private Logger logger = LoggerFactory.getLogger(TxManagerSenderServiceImpl.class);
+
+	private ScheduledExecutorService executorService = Executors.newScheduledThreadPool(100);
+
+	private Executor threadPool = Executors.newFixedThreadPool(100);
+
+	@Autowired
+	private TxManagerService txManagerService;
+
+	@Autowired
+	private RedisServerService redisServerService;
+
+	@Autowired
+	private ConfigReader configReader;
+
+	@Autowired
+	private CompensateService compensateService;
+
+	@Override
+	public int confirm(TxGroup txGroup) {
+		//绑定管道对象,检查网络
+		setChannel(txGroup.getList());
+
+		//事务不满足直接回滚事务
+		if (txGroup.getState() == 0) {
+			transaction(txGroup, 0);
+			return 0;
+		}
+
+		if (txGroup.getRollback() == 1) {
+			transaction(txGroup, 0);
+			return -1;
+		}
+
+		boolean hasOk = transaction(txGroup, 1);
+		txManagerService.dealTxGroup(txGroup, hasOk);
+		return hasOk ? 1 : 0;
+	}
+
+
+	/**
+	 * 匹配管道
+	 *
+	 * @param list
+	 */
+	private void setChannel(List<TxInfo> list) {
+		for (TxInfo info : list) {
+			if (Constants.address.equals(info.getAddress())) {
+				Channel channel = SocketManager.getInstance().getChannelByModelName(info.getChannelAddress());
+				if (channel != null && channel.isActive()) {
+					ChannelSender sender = new ChannelSender();
+					sender.setChannel(channel);
+
+					info.setChannel(sender);
+				}
+			} else {
+				ChannelSender sender = new ChannelSender();
+				sender.setAddress(info.getAddress());
+				sender.setModelName(info.getChannelAddress());
+
+				info.setChannel(sender);
+			}
+		}
+	}
+
+
+	/**
+	 * 事务提交或回归
+	 *
+	 * @param checkSate
+	 */
+	private boolean transaction(final TxGroup txGroup, final int checkSate) {
+
+
+		if (checkSate == 1) {
+
+			//补偿请求,加载历史数据
+			if (txGroup.getIsCompensate() == 1) {
+				compensateService.reloadCompensate(txGroup);
+			}
+
+			CountDownLatchHelper<Boolean> countDownLatchHelper = new CountDownLatchHelper<Boolean>();
+			for (final TxInfo txInfo : txGroup.getList()) {
+				if (txInfo.getIsGroup() == 0) {
+					countDownLatchHelper.addExecute(new IExecute<Boolean>() {
+						@Override
+						public Boolean execute() {
+							if (txInfo.getChannel() == null) {
+								return false;
+							}
+
+							final JSONObject jsonObject = new JSONObject();
+							jsonObject.put("a", "t");
+
+
+							if (txGroup.getIsCompensate() == 1) {   //补偿请求
+								jsonObject.put("c", txInfo.getIsCommit());
+							} else { //正常业务
+								jsonObject.put("c", checkSate);
+							}
+
+							jsonObject.put("t", txInfo.getKid());
+							final String key = KidUtils.generateShortUuid();
+							jsonObject.put("k", key);
+
+							Task task = ConditionUtils.getInstance().createTask(key);
+
+							ScheduledFuture future = schedule(key, configReader.getTransactionNettyDelayTime());
+
+							threadAwaitSend(task, txInfo, jsonObject.toJSONString());
+
+							task.awaitTask();
+
+							if (!future.isDone()) {
+								future.cancel(false);
+							}
+
+							try {
+								String data = (String) task.getBack().doing();
+								// 1  成功 0 失败 -1 task为空 -2 超过
+								boolean res = "1".equals(data);
+
+								if (res) {
+									txInfo.setNotify(1);
+								}
+
+								return res;
+							} catch (Throwable throwable) {
+								throwable.printStackTrace();
+								return false;
+							} finally {
+								task.remove();
+							}
+						}
+					});
+				}
+			}
+
+			List<Boolean> hasOks = countDownLatchHelper.execute().getData();
+
+			String key = configReader.getKeyPrefix() + txGroup.getGroupId();
+			redisServerService.saveTransaction(key, txGroup.toJsonString());
+
+			boolean hasOk = true;
+			for (boolean bl : hasOks) {
+				if (!bl) {
+					hasOk = false;
+					break;
+				}
+			}
+			logger.info("--->" + hasOk + ",group:" + txGroup.getGroupId() + ",state:" + checkSate + ",list:" + txGroup.toJsonString());
+			return hasOk;
+		} else {
+			//回滚操作只发送通过不需要等待确认
+			for (TxInfo txInfo : txGroup.getList()) {
+				if (txInfo.getChannel() != null) {
+					if (txInfo.getIsGroup() == 0) {
+						JSONObject jsonObject = new JSONObject();
+						jsonObject.put("a", "t");
+						jsonObject.put("c", checkSate);
+						jsonObject.put("t", txInfo.getKid());
+						String key = KidUtils.generateShortUuid();
+						jsonObject.put("k", key);
+						txInfo.getChannel().send(jsonObject.toJSONString());
+					}
+				}
+			}
+			txManagerService.deleteTxGroup(txGroup);
+			return true;
+		}
+
+	}
+
+	@Override
+	public String sendCompensateMsg(String model, String groupId, String data, int startState) {
+		JSONObject newCmd = new JSONObject();
+		newCmd.put("a", "c");
+		newCmd.put("d", data);
+		newCmd.put("ss", startState);
+		newCmd.put("g", groupId);
+		newCmd.put("k", KidUtils.generateShortUuid());
+		return sendMsg(model, newCmd.toJSONString(), configReader.getRedisSaveMaxTime());
+	}
+
+	@Override
+	public String sendMsg(final String model, final String msg, int delay) {
+		JSONObject jsonObject = JSON.parseObject(msg);
+		String key = jsonObject.getString("k");
+
+		//创建Task
+		final Task task = ConditionUtils.getInstance().createTask(key);
+
+		threadPool.execute(new Runnable() {
+			@Override
+			public void run() {
+				while (!task.isAwait() && !Thread.currentThread().interrupted()) {
+					try {
+						Thread.sleep(1);
+					} catch (InterruptedException e) {
+						e.printStackTrace();
+					}
+				}
+
+				Channel channel = SocketManager.getInstance().getChannelByModelName(model);
+				if (channel != null && channel.isActive()) {
+					SocketUtils.sendMsg(channel, msg);
+				}
+			}
+		});
+
+		ScheduledFuture future = schedule(key, delay);
+
+		task.awaitTask();
+
+		if (!future.isDone()) {
+			future.cancel(false);
+		}
+
+		try {
+			return (String) task.getBack().doing();
+		} catch (Throwable throwable) {
+			return "-1";
+		} finally {
+			task.remove();
+		}
+	}
+
+
+	private void threadAwaitSend(final Task task, final TxInfo txInfo, final String msg) {
+		threadPool.execute(new Runnable() {
+			@Override
+			public void run() {
+				while (!task.isAwait() && !Thread.currentThread().interrupted()) {
+					try {
+						Thread.sleep(1);
+					} catch (InterruptedException e) {
+						e.printStackTrace();
+					}
+				}
+
+				if (txInfo != null && txInfo.getChannel() != null) {
+					txInfo.getChannel().send(msg, task);
+				} else {
+					task.setBack(new IBack() {
+						@Override
+						public Object doing(Object... objs) throws Throwable {
+							return "-2";
+						}
+					});
+					task.signalTask();
+				}
+			}
+		});
+
+	}
+
+
+	private ScheduledFuture schedule(final String key, int delayTime) {
+		ScheduledFuture future = executorService.schedule(new Runnable() {
+			@Override
+			public void run() {
+				Task task = ConditionUtils.getInstance().getTask(key);
+				if (task != null && !task.isNotify()) {
+					task.setBack(new IBack() {
+						@Override
+						public Object doing(Object... objs) throws Throwable {
+							return "-2";
+						}
+					});
+					task.signalTask();
+				}
+			}
+		}, delayTime, TimeUnit.SECONDS);
+
+		return future;
+	}
+
+
+}

+ 226 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/manager/service/impl/TxManagerServiceImpl.java

@@ -0,0 +1,226 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.manager.service.impl;
+
+
+import com.pig4cloud.pigx.manager.compensate.service.CompensateService;
+import com.pig4cloud.pigx.manager.config.ConfigReader;
+import com.pig4cloud.pigx.manager.framework.utils.Constants;
+import com.pig4cloud.pigx.manager.manager.ModelInfoManager;
+import com.pig4cloud.pigx.manager.manager.service.LoadBalanceService;
+import com.pig4cloud.pigx.manager.manager.service.TxManagerSenderService;
+import com.pig4cloud.pigx.manager.manager.service.TxManagerService;
+import com.pig4cloud.pigx.manager.model.ModelInfo;
+import com.pig4cloud.pigx.manager.netty.model.TxGroup;
+import com.pig4cloud.pigx.manager.netty.model.TxInfo;
+import com.pig4cloud.pigx.manager.redis.RedisServerService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * Created by lorne on 2017/6/7.
+ */
+@Service
+public class TxManagerServiceImpl implements TxManagerService {
+	@Autowired
+	private ConfigReader configReader;
+	@Autowired
+	private RedisServerService redisServerService;
+
+
+	@Autowired
+	private TxManagerSenderService transactionConfirmService;
+
+
+	@Autowired
+	private LoadBalanceService loadBalanceService;
+
+	@Autowired
+	private CompensateService compensateService;
+
+
+	private Logger logger = LoggerFactory.getLogger(TxManagerServiceImpl.class);
+
+
+	@Override
+	public TxGroup createTransactionGroup(String groupId) {
+		TxGroup txGroup = new TxGroup();
+		if (compensateService.getCompensateByGroupId(groupId) != null) {
+			txGroup.setIsCompensate(1);
+		}
+
+		txGroup.setStartTime(System.currentTimeMillis());
+		txGroup.setGroupId(groupId);
+
+		String key = configReader.getKeyPrefix() + groupId;
+		redisServerService.saveTransaction(key, txGroup.toJsonString());
+
+		return txGroup;
+	}
+
+
+	@Override
+	public TxGroup addTransactionGroup(String groupId, String taskId, int isGroup, String channelAddress, String methodStr) {
+		String key = getTxGroupKey(groupId);
+		TxGroup txGroup = getTxGroup(groupId);
+		if (txGroup == null) {
+			return null;
+		}
+		TxInfo txInfo = new TxInfo();
+		txInfo.setChannelAddress(channelAddress);
+		txInfo.setKid(taskId);
+		txInfo.setAddress(Constants.address);
+		txInfo.setIsGroup(isGroup);
+		txInfo.setMethodStr(methodStr);
+
+
+		ModelInfo modelInfo = ModelInfoManager.getInstance().getModelByChannelName(channelAddress);
+		if (modelInfo != null) {
+			txInfo.setUniqueKey(modelInfo.getUniqueKey());
+			txInfo.setModelIpAddress(modelInfo.getIpAddress());
+			txInfo.setModel(modelInfo.getModel());
+		}
+
+		txGroup.addTransactionInfo(txInfo);
+
+		redisServerService.saveTransaction(key, txGroup.toJsonString());
+
+		return txGroup;
+	}
+
+	@Override
+	public boolean rollbackTransactionGroup(String groupId) {
+		String key = getTxGroupKey(groupId);
+		TxGroup txGroup = getTxGroup(groupId);
+		if (txGroup == null) {
+			return false;
+		}
+		txGroup.setRollback(1);
+		redisServerService.saveTransaction(key, txGroup.toJsonString());
+		return true;
+	}
+
+	@Override
+	public int cleanNotifyTransaction(String groupId, String taskId) {
+		int res = 0;
+		logger.info("start-cleanNotifyTransaction->groupId:" + groupId + ",taskId:" + taskId);
+		String key = getTxGroupKey(groupId);
+		TxGroup txGroup = getTxGroup(groupId);
+		if (txGroup == null) {
+			logger.info("cleanNotifyTransaction - > txGroup is null ");
+			return res;
+		}
+
+		if (txGroup.getHasOver() == 0) {
+
+			//整个事务回滚.
+			txGroup.setRollback(1);
+			redisServerService.saveTransaction(key, txGroup.toJsonString());
+
+			logger.info("cleanNotifyTransaction - > groupId " + groupId + " not over,all transaction must rollback !");
+			return 0;
+		}
+
+		if (txGroup.getRollback() == 1) {
+			logger.info("cleanNotifyTransaction - > groupId " + groupId + " only rollback !");
+			return 0;
+		}
+
+		//更新数据
+		boolean hasSet = false;
+		for (TxInfo info : txGroup.getList()) {
+			if (info.getKid().equals(taskId)) {
+				if (info.getNotify() == 0 && info.getIsGroup() == 0) {
+					info.setNotify(1);
+					hasSet = true;
+					res = 1;
+
+					break;
+				}
+			}
+		}
+
+		//判断是否都结束
+		boolean isOver = true;
+		for (TxInfo info : txGroup.getList()) {
+			if (info.getIsGroup() == 0 && info.getNotify() == 0) {
+				isOver = false;
+				break;
+			}
+		}
+
+		if (isOver) {
+			deleteTxGroup(txGroup);
+		}
+
+		//有更新的数据,需要修改记录
+		if (!isOver && hasSet) {
+			redisServerService.saveTransaction(key, txGroup.toJsonString());
+		}
+
+		logger.info("end-cleanNotifyTransaction->groupId:" + groupId + ",taskId:" + taskId + ",res(1:commit,0:rollback):" + res);
+		return res;
+	}
+
+
+	@Override
+	public int closeTransactionGroup(String groupId, int state) {
+		String key = getTxGroupKey(groupId);
+		TxGroup txGroup = getTxGroup(groupId);
+		if (txGroup == null) {
+			return 0;
+		}
+		txGroup.setState(state);
+		txGroup.setHasOver(1);
+		redisServerService.saveTransaction(key, txGroup.toJsonString());
+		return transactionConfirmService.confirm(txGroup);
+	}
+
+
+	@Override
+	public void dealTxGroup(TxGroup txGroup, boolean hasOk) {
+		if (hasOk) {
+			deleteTxGroup(txGroup);
+		}
+	}
+
+
+	@Override
+	public void deleteTxGroup(TxGroup txGroup) {
+		String groupId = txGroup.getGroupId();
+
+		String key = getTxGroupKey(groupId);
+		redisServerService.deleteKey(key);
+
+		loadBalanceService.remove(groupId);
+	}
+
+
+	@Override
+	public TxGroup getTxGroup(String groupId) {
+		String key = getTxGroupKey(groupId);
+		return redisServerService.getTxGroupByKey(key);
+	}
+
+	@Override
+	public String getTxGroupKey(String groupId) {
+		return configReader.getKeyPrefix() + groupId;
+	}
+}

+ 89 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/model/ChannelSender.java

@@ -0,0 +1,89 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.model;
+
+import com.lorne.core.framework.utils.http.HttpUtils;
+import com.lorne.core.framework.utils.task.IBack;
+import com.lorne.core.framework.utils.task.Task;
+import com.pig4cloud.pigx.manager.framework.utils.SocketUtils;
+import io.netty.channel.Channel;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * create by lorne on 2017/8/7
+ */
+public class ChannelSender {
+
+
+	private Channel channel;
+
+	private String address;
+
+	private String modelName;
+
+	public void setModelName(String modelName) {
+		this.modelName = modelName;
+	}
+
+	public void setChannel(Channel channel) {
+		this.channel = channel;
+	}
+
+	public void setAddress(String address) {
+		this.address = address;
+	}
+
+
+	public void send(String msg) {
+		if (channel != null) {
+			SocketUtils.sendMsg(channel, msg);
+		}
+
+	}
+
+	public void send(String msg, Task task) {
+		if (channel != null) {
+			SocketUtils.sendMsg(channel, msg);
+		} else {
+			String url = String.format("http://%s/tx/manager/sendMsg", address);
+			final String res = HttpUtils.post(url, "msg=" + msg + "&model=" + modelName);
+			if (StringUtils.isNotEmpty(res)) {
+				if (task != null) {
+					task.setBack(new IBack() {
+						@Override
+						public Object doing(Object... objs) throws Throwable {
+							return res;
+						}
+					});
+					task.signalTask();
+				}
+			} else {
+				if (task != null) {
+					task.setBack(new IBack() {
+						@Override
+						public Object doing(Object... objs) throws Throwable {
+							return "-2";
+						}
+					});
+					task.signalTask();
+				}
+			}
+		}
+
+	}
+}

+ 56 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/model/LoadBalanceInfo.java

@@ -0,0 +1,56 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.model;
+
+/**
+ * 负载均衡模块信息
+ * create by lorne on 2017/12/5
+ */
+public class LoadBalanceInfo {
+
+	private String groupId;
+
+	private String key;
+
+	private String data;
+
+
+	public String getGroupId() {
+		return groupId;
+	}
+
+	public void setGroupId(String groupId) {
+		this.groupId = groupId;
+	}
+
+	public String getKey() {
+		return key;
+	}
+
+	public void setKey(String key) {
+		this.key = key;
+	}
+
+	public String getData() {
+		return data;
+	}
+
+	public void setData(String data) {
+		this.data = data;
+	}
+}

+ 65 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/model/ModelInfo.java

@@ -0,0 +1,65 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.model;
+
+/**
+ * 模块信息
+ * create by lorne on 2017/11/13
+ */
+public class ModelInfo {
+
+	private String model;
+
+	private String ipAddress;
+
+	private String channelName;
+
+	private String uniqueKey;
+
+	public String getModel() {
+		return model;
+	}
+
+	public void setModel(String model) {
+		this.model = model;
+	}
+
+	public String getIpAddress() {
+		return ipAddress;
+	}
+
+	public void setIpAddress(String ipAddress) {
+		this.ipAddress = ipAddress;
+	}
+
+	public String getChannelName() {
+		return channelName;
+	}
+
+	public void setChannelName(String channelName) {
+		this.channelName = channelName;
+	}
+
+	public String getUniqueKey() {
+		return uniqueKey;
+	}
+
+	public void setUniqueKey(String uniqueKey) {
+		this.uniqueKey = uniqueKey;
+	}
+}

+ 45 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/model/ModelName.java

@@ -0,0 +1,45 @@
+
+
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.model;
+
+/**
+ * create by lorne on 2017/11/22
+ */
+public class ModelName {
+
+	private String name;
+	private int count;
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public int getCount() {
+		return count;
+	}
+
+	public void setCount(int count) {
+		this.count = count;
+	}
+}

+ 86 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/model/TxServer.java

@@ -0,0 +1,86 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.model;
+
+/**
+ * Created by lorne on 2017/7/1.
+ */
+public class TxServer {
+
+	private String ip;
+	private int port;
+	private int heart;
+	private int delay;
+	private int compensateMaxWaitTime;
+
+	public static TxServer format(TxState state) {
+		TxServer txServer = new TxServer();
+		txServer.setIp(state.getIp());
+		txServer.setPort(state.getPort());
+		txServer.setHeart(state.getTransactionNettyHeartTime());
+		txServer.setDelay(state.getTransactionNettyDelayTime());
+		txServer.setCompensateMaxWaitTime(state.getCompensateMaxWaitTime());
+		return txServer;
+	}
+
+
+	public String getIp() {
+		return ip;
+	}
+
+	public void setIp(String ip) {
+		this.ip = ip;
+	}
+
+
+	public int getPort() {
+		return port;
+	}
+
+	public void setPort(int port) {
+		this.port = port;
+	}
+
+	public int getHeart() {
+		return heart;
+	}
+
+	public void setHeart(int heart) {
+		this.heart = heart;
+	}
+
+	public int getDelay() {
+		return delay;
+	}
+
+	public void setDelay(int delay) {
+		this.delay = delay;
+	}
+
+
+	public int getCompensateMaxWaitTime() {
+		return compensateMaxWaitTime;
+	}
+
+
+	public void setCompensateMaxWaitTime(int compensateMaxWaitTime) {
+		this.compensateMaxWaitTime = compensateMaxWaitTime;
+	}
+
+
+}

+ 187 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/model/TxState.java

@@ -0,0 +1,187 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.model;
+
+import java.util.List;
+
+/**
+ * Created by lorne on 2017/7/1.
+ */
+public class TxState {
+
+	/**
+	 * socket ip
+	 */
+	private String ip;
+	/**
+	 * socket port
+	 */
+	private int port;
+
+	/**
+	 * max connection
+	 */
+	private int maxConnection;
+
+	/**
+	 * now connection
+	 */
+	private int nowConnection;
+
+
+	/**
+	 * transaction_netty_heart_time
+	 */
+	private int transactionNettyHeartTime;
+
+	/**
+	 * transaction_netty_delay_time
+	 */
+	private int transactionNettyDelayTime;
+
+
+	/**
+	 * redis_save_max_time
+	 */
+	private int redisSaveMaxTime;
+
+
+	/**
+	 * 回调地址
+	 */
+	private String notifyUrl;
+
+	/**
+	 * 自动补偿
+	 */
+	private boolean isCompensate;
+
+	/**
+	 * 补偿尝试时间
+	 */
+	private int compensateTryTime;
+
+	/**
+	 * slb list
+	 */
+	private List<String> slbList;
+
+	/**
+	 * 自动补偿间隔时间
+	 */
+	private int compensateMaxWaitTime;
+
+
+	public String getIp() {
+		return ip;
+	}
+
+	public void setIp(String ip) {
+		this.ip = ip;
+	}
+
+	public int getPort() {
+		return port;
+	}
+
+	public void setPort(int port) {
+		this.port = port;
+	}
+
+	public int getMaxConnection() {
+		return maxConnection;
+	}
+
+	public void setMaxConnection(int maxConnection) {
+		this.maxConnection = maxConnection;
+	}
+
+	public int getNowConnection() {
+		return nowConnection;
+	}
+
+	public void setNowConnection(int nowConnection) {
+		this.nowConnection = nowConnection;
+	}
+
+	public boolean isCompensate() {
+		return isCompensate;
+	}
+
+	public void setCompensate(boolean compensate) {
+		isCompensate = compensate;
+	}
+
+	public int getCompensateTryTime() {
+		return compensateTryTime;
+	}
+
+	public void setCompensateTryTime(int compensateTryTime) {
+		this.compensateTryTime = compensateTryTime;
+	}
+
+	public int getRedisSaveMaxTime() {
+		return redisSaveMaxTime;
+	}
+
+	public void setRedisSaveMaxTime(int redisSaveMaxTime) {
+		this.redisSaveMaxTime = redisSaveMaxTime;
+	}
+
+	public List<String> getSlbList() {
+		return slbList;
+	}
+
+	public void setSlbList(List<String> slbList) {
+		this.slbList = slbList;
+	}
+
+	public int getTransactionNettyHeartTime() {
+		return transactionNettyHeartTime;
+	}
+
+	public void setTransactionNettyHeartTime(int transactionNettyHeartTime) {
+		this.transactionNettyHeartTime = transactionNettyHeartTime;
+	}
+
+	public int getTransactionNettyDelayTime() {
+		return transactionNettyDelayTime;
+	}
+
+	public void setTransactionNettyDelayTime(int transactionNettyDelayTime) {
+		this.transactionNettyDelayTime = transactionNettyDelayTime;
+	}
+
+	public String getNotifyUrl() {
+		return notifyUrl;
+	}
+
+	public void setNotifyUrl(String notifyUrl) {
+		this.notifyUrl = notifyUrl;
+	}
+
+	public int getCompensateMaxWaitTime() {
+		return compensateMaxWaitTime;
+	}
+
+	public void setCompensateMaxWaitTime(int compensateMaxWaitTime) {
+		this.compensateMaxWaitTime = compensateMaxWaitTime;
+	}
+
+
+}

+ 140 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/handler/TxCoreServerHandler.java

@@ -0,0 +1,140 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.netty.handler;
+
+/**
+ * Created by lorne on 2017/6/29.
+ */
+
+import com.alibaba.fastjson.JSONObject;
+import com.pig4cloud.pigx.manager.framework.utils.SocketManager;
+import com.pig4cloud.pigx.manager.framework.utils.SocketUtils;
+import com.pig4cloud.pigx.manager.manager.ModelInfoManager;
+import com.pig4cloud.pigx.manager.netty.service.IActionService;
+import com.pig4cloud.pigx.manager.netty.service.NettyService;
+import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInboundHandlerAdapter;
+import io.netty.handler.timeout.IdleState;
+import io.netty.handler.timeout.IdleStateEvent;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Handles a server-side channel.
+ */
+
+@ChannelHandler.Sharable
+public class TxCoreServerHandler extends ChannelInboundHandlerAdapter { // (1)
+
+	private NettyService nettyService;
+
+
+	private Logger logger = LoggerFactory.getLogger(TxCoreServerHandler.class);
+
+
+	private Executor threadPool;
+
+
+	public TxCoreServerHandler(Executor threadPool, NettyService nettyService) {
+		this.threadPool = threadPool;
+		this.nettyService = nettyService;
+	}
+
+	@Override
+	public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception {
+		final String json = SocketUtils.getJson(msg);
+		logger.debug("request->" + json);
+		threadPool.execute(new Runnable() {
+			@Override
+			public void run() {
+				service(json, ctx);
+			}
+		});
+	}
+
+	private void service(String json, ChannelHandlerContext ctx) {
+		if (StringUtils.isNotEmpty(json)) {
+			JSONObject jsonObject = JSONObject.parseObject(json);
+			String action = jsonObject.getString("a");
+			String key = jsonObject.getString("k");
+			JSONObject params = JSONObject.parseObject(jsonObject.getString("p"));
+			String channelAddress = ctx.channel().remoteAddress().toString();
+
+			IActionService actionService = nettyService.getActionService(action);
+
+			String res = actionService.execute(channelAddress, key, params);
+
+			JSONObject resObj = new JSONObject();
+			resObj.put("k", key);
+			resObj.put("d", res);
+
+			SocketUtils.sendMsg(ctx, resObj.toString());
+
+		}
+	}
+
+	@Override
+	public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
+
+		//是否到达最大上线连接数
+		if (SocketManager.getInstance().isAllowConnection()) {
+			SocketManager.getInstance().addClient(ctx.channel());
+		} else {
+			ctx.close();
+		}
+		super.channelRegistered(ctx);
+	}
+
+	@Override
+	public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
+
+		SocketManager.getInstance().removeClient(ctx.channel());
+		String modelName = ctx.channel().remoteAddress().toString();
+		SocketManager.getInstance().outLine(modelName);
+
+		ModelInfoManager.getInstance().removeModelInfo(modelName);
+		super.channelUnregistered(ctx);
+	}
+
+	@Override
+	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
+		ctx.flush();
+	}
+
+	@Override
+	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
+		cause.printStackTrace();
+		//ctx.close();
+	}
+
+	@Override
+	public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
+		//心跳配置
+		if (IdleStateEvent.class.isAssignableFrom(evt.getClass())) {
+			IdleStateEvent event = (IdleStateEvent) evt;
+			if (event.state() == IdleState.READER_IDLE) {
+				ctx.close();
+			}
+		}
+	}
+
+}

+ 199 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/model/TxGroup.java

@@ -0,0 +1,199 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.netty.model;
+
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by lorne on 2017/6/7.
+ */
+public class TxGroup {
+
+	private String groupId;
+
+	private long startTime;
+
+	private long nowTime;
+
+	private int state;
+
+	private int hasOver;
+
+	/**
+	 * 补偿请求
+	 */
+	private int isCompensate;
+
+
+	/**
+	 * 是否强制回滚(1:开启,0:关闭)
+	 */
+	private int rollback = 0;
+
+	private List<TxInfo> list;
+
+	public TxGroup() {
+		list = new ArrayList<TxInfo>();
+	}
+
+	public static TxGroup parser(String json) {
+		try {
+			JSONObject jsonObject = JSONObject.parseObject(json);
+			TxGroup txGroup = new TxGroup();
+			txGroup.setGroupId(jsonObject.getString("g"));
+			txGroup.setStartTime(jsonObject.getLong("st"));
+			txGroup.setNowTime(jsonObject.getLong("nt"));
+			txGroup.setState(jsonObject.getInteger("s"));
+			txGroup.setIsCompensate(jsonObject.getInteger("i"));
+			txGroup.setRollback(jsonObject.getInteger("r"));
+			txGroup.setHasOver(jsonObject.getInteger("o"));
+			JSONArray array = jsonObject.getJSONArray("l");
+			int length = array.size();
+			for (int i = 0; i < length; i++) {
+				JSONObject object = array.getJSONObject(i);
+				TxInfo info = new TxInfo();
+				info.setKid(object.getString("k"));
+				info.setChannelAddress(object.getString("ca"));
+				info.setNotify(object.getInteger("n"));
+				info.setIsGroup(object.getInteger("ig"));
+				info.setAddress(object.getString("a"));
+				info.setUniqueKey(object.getString("u"));
+
+				info.setModel(object.getString("mn"));
+				info.setModelIpAddress(object.getString("ip"));
+				info.setMethodStr(object.getString("ms"));
+
+				txGroup.getList().add(info);
+			}
+			return txGroup;
+
+		} catch (Exception e) {
+			return null;
+		}
+
+	}
+
+	public String getGroupId() {
+		return groupId;
+	}
+
+	public void setGroupId(String groupId) {
+		this.groupId = groupId;
+	}
+
+	public List<TxInfo> getList() {
+		return list;
+	}
+
+	public void setList(List<TxInfo> list) {
+		this.list = list;
+	}
+
+	public long getStartTime() {
+		return startTime;
+	}
+
+	public void setStartTime(long startTime) {
+		this.startTime = startTime;
+	}
+
+	public int getIsCompensate() {
+		return isCompensate;
+	}
+
+	public void setIsCompensate(int isCompensate) {
+		this.isCompensate = isCompensate;
+	}
+
+	public int getState() {
+		return state;
+	}
+
+	public void setState(int state) {
+		this.state = state;
+	}
+
+	public void addTransactionInfo(TxInfo info) {
+		list.add(info);
+	}
+
+	public long getNowTime() {
+		return nowTime;
+	}
+
+	public void setNowTime(long nowTime) {
+		this.nowTime = nowTime;
+	}
+
+	public int getHasOver() {
+		return hasOver;
+	}
+
+	public void setHasOver(int hasOver) {
+		this.hasOver = hasOver;
+	}
+
+	public int getRollback() {
+		return rollback;
+	}
+
+	public void setRollback(int rollback) {
+		this.rollback = rollback;
+	}
+
+	public String toJsonString(boolean noList) {
+		JSONObject jsonObject = new JSONObject();
+		jsonObject.put("g", getGroupId());
+		jsonObject.put("st", getStartTime());
+		jsonObject.put("nt", getNowTime());
+		jsonObject.put("s", getState());
+		jsonObject.put("i", getIsCompensate());
+		jsonObject.put("r", getRollback());
+		jsonObject.put("o", getHasOver());
+		if (noList) {
+			JSONArray jsonArray = new JSONArray();
+			for (TxInfo info : getList()) {
+				JSONObject item = new JSONObject();
+				item.put("k", info.getKid());
+				item.put("ca", info.getChannelAddress());
+				item.put("n", info.getNotify());
+				item.put("ig", info.getIsGroup());
+				item.put("a", info.getAddress());
+				item.put("u", info.getUniqueKey());
+
+				item.put("mn", info.getModel());
+				item.put("ip", info.getModelIpAddress());
+				item.put("ms", info.getMethodStr());
+
+
+				jsonArray.add(item);
+			}
+			jsonObject.put("l", jsonArray);
+		}
+		return jsonObject.toString();
+	}
+
+	public String toJsonString() {
+		return toJsonString(true);
+	}
+}

+ 191 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/model/TxInfo.java

@@ -0,0 +1,191 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.netty.model;
+
+import com.alibaba.fastjson.JSONObject;
+import com.lorne.core.framework.model.JsonModel;
+import com.pig4cloud.pigx.manager.model.ChannelSender;
+
+/**
+ * Created by lorne on 2017/6/7.
+ */
+public class TxInfo extends JsonModel {
+
+	/**
+	 * 任务唯一标示
+	 */
+	private String kid;
+
+	/**
+	 * 模块管道名称(netty管道名称)
+	 */
+	private String channelAddress;
+
+	/**
+	 * 是否通知成功
+	 */
+	private int notify;
+
+	/**
+	 * 0 不组合
+	 * 1 组合
+	 */
+	private int isGroup;
+
+	/**
+	 * tm识别标示
+	 */
+	private String address;
+
+	/**
+	 * tx识别标示
+	 */
+	private String uniqueKey;
+
+
+	/**
+	 * 管道发送数据
+	 */
+	private ChannelSender channel;
+
+
+	/**
+	 * 业务方法名称
+	 */
+	private String methodStr;
+
+	/**
+	 * 模块名称
+	 */
+	private String model;
+
+	/**
+	 * 模块地址
+	 */
+	private String modelIpAddress;
+
+	/**
+	 * 是否提交(临时数据)
+	 */
+	private int isCommit;
+
+	public int getIsCommit() {
+		return isCommit;
+	}
+
+	public void setIsCommit(int isCommit) {
+		this.isCommit = isCommit;
+	}
+
+	public String getMethodStr() {
+		return methodStr;
+	}
+
+	public void setMethodStr(String methodStr) {
+		this.methodStr = methodStr;
+	}
+
+	public String getModel() {
+		return model;
+	}
+
+	public void setModel(String model) {
+		this.model = model;
+	}
+
+	public String getModelIpAddress() {
+		return modelIpAddress;
+	}
+
+	public void setModelIpAddress(String modelIpAddress) {
+		this.modelIpAddress = modelIpAddress;
+	}
+
+	public String getKid() {
+		return kid;
+	}
+
+	public void setKid(String kid) {
+		this.kid = kid;
+	}
+
+	public ChannelSender getChannel() {
+		return channel;
+	}
+
+	public void setChannel(ChannelSender channel) {
+		this.channel = channel;
+	}
+
+	public String getChannelAddress() {
+		return channelAddress;
+	}
+
+	public void setChannelAddress(String channelAddress) {
+		this.channelAddress = channelAddress;
+	}
+
+	public int getNotify() {
+		return notify;
+	}
+
+	public void setNotify(int notify) {
+		this.notify = notify;
+	}
+
+	public int getIsGroup() {
+		return isGroup;
+	}
+
+	public void setIsGroup(int isGroup) {
+		this.isGroup = isGroup;
+	}
+
+	public String getAddress() {
+		return address;
+	}
+
+	public void setAddress(String address) {
+		this.address = address;
+	}
+
+	public String getUniqueKey() {
+		return uniqueKey;
+	}
+
+	public void setUniqueKey(String uniqueKey) {
+		this.uniqueKey = uniqueKey;
+	}
+
+	@Override
+	public String toString() {
+		JSONObject jsonObject = new JSONObject();
+		jsonObject.put("kid", getKid());
+		jsonObject.put("channelAddress", getChannelAddress());
+		jsonObject.put("notify", getNotify());
+		jsonObject.put("isGroup", getIsGroup());
+		jsonObject.put("address", getAddress());
+		jsonObject.put("uniqueKey", getUniqueKey());
+
+		jsonObject.put("model", getModel());
+		jsonObject.put("modelIpAddress", getModelIpAddress());
+		jsonObject.put("methodStr", getMethodStr());
+
+		return jsonObject.toString();
+	}
+}

+ 30 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/IActionService.java

@@ -0,0 +1,30 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.netty.service;
+
+import com.alibaba.fastjson.JSONObject;
+
+/**
+ * create by lorne on 2017/11/11
+ */
+public interface IActionService {
+
+
+	String execute(String channelAddress, String key, JSONObject params);
+
+}

+ 30 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/NettyServerService.java

@@ -0,0 +1,30 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.netty.service;
+
+/**
+ * Created by lorne on 2017/6/30.
+ */
+public interface NettyServerService {
+
+	void start();
+
+	void close();
+
+
+}

+ 27 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/NettyService.java

@@ -0,0 +1,27 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.netty.service;
+
+/**
+ * create by lorne on 2017/11/11
+ */
+public interface NettyService {
+
+
+	IActionService getActionService(String action);
+}

+ 56 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/ActionATGServiceImpl.java

@@ -0,0 +1,56 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.netty.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.pig4cloud.pigx.manager.manager.service.TxManagerService;
+import com.pig4cloud.pigx.manager.netty.model.TxGroup;
+import com.pig4cloud.pigx.manager.netty.service.IActionService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * 添加事务组
+ * create by lorne on 2017/11/11
+ */
+@Service(value = "atg")
+public class ActionATGServiceImpl implements IActionService {
+
+
+	@Autowired
+	private TxManagerService txManagerService;
+
+	@Override
+	public String execute(String channelAddress, String key, JSONObject params) {
+		String res = "";
+		String groupId = params.getString("g");
+		String taskId = params.getString("t");
+		String methodStr = params.getString("ms");
+		int isGroup = params.getInteger("s");
+
+		TxGroup txGroup = txManagerService.addTransactionGroup(groupId, taskId, isGroup, channelAddress, methodStr);
+
+		if (txGroup != null) {
+			txGroup.setNowTime(System.currentTimeMillis());
+			res = txGroup.toJsonString(false);
+		} else {
+			res = "";
+		}
+		return res;
+	}
+}

+ 51 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/ActionCGServiceImpl.java

@@ -0,0 +1,51 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.netty.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.pig4cloud.pigx.manager.manager.service.TxManagerService;
+import com.pig4cloud.pigx.manager.netty.model.TxGroup;
+import com.pig4cloud.pigx.manager.netty.service.IActionService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * 创建事务组
+ * create by lorne on 2017/11/11
+ */
+@Service(value = "cg")
+public class ActionCGServiceImpl implements IActionService {
+
+
+	@Autowired
+	private TxManagerService txManagerService;
+
+	@Override
+	public String execute(String channelAddress, String key, JSONObject params) {
+		String res = "";
+		String groupId = params.getString("g");
+		TxGroup txGroup = txManagerService.createTransactionGroup(groupId);
+		if (txGroup != null) {
+			txGroup.setNowTime(System.currentTimeMillis());
+			res = txGroup.toJsonString(false);
+		} else {
+			res = "";
+		}
+		return res;
+	}
+}

+ 47 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/ActionCKGServiceImpl.java

@@ -0,0 +1,47 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.netty.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.pig4cloud.pigx.manager.manager.service.TxManagerService;
+import com.pig4cloud.pigx.manager.netty.service.IActionService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * 检查事务组
+ * create by lorne on 2017/11/11
+ */
+@Service(value = "ckg")
+public class ActionCKGServiceImpl implements IActionService {
+
+
+	@Autowired
+	private TxManagerService txManagerService;
+
+	@Override
+	public String execute(String channelAddress, String key, JSONObject params) {
+		String res = "";
+		String groupId = params.getString("g");
+		String taskId = params.getString("t");
+		int bs = txManagerService.cleanNotifyTransaction(groupId, taskId);
+
+		res = String.valueOf(bs);
+		return res;
+	}
+}

+ 31 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/ActionCServiceImpl.java

@@ -0,0 +1,31 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.netty.service.impl;
+
+import com.pig4cloud.pigx.manager.netty.service.IActionService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 补偿回调
+ * create by lorne on 2017/11/11
+ */
+@Service(value = "c")
+public class ActionCServiceImpl extends BaseSignalTaskService implements IActionService {
+
+
+}

+ 44 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/ActionCTGServiceImpl.java

@@ -0,0 +1,44 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.netty.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.pig4cloud.pigx.manager.manager.service.TxManagerService;
+import com.pig4cloud.pigx.manager.netty.service.IActionService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * 关闭事务组
+ * create by lorne on 2017/11/11
+ */
+@Service(value = "ctg")
+public class ActionCTGServiceImpl implements IActionService {
+
+
+	@Autowired
+	private TxManagerService txManagerService;
+
+	@Override
+	public String execute(String channelAddress, String key, JSONObject params) {
+		String groupId = params.getString("g");
+		int state = params.getInteger("s");
+		String res = String.valueOf(txManagerService.closeTransactionGroup(groupId, state));
+		return res;
+	}
+}

+ 53 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/ActionGLBServiceImpl.java

@@ -0,0 +1,53 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.netty.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.pig4cloud.pigx.manager.manager.service.LoadBalanceService;
+import com.pig4cloud.pigx.manager.model.LoadBalanceInfo;
+import com.pig4cloud.pigx.manager.netty.service.IActionService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * 获取负载模块信息
+ * create by lorne on 2017/11/11
+ */
+@Service(value = "glb")
+public class ActionGLBServiceImpl implements IActionService {
+
+
+	@Autowired
+	private LoadBalanceService loadBalanceService;
+
+
+	@Override
+	public String execute(String channelAddress, String key, JSONObject params) {
+		String res;
+		String groupId = params.getString("g");
+		String k = params.getString("k");
+
+		LoadBalanceInfo loadBalanceInfo = loadBalanceService.get(groupId, k);
+		if (loadBalanceInfo == null) {
+			res = "";
+		} else {
+			res = loadBalanceInfo.getData();
+		}
+		return res;
+	}
+}

+ 41 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/ActionHServiceImpl.java

@@ -0,0 +1,41 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.netty.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.pig4cloud.pigx.manager.config.ConfigReader;
+import com.pig4cloud.pigx.manager.netty.service.IActionService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * 心跳包
+ * create by lorne on 2017/11/11
+ */
+@Service(value = "h")
+public class ActionHServiceImpl implements IActionService {
+
+
+	@Autowired
+	private ConfigReader configReader;
+
+	@Override
+	public String execute(String channelAddress, String key, JSONObject params) {
+		return String.valueOf(configReader.getTransactionNettyDelayTime());
+	}
+}

+ 54 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/ActionPLBServiceImpl.java

@@ -0,0 +1,54 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.netty.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.pig4cloud.pigx.manager.manager.service.LoadBalanceService;
+import com.pig4cloud.pigx.manager.model.LoadBalanceInfo;
+import com.pig4cloud.pigx.manager.netty.service.IActionService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * 添加负载模块信息
+ * create by lorne on 2017/11/11
+ */
+@Service(value = "plb")
+public class ActionPLBServiceImpl implements IActionService {
+
+
+	@Autowired
+	private LoadBalanceService loadBalanceService;
+
+
+	@Override
+	public String execute(String channelAddress, String key, JSONObject params) {
+
+		String groupId = params.getString("g");
+		String k = params.getString("k");
+		String data = params.getString("d");
+
+		LoadBalanceInfo loadBalanceInfo = new LoadBalanceInfo();
+		loadBalanceInfo.setData(data);
+		loadBalanceInfo.setKey(k);
+		loadBalanceInfo.setGroupId(groupId);
+		boolean ok = loadBalanceService.put(loadBalanceInfo);
+
+		return ok ? "1" : "0";
+	}
+}

+ 45 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/ActionRGServiceImpl.java

@@ -0,0 +1,45 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.netty.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.pig4cloud.pigx.manager.manager.service.TxManagerService;
+import com.pig4cloud.pigx.manager.netty.service.IActionService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * 强制回滚事务组
+ * create by lorne on 2017/11/11
+ */
+@Service(value = "rg")
+public class ActionRGServiceImpl implements IActionService {
+
+
+	@Autowired
+	private TxManagerService txManagerService;
+
+	@Override
+	public String execute(String channelAddress, String key, JSONObject params) {
+		String res = "";
+		String groupId = params.getString("g");
+		boolean bs = txManagerService.rollbackTransactionGroup(groupId);
+		res = bs ? "1" : "0";
+		return res;
+	}
+}

+ 31 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/ActionTServiceImpl.java

@@ -0,0 +1,31 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.netty.service.impl;
+
+import com.pig4cloud.pigx.manager.netty.service.IActionService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 通知事务回调
+ * create by lorne on 2017/11/11
+ */
+@Service(value = "t")
+public class ActionTServiceImpl extends BaseSignalTaskService implements IActionService {
+
+
+}

+ 56 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/ActionUMIServiceImpl.java

@@ -0,0 +1,56 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.netty.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.pig4cloud.pigx.manager.framework.utils.SocketManager;
+import com.pig4cloud.pigx.manager.manager.ModelInfoManager;
+import com.pig4cloud.pigx.manager.model.ModelInfo;
+import com.pig4cloud.pigx.manager.netty.service.IActionService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 上传模块信息
+ * create by lorne on 2017/11/11
+ */
+@Service(value = "umi")
+public class ActionUMIServiceImpl implements IActionService {
+
+
+	@Override
+	public String execute(String channelAddress, String key, JSONObject params) {
+		String res = "1";
+
+		String uniqueKey = params.getString("u");
+		String ipAddress = params.getString("i");
+		String model = params.getString("m");
+
+
+		ModelInfo modelInfo = new ModelInfo();
+		modelInfo.setChannelName(channelAddress);
+		modelInfo.setIpAddress(ipAddress);
+		modelInfo.setModel(model);
+		modelInfo.setUniqueKey(uniqueKey);
+
+		ModelInfoManager.getInstance().addModelInfo(modelInfo);
+
+		SocketManager.getInstance().onLine(channelAddress, uniqueKey);
+
+		return res;
+	}
+}

+ 45 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/BaseSignalTaskService.java

@@ -0,0 +1,45 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.netty.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.lorne.core.framework.utils.task.ConditionUtils;
+import com.lorne.core.framework.utils.task.IBack;
+import com.lorne.core.framework.utils.task.Task;
+
+/**
+ * create by lorne on 2017/11/13
+ */
+public class BaseSignalTaskService {
+
+	public String execute(String channelAddress, String key, JSONObject params) {
+		String res = "";
+		final String data = params.getString("d");
+		Task task = ConditionUtils.getInstance().getTask(key);
+		if (task != null) {
+			task.setBack(new IBack() {
+				@Override
+				public Object doing(Object... objs) throws Throwable {
+					return data;
+				}
+			});
+			task.signalTask();
+		}
+		return res;
+	}
+}

+ 120 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/NettyServerServiceImpl.java

@@ -0,0 +1,120 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.netty.service.impl;
+
+import com.pig4cloud.pigx.manager.config.ConfigReader;
+import com.pig4cloud.pigx.manager.framework.utils.Constants;
+import com.pig4cloud.pigx.manager.netty.handler.TxCoreServerHandler;
+import com.pig4cloud.pigx.manager.netty.service.NettyServerService;
+import com.pig4cloud.pigx.manager.netty.service.NettyService;
+import io.netty.bootstrap.ServerBootstrap;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.nio.NioServerSocketChannel;
+import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
+import io.netty.handler.codec.LengthFieldPrepender;
+import io.netty.handler.logging.LogLevel;
+import io.netty.handler.logging.LoggingHandler;
+import io.netty.handler.timeout.IdleStateHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Created by lorne on 2017/6/30.
+ */
+@Service
+public class NettyServerServiceImpl implements NettyServerService, DisposableBean {
+
+
+	@Autowired
+	private NettyService nettyService;
+
+	private Logger logger = LoggerFactory.getLogger(NettyServerServiceImpl.class);
+
+	private EventLoopGroup bossGroup;
+	private EventLoopGroup workerGroup;
+
+	private TxCoreServerHandler txCoreServerHandler;
+
+	private ExecutorService threadPool = Executors.newFixedThreadPool(100);
+
+	@Autowired
+	private ConfigReader configReader;
+
+
+	@Override
+	public void start() {
+		final int heartTime = configReader.getTransactionNettyHeartTime() + 10;
+		txCoreServerHandler = new TxCoreServerHandler(threadPool, nettyService);
+		bossGroup = new NioEventLoopGroup(50); // (1)
+		workerGroup = new NioEventLoopGroup();
+		try {
+			ServerBootstrap b = new ServerBootstrap();
+			b.group(bossGroup, workerGroup)
+				.channel(NioServerSocketChannel.class)
+				.option(ChannelOption.SO_BACKLOG, 100)
+				.handler(new LoggingHandler(LogLevel.INFO))
+				.childHandler(new ChannelInitializer<SocketChannel>() {
+					@Override
+					public void initChannel(SocketChannel ch) throws Exception {
+						ch.pipeline().addLast("timeout", new IdleStateHandler(heartTime, heartTime, heartTime, TimeUnit.SECONDS));
+
+						ch.pipeline().addLast(new LengthFieldPrepender(4, false));
+						ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
+
+						ch.pipeline().addLast(txCoreServerHandler);
+					}
+				});
+
+			// Start the server.
+			b.bind(Constants.socketPort);
+			logger.info("Socket started on port(s): " + Constants.socketPort + " (socket)");
+
+		} catch (Exception e) {
+			// Shut down all event loops to terminate all threads.
+			e.printStackTrace();
+		}
+	}
+
+	@Override
+	public void close() {
+		if (workerGroup != null) {
+			workerGroup.shutdownGracefully();
+		}
+		if (bossGroup != null) {
+			bossGroup.shutdownGracefully();
+		}
+
+	}
+
+	@Override
+	public void destroy() throws Exception {
+		close();
+		threadPool.shutdown();
+	}
+}

+ 39 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/netty/service/impl/NettyServiceImpl.java

@@ -0,0 +1,39 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.netty.service.impl;
+
+import com.pig4cloud.pigx.manager.netty.service.IActionService;
+import com.pig4cloud.pigx.manager.netty.service.NettyService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.stereotype.Service;
+
+/**
+ * create by lorne on 2017/11/11
+ */
+@Service
+public class NettyServiceImpl implements NettyService {
+
+	@Autowired
+	private ApplicationContext spring;
+
+	@Override
+	public IActionService getActionService(String action) {
+		return spring.getBean(action, IActionService.class);
+	}
+}

+ 6 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/pack-info.md

@@ -0,0 +1,6 @@
+由于LCN 暂未发布适配 2.0 版本  
+当前包是根据TCN tx-manager 模块修改而来 ,重构部分代码
+解决LCN 不兼容 Spring Cloud Finchley 问题
+
+关于LCN  
+https://github.com/codingapi/tx-lcn

+ 52 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/redis/RedisServerService.java

@@ -0,0 +1,52 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.redis;
+
+
+import com.pig4cloud.pigx.manager.netty.model.TxGroup;
+
+import java.util.List;
+
+/**
+ * create by lorne on 2017/11/11
+ */
+public interface RedisServerService {
+
+	String loadNotifyJson();
+
+	void saveTransaction(String key, String json);
+
+	TxGroup getTxGroupByKey(String key);
+
+	void saveCompensateMsg(String name, String json);
+
+	List<String> getKeys(String key);
+
+	List<String> getValuesByKeys(List<String> keys);
+
+	String getValueByKey(String key);
+
+	void deleteKey(String key);
+
+	void saveLoadBalance(String groupName, String key, String data);
+
+
+	String getLoadBalance(String groupName, String key);
+
+
+}

+ 132 - 0
pigx-visual/pigx-tx-manager/src/main/java/com/pig4cloud/pigx/manager/redis/impl/RedisServerServiceImpl.java

@@ -0,0 +1,132 @@
+/*
+ *    Copyright (c) 2018-2025, lengleng All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the pig4cloud.com developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: lengleng (wangiegie@gmail.com)
+ */
+
+package com.pig4cloud.pigx.manager.redis.impl;
+
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.pig4cloud.pigx.manager.config.ConfigReader;
+import com.pig4cloud.pigx.manager.netty.model.TxGroup;
+import com.pig4cloud.pigx.manager.redis.RedisServerService;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.HashOperations;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.ValueOperations;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * create by lorne on 2017/11/11
+ */
+@Service
+public class RedisServerServiceImpl implements RedisServerService {
+
+	@Autowired
+	private RedisTemplate<String, String> redisTemplate;
+
+	@Autowired
+	private ConfigReader configReader;
+
+	@Override
+	public String loadNotifyJson() {
+		Set<String> keys = redisTemplate.keys(configReader.getKeyPrefixCompensate() + "*");
+		ValueOperations<String, String> value = redisTemplate.opsForValue();
+		JSONArray jsonArray = new JSONArray();
+		for (String key : keys) {
+			String json = value.get(key);
+			JSONObject jsonObject = new JSONObject();
+			jsonObject.put("key", key);
+			jsonObject.put("value", JSONObject.parse(json));
+			jsonArray.add(jsonObject);
+		}
+		return jsonArray.toJSONString();
+	}
+
+	@Override
+	public void saveTransaction(String key, String json) {
+		ValueOperations<String, String> value = redisTemplate.opsForValue();
+		value.set(key, json, configReader.getRedisSaveMaxTime(), TimeUnit.SECONDS);
+	}
+
+
+	@Override
+	public TxGroup getTxGroupByKey(String key) {
+		ValueOperations<String, String> value = redisTemplate.opsForValue();
+		String json = value.get(key);
+		if (StringUtils.isEmpty(json)) {
+			return null;
+		}
+		return TxGroup.parser(json);
+	}
+
+
+	@Override
+	public void saveCompensateMsg(String name, String json) {
+		ValueOperations<String, String> value = redisTemplate.opsForValue();
+		value.set(name, json);
+	}
+
+	@Override
+	public List<String> getKeys(String key) {
+		Set<String> keys = redisTemplate.keys(key);
+		List<String> list = new ArrayList<String>();
+		for (String k : keys) {
+			list.add(k);
+		}
+		return list;
+	}
+
+	@Override
+	public List<String> getValuesByKeys(List<String> keys) {
+		ValueOperations<String, String> value = redisTemplate.opsForValue();
+		List<String> list = new ArrayList<>();
+		for (String key : keys) {
+			String json = value.get(key);
+			list.add(json);
+		}
+		return list;
+	}
+
+	@Override
+	public String getValueByKey(String key) {
+		ValueOperations<String, String> value = redisTemplate.opsForValue();
+		return value.get(key);
+	}
+
+	@Override
+	public void deleteKey(String key) {
+		redisTemplate.delete(key);
+	}
+
+	@Override
+	public void saveLoadBalance(String groupName, String key, String data) {
+		HashOperations<String, String, String> value = redisTemplate.opsForHash();
+		value.put(groupName, key, data);
+	}
+
+
+	@Override
+	public String getLoadBalance(String groupName, String key) {
+		HashOperations<String, String, String> value = redisTemplate.opsForHash();
+		return value.get(groupName, key);
+	}
+}

+ 24 - 0
pigx-visual/pigx-tx-manager/src/main/resources/bootstrap.yml

@@ -0,0 +1,24 @@
+server:
+  port: 7000
+
+spring:
+  application:
+    name: pigx-tx-manager
+  #配置中心
+  cloud:
+    config:
+      fail-fast: true
+      name: ${spring.application.name}
+      profile: dev
+      discovery:
+        enabled: true
+        service-id: pigx-config
+
+# 注册中心配置
+eureka:
+  instance:
+    prefer-ip-address: true
+  client:
+    service-url:
+      defaultZone: http://pig:pig@localhost:1025/eureka/
+

+ 139 - 0
pigx-visual/pigx-tx-manager/src/main/resources/static/index.html

@@ -0,0 +1,139 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8"/>
+  <title>TxManager v4.1.0</title>
+  <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
+  <link rel="stylesheet" href="static/bootstrap/css/bootstrap.min.css"/>
+  <script src="static/jquery/jquery.min.js"></script>
+  <script src="static/jquery/jquery.blockUI.min.js"></script>
+  <script src="static/jquery/jquery.blockUI-css.js"></script>
+  <script src="static/common/common.js"></script>
+  <script src="static/common/http.js"></script>
+  <link rel="shortcut icon" href="static/images/logo.png">
+
+  <style>
+    .container {
+      margin-top: 20px;
+    }
+
+    .table-responsive {
+      margin-top: 30px;
+    }
+  </style>
+</head>
+<body>
+<div class="container">
+
+  <h3 class="text-center">TxManagerV4.1.0 服务已启动</h3>
+  <div class="table-responsive">
+    <table class="table table-bordered table-striped">
+      <colgroup>
+        <col class="col-xs-4"/>
+        <col class="col-xs-8"/>
+      </colgroup>
+      <thead>
+      <tr>
+        <th>属性名称</th>
+        <th>属性值</th>
+      </tr>
+      </thead>
+      <tbody>
+      <tr>
+        <th scope="row">
+          Socket对外服务IP
+        </th>
+        <td><span id="ip"></span></td>
+      </tr>
+      <tr>
+        <th scope="row">
+          Socket对外服务端口
+        </th>
+        <td><span id="port"></span></td>
+      </tr>
+      <tr>
+        <th scope="row">
+          最大连接数
+        </th>
+        <td><span id="maxConnection"></span></td>
+      </tr>
+      <tr>
+        <th scope="row">
+          当前连接数
+        </th>
+        <td><span id="nowConnection"></span></td>
+      </tr>
+      <tr>
+        <th scope="row">
+          TxManager模块心跳间隔时间(秒)
+        </th>
+        <td><span id="transactionNettyHeartTime"></span></td>
+      </tr>
+      <tr>
+        <th scope="row">
+          TxManager模块通讯最大等待时间(秒)
+        </th>
+        <td><span id="transactionNettyDelayTime"></span></td>
+      </tr>
+      <tr>
+        <th scope="row">
+          redis服务状态
+        </th>
+        <td><span id="redisState"></span></td>
+      </tr>
+      <tr>
+        <th scope="row">
+          redis存储最大时间(秒)
+        </th>
+        <td><span id="redisSaveMaxTime"></span></td>
+      </tr>
+      <tr>
+        <th scope="row">
+          负载均衡服务器地址
+        </th>
+        <td><span id="slbList"></span></td>
+      </tr>
+      <tr>
+        <th scope="row">
+          补偿回调地址(rest api 地址,post json格式)
+        </th>
+        <td><span id="notifyUrl"></span></td>
+      </tr>
+      <tr>
+        <th scope="row">
+          存在补偿数据
+        </th>
+        <td><span id="hasCompensate"></span></td>
+      </tr>
+      <tr>
+        <th scope="row">
+          开启自动补偿(true 开启,false 关闭)
+        </th>
+        <td><span id="compensate"></span></td>
+      </tr>
+      <tr>
+        <th scope="row">
+          补偿失败尝试间隔时间(秒)
+        </th>
+        <td><span id="compensateTryTime"></span></td>
+      </tr>
+      <tr>
+        <th scope="row">
+          各事务模块自动补偿的时间上限(毫秒)
+        </th>
+        <td><span id="compensateMaxWaitTime"></span></td>
+      </tr>
+      </tbody>
+    </table>
+
+
+    <a href="model.html" style="margin-left: 20px;" class="btn btn-info pull-right">在线模块</a>
+    <a href="log.html" class="btn btn-warning pull-right">事务补偿</a>
+
+  </div>
+
+
+  <script src="static/index.js"></script>
+</div>
+</body>
+</html>

+ 192 - 0
pigx-visual/pigx-tx-manager/src/main/resources/static/log.html

@@ -0,0 +1,192 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8"/>
+  <title>事务补偿</title>
+  <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
+  <link rel="stylesheet" href="static/bootstrap/css/bootstrap.min.css"/>
+  <script src="static/jquery/jquery.min.js"></script>
+  <script src="static/bootstrap/js/bootstrap.min.js"></script>
+  <script src="static/jquery/jquery.blockUI.min.js"></script>
+  <script src="static/jquery/jquery.blockUI-css.js"></script>
+  <script src="static/common/jbase64.js"></script>
+  <script src="static/common/common.js"></script>
+  <script src="static/common/http.js"></script>
+  <link rel="shortcut icon" href="static/images/logo.png">
+
+  <style>
+    .container-fluid {
+      margin-top: 20px;
+    }
+
+    .table-responsive {
+      margin-top: 30px;
+      text-align: center;
+    }
+
+    th {
+
+      text-align: center;
+    }
+  </style>
+</head>
+<body>
+<div class="container-fluid">
+
+  <a class="pull-right" href="index.html">返回首页</a>
+
+  <div class="text text-danger">
+    说明:</br>
+    补偿记录展示的数据是分布事务发起方的切面数据信息。</br>
+    记录时间是指发起方出现补偿时记录下的时间,并非是TxManager的记录数据的时间。</br>
+  </div>
+
+  <input type="hidden" id="model"/>
+
+  <div class="row">
+    <div class="col-lg-2 col-md-2">
+      <div class="table-responsive">
+        <table class="table table-bordered table-striped">
+          <colgroup>
+            <col class="col-xs-8"/>
+            <col class="col-xs-4"/>
+          </colgroup>
+          <thead>
+          <tr>
+            <th>模块名称</th>
+            <th>条数</th>
+          </tr>
+          </thead>
+          <tbody id="list">
+          <tr>
+            <td><span></span></td>
+            <td><span></span></td>
+          </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+
+    <div class="col-lg-1 col-md-1" style="margin: 0;padding: 0">
+      <div class="table-responsive">
+        <table class="table table-bordered table-striped">
+          <colgroup>
+            <col class="col-xs-12"/>
+          </colgroup>
+          <thead>
+          <tr>
+            <th>记录日期</th>
+          </tr>
+          </thead>
+          <tbody id="logs">
+          <tr>
+            <td><span></span></td>
+          </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+    <div class="col-lg-9 col-md-9">
+      <div class="table-responsive">
+        <table class="table table-bordered table-striped">
+          <colgroup>
+            <col class="col-xs-2"/>
+            <col class="col-xs-6"/>
+            <col class="col-xs-1"/>
+            <col class="col-xs-3"/>
+          </colgroup>
+          <thead>
+          <tr>
+            <th>记录时间</th>
+            <th>执行方法</th>
+            <th>执行时间</th>
+            <th>操作</th>
+          </tr>
+          </thead>
+          <tbody id="compensate">
+          <tr>
+            <td><span></span></td>
+            <td><span></span></td>
+            <td><span></span></td>
+            <td><span></span></td>
+          </tr>
+          </tbody>
+        </table>
+      </div>
+    </div>
+  </div>
+
+
+  <!-- Modal -->
+  <div class="modal fade " style="width: 95%;margin: 0 2% 0 2%" id="show-modal" tabindex="-1" role="dialog"
+       aria-labelledby="myModalLabel">
+    <div class="modal-dialog" role="document" style="width: 100%">
+      <div class="modal-content">
+        <div class="modal-header">
+          <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
+            aria-hidden="true">&times;</span></button>
+          <h4 class="modal-title" id="myModalLabel">详细信息</h4>
+        </div>
+        <div class="modal-body">
+          <div class="text text-danger" style="padding: 0 0 5px 12px">
+            补偿详细说明:</br>
+            模块唯一标示:是由模块的ip+port然后md5加密得来,用于LCN系统的模块唯一识别码</br>
+            事务ID:事务组信息的唯一标示</br>
+            模块名称列表说明,该记录的数据未必是模块的完整调用曲线数据,没有事务的业务模块是不记录数据的。</br>
+            例如:参与模块 a b c d ,若a模块是发起方,执行顺序是a->b->c->d,若b事务是只读的,c没有事务,仅有d模块有事务。那么实际记录的模块数据仅会记录d模块的数据。
+          </div>
+          <table class="table table-bordered table-striped">
+            <colgroup>
+              <col class="col-xs-2"/>
+              <col class="col-xs-4"/>
+              <col class="col-xs-2"/>
+              <col class="col-xs-4"/>
+            </colgroup>
+            <thead>
+            <tr>
+              <th>属性名称</th>
+              <th>属性值</th>
+              <th>属性名称</th>
+              <th>属性值</th>
+            </tr>
+            </thead>
+            <tbody id="body">
+
+            </tbody>
+          </table>
+        </div>
+        <div class="modal-footer">
+          <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
+        </div>
+      </div>
+    </div>
+  </div>
+
+
+  <!-- Modal -->
+  <div class="modal fade " id="show-alert" tabindex="-1" role="dialog"
+       aria-labelledby="myModalLabel">
+    <div class="modal-dialog" role="document">
+      <div class="modal-content">
+        <div class="modal-header">
+          <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
+            aria-hidden="true">&times;</span></button>
+          <h4 class="modal-title">提醒</h4>
+        </div>
+        <div class="modal-body" id="content">
+          确认要执行吗?
+        </div>
+        <div class="modal-footer">
+          <button type="button" class="btn btn-success" data-event="button" data-dismiss="modal">确认</button>
+          <button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
+        </div>
+      </div>
+    </div>
+  </div>
+
+  <script src="static/log.js"></script>
+
+
+</div>
+</body>
+</html>

+ 65 - 0
pigx-visual/pigx-tx-manager/src/main/resources/static/model.html

@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="UTF-8"/>
+  <title>在线模块</title>
+  <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
+  <link rel="stylesheet" href="static/bootstrap/css/bootstrap.min.css"/>
+  <script src="static/jquery/jquery.min.js"></script>
+  <script src="static/bootstrap/js/bootstrap.min.js"></script>
+  <script src="static/jquery/jquery.blockUI.min.js"></script>
+  <script src="static/jquery/jquery.blockUI-css.js"></script>
+  <script src="static/common/jbase64.js"></script>
+  <script src="static/common/common.js"></script>
+  <script src="static/common/http.js"></script>
+  <link rel="shortcut icon" href="static/images/logo.png">
+
+  <style>
+    .container-fluid {
+      margin-top: 20px;
+    }
+
+    .table-responsive {
+      margin-top: 30px;
+    }
+  </style>
+</head>
+<body>
+<div class="container-fluid">
+
+  <a class="pull-right" href="index.html">返回首页</a>
+
+
+  <div class="table-responsive">
+    <table class="table table-bordered table-striped">
+      <colgroup>
+        <col class="col-xs-3"/>
+        <col class="col-xs-3"/>
+        <col class="col-xs-3"/>
+        <col class="col-xs-3"/>
+      </colgroup>
+      <thead>
+      <tr>
+        <th>模块名称</th>
+        <th>唯一标示</th>
+        <th>模块地址</th>
+        <th>管道名称</th>
+      </tr>
+      </thead>
+      <tbody id="list">
+      <tr>
+        <td><span></span></td>
+        <td><span></span></td>
+        <td><span></span></td>
+        <td><span></span></td>
+      </tr>
+      </tbody>
+    </table>
+  </div>
+
+  <script src="static/model.js"></script>
+
+
+</div>
+</body>
+</html>

+ 650 - 0
pigx-visual/pigx-tx-manager/src/main/resources/static/static/bootstrap/css/bootstrap-theme.css

@@ -0,0 +1,650 @@
+/*!
+ * Bootstrap v3.3.7 (http://getbootstrap.com)
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+.btn-default,
+.btn-primary,
+.btn-success,
+.btn-info,
+.btn-warning,
+.btn-danger {
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, .2);
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
+  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075);
+}
+
+.btn-default:active,
+.btn-primary:active,
+.btn-success:active,
+.btn-info:active,
+.btn-warning:active,
+.btn-danger:active,
+.btn-default.active,
+.btn-primary.active,
+.btn-success.active,
+.btn-info.active,
+.btn-warning.active,
+.btn-danger.active {
+  -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+  box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125);
+}
+
+.btn-default.disabled,
+.btn-primary.disabled,
+.btn-success.disabled,
+.btn-info.disabled,
+.btn-warning.disabled,
+.btn-danger.disabled,
+.btn-default[disabled],
+.btn-primary[disabled],
+.btn-success[disabled],
+.btn-info[disabled],
+.btn-warning[disabled],
+.btn-danger[disabled],
+fieldset[disabled] .btn-default,
+fieldset[disabled] .btn-primary,
+fieldset[disabled] .btn-success,
+fieldset[disabled] .btn-info,
+fieldset[disabled] .btn-warning,
+fieldset[disabled] .btn-danger {
+  -webkit-box-shadow: none;
+  box-shadow: none;
+}
+
+.btn-default .badge,
+.btn-primary .badge,
+.btn-success .badge,
+.btn-info .badge,
+.btn-warning .badge,
+.btn-danger .badge {
+  text-shadow: none;
+}
+
+.btn:active,
+.btn.active {
+  background-image: none;
+}
+
+.btn-default {
+  text-shadow: 0 1px 0 #fff;
+  background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%);
+  background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0));
+  background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+  background-repeat: repeat-x;
+  border-color: #dbdbdb;
+  border-color: #ccc;
+}
+
+.btn-default:hover,
+.btn-default:focus {
+  background-color: #e0e0e0;
+  background-position: 0 -15px;
+}
+
+.btn-default:active,
+.btn-default.active {
+  background-color: #e0e0e0;
+  border-color: #dbdbdb;
+}
+
+.btn-default.disabled,
+.btn-default[disabled],
+fieldset[disabled] .btn-default,
+.btn-default.disabled:hover,
+.btn-default[disabled]:hover,
+fieldset[disabled] .btn-default:hover,
+.btn-default.disabled:focus,
+.btn-default[disabled]:focus,
+fieldset[disabled] .btn-default:focus,
+.btn-default.disabled.focus,
+.btn-default[disabled].focus,
+fieldset[disabled] .btn-default.focus,
+.btn-default.disabled:active,
+.btn-default[disabled]:active,
+fieldset[disabled] .btn-default:active,
+.btn-default.disabled.active,
+.btn-default[disabled].active,
+fieldset[disabled] .btn-default.active {
+  background-color: #e0e0e0;
+  background-image: none;
+}
+
+.btn-primary {
+  background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);
+  background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#265a88));
+  background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+  background-repeat: repeat-x;
+  border-color: #245580;
+}
+
+.btn-primary:hover,
+.btn-primary:focus {
+  background-color: #265a88;
+  background-position: 0 -15px;
+}
+
+.btn-primary:active,
+.btn-primary.active {
+  background-color: #265a88;
+  border-color: #245580;
+}
+
+.btn-primary.disabled,
+.btn-primary[disabled],
+fieldset[disabled] .btn-primary,
+.btn-primary.disabled:hover,
+.btn-primary[disabled]:hover,
+fieldset[disabled] .btn-primary:hover,
+.btn-primary.disabled:focus,
+.btn-primary[disabled]:focus,
+fieldset[disabled] .btn-primary:focus,
+.btn-primary.disabled.focus,
+.btn-primary[disabled].focus,
+fieldset[disabled] .btn-primary.focus,
+.btn-primary.disabled:active,
+.btn-primary[disabled]:active,
+fieldset[disabled] .btn-primary:active,
+.btn-primary.disabled.active,
+.btn-primary[disabled].active,
+fieldset[disabled] .btn-primary.active {
+  background-color: #265a88;
+  background-image: none;
+}
+
+.btn-success {
+  background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
+  background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641));
+  background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+  background-repeat: repeat-x;
+  border-color: #3e8f3e;
+}
+
+.btn-success:hover,
+.btn-success:focus {
+  background-color: #419641;
+  background-position: 0 -15px;
+}
+
+.btn-success:active,
+.btn-success.active {
+  background-color: #419641;
+  border-color: #3e8f3e;
+}
+
+.btn-success.disabled,
+.btn-success[disabled],
+fieldset[disabled] .btn-success,
+.btn-success.disabled:hover,
+.btn-success[disabled]:hover,
+fieldset[disabled] .btn-success:hover,
+.btn-success.disabled:focus,
+.btn-success[disabled]:focus,
+fieldset[disabled] .btn-success:focus,
+.btn-success.disabled.focus,
+.btn-success[disabled].focus,
+fieldset[disabled] .btn-success.focus,
+.btn-success.disabled:active,
+.btn-success[disabled]:active,
+fieldset[disabled] .btn-success:active,
+.btn-success.disabled.active,
+.btn-success[disabled].active,
+fieldset[disabled] .btn-success.active {
+  background-color: #419641;
+  background-image: none;
+}
+
+.btn-info {
+  background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
+  background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2));
+  background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+  background-repeat: repeat-x;
+  border-color: #28a4c9;
+}
+
+.btn-info:hover,
+.btn-info:focus {
+  background-color: #2aabd2;
+  background-position: 0 -15px;
+}
+
+.btn-info:active,
+.btn-info.active {
+  background-color: #2aabd2;
+  border-color: #28a4c9;
+}
+
+.btn-info.disabled,
+.btn-info[disabled],
+fieldset[disabled] .btn-info,
+.btn-info.disabled:hover,
+.btn-info[disabled]:hover,
+fieldset[disabled] .btn-info:hover,
+.btn-info.disabled:focus,
+.btn-info[disabled]:focus,
+fieldset[disabled] .btn-info:focus,
+.btn-info.disabled.focus,
+.btn-info[disabled].focus,
+fieldset[disabled] .btn-info.focus,
+.btn-info.disabled:active,
+.btn-info[disabled]:active,
+fieldset[disabled] .btn-info:active,
+.btn-info.disabled.active,
+.btn-info[disabled].active,
+fieldset[disabled] .btn-info.active {
+  background-color: #2aabd2;
+  background-image: none;
+}
+
+.btn-warning {
+  background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
+  background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316));
+  background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+  background-repeat: repeat-x;
+  border-color: #e38d13;
+}
+
+.btn-warning:hover,
+.btn-warning:focus {
+  background-color: #eb9316;
+  background-position: 0 -15px;
+}
+
+.btn-warning:active,
+.btn-warning.active {
+  background-color: #eb9316;
+  border-color: #e38d13;
+}
+
+.btn-warning.disabled,
+.btn-warning[disabled],
+fieldset[disabled] .btn-warning,
+.btn-warning.disabled:hover,
+.btn-warning[disabled]:hover,
+fieldset[disabled] .btn-warning:hover,
+.btn-warning.disabled:focus,
+.btn-warning[disabled]:focus,
+fieldset[disabled] .btn-warning:focus,
+.btn-warning.disabled.focus,
+.btn-warning[disabled].focus,
+fieldset[disabled] .btn-warning.focus,
+.btn-warning.disabled:active,
+.btn-warning[disabled]:active,
+fieldset[disabled] .btn-warning:active,
+.btn-warning.disabled.active,
+.btn-warning[disabled].active,
+fieldset[disabled] .btn-warning.active {
+  background-color: #eb9316;
+  background-image: none;
+}
+
+.btn-danger {
+  background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
+  background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a));
+  background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+  background-repeat: repeat-x;
+  border-color: #b92c28;
+}
+
+.btn-danger:hover,
+.btn-danger:focus {
+  background-color: #c12e2a;
+  background-position: 0 -15px;
+}
+
+.btn-danger:active,
+.btn-danger.active {
+  background-color: #c12e2a;
+  border-color: #b92c28;
+}
+
+.btn-danger.disabled,
+.btn-danger[disabled],
+fieldset[disabled] .btn-danger,
+.btn-danger.disabled:hover,
+.btn-danger[disabled]:hover,
+fieldset[disabled] .btn-danger:hover,
+.btn-danger.disabled:focus,
+.btn-danger[disabled]:focus,
+fieldset[disabled] .btn-danger:focus,
+.btn-danger.disabled.focus,
+.btn-danger[disabled].focus,
+fieldset[disabled] .btn-danger.focus,
+.btn-danger.disabled:active,
+.btn-danger[disabled]:active,
+fieldset[disabled] .btn-danger:active,
+.btn-danger.disabled.active,
+.btn-danger[disabled].active,
+fieldset[disabled] .btn-danger.active {
+  background-color: #c12e2a;
+  background-image: none;
+}
+
+.thumbnail,
+.img-thumbnail {
+  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
+  box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
+}
+
+.dropdown-menu > li > a:hover,
+.dropdown-menu > li > a:focus {
+  background-color: #e8e8e8;
+  background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
+  background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
+  background-repeat: repeat-x;
+}
+
+.dropdown-menu > .active > a,
+.dropdown-menu > .active > a:hover,
+.dropdown-menu > .active > a:focus {
+  background-color: #2e6da4;
+  background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+  background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
+  background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
+  background-repeat: repeat-x;
+}
+
+.navbar-default {
+  background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%);
+  background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8));
+  background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+  background-repeat: repeat-x;
+  border-radius: 4px;
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
+  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075);
+}
+
+.navbar-default .navbar-nav > .open > a,
+.navbar-default .navbar-nav > .active > a {
+  background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
+  background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#dbdbdb), to(#e2e2e2));
+  background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);
+  background-repeat: repeat-x;
+  -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
+  box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075);
+}
+
+.navbar-brand,
+.navbar-nav > li > a {
+  text-shadow: 0 1px 0 rgba(255, 255, 255, .25);
+}
+
+.navbar-inverse {
+  background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%);
+  background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222));
+  background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
+  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);
+  background-repeat: repeat-x;
+  border-radius: 4px;
+}
+
+.navbar-inverse .navbar-nav > .open > a,
+.navbar-inverse .navbar-nav > .active > a {
+  background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);
+  background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#080808), to(#0f0f0f));
+  background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);
+  background-repeat: repeat-x;
+  -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
+  box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25);
+}
+
+.navbar-inverse .navbar-brand,
+.navbar-inverse .navbar-nav > li > a {
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, .25);
+}
+
+.navbar-static-top,
+.navbar-fixed-top,
+.navbar-fixed-bottom {
+  border-radius: 0;
+}
+
+@media (max-width: 767px) {
+  .navbar .navbar-nav .open .dropdown-menu > .active > a,
+  .navbar .navbar-nav .open .dropdown-menu > .active > a:hover,
+  .navbar .navbar-nav .open .dropdown-menu > .active > a:focus {
+    color: #fff;
+    background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+    background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+    background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
+    background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
+    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
+    background-repeat: repeat-x;
+  }
+}
+
+.alert {
+  text-shadow: 0 1px 0 rgba(255, 255, 255, .2);
+  -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
+  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05);
+}
+
+.alert-success {
+  background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
+  background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc));
+  background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #b2dba1;
+}
+
+.alert-info {
+  background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
+  background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0));
+  background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #9acfea;
+}
+
+.alert-warning {
+  background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
+  background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0));
+  background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #f5e79e;
+}
+
+.alert-danger {
+  background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
+  background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3));
+  background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #dca7a7;
+}
+
+.progress {
+  background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
+  background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5));
+  background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
+  background-repeat: repeat-x;
+}
+
+.progress-bar {
+  background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);
+  background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#286090));
+  background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);
+  background-repeat: repeat-x;
+}
+
+.progress-bar-success {
+  background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
+  background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44));
+  background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
+  background-repeat: repeat-x;
+}
+
+.progress-bar-info {
+  background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
+  background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5));
+  background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
+  background-repeat: repeat-x;
+}
+
+.progress-bar-warning {
+  background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
+  background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f));
+  background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
+  background-repeat: repeat-x;
+}
+
+.progress-bar-danger {
+  background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
+  background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c));
+  background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
+  background-repeat: repeat-x;
+}
+
+.progress-bar-striped {
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent);
+}
+
+.list-group {
+  border-radius: 4px;
+  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
+  box-shadow: 0 1px 2px rgba(0, 0, 0, .075);
+}
+
+.list-group-item.active,
+.list-group-item.active:hover,
+.list-group-item.active:focus {
+  text-shadow: 0 -1px 0 #286090;
+  background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);
+  background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2b669a));
+  background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #2b669a;
+}
+
+.list-group-item.active .badge,
+.list-group-item.active:hover .badge,
+.list-group-item.active:focus .badge {
+  text-shadow: none;
+}
+
+.panel {
+  -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
+  box-shadow: 0 1px 2px rgba(0, 0, 0, .05);
+}
+
+.panel-default > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
+  background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
+  background-repeat: repeat-x;
+}
+
+.panel-primary > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+  background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#337ab7), to(#2e6da4));
+  background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);
+  background-repeat: repeat-x;
+}
+
+.panel-success > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
+  background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6));
+  background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
+  background-repeat: repeat-x;
+}
+
+.panel-info > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
+  background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3));
+  background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
+  background-repeat: repeat-x;
+}
+
+.panel-warning > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
+  background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc));
+  background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
+  background-repeat: repeat-x;
+}
+
+.panel-danger > .panel-heading {
+  background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
+  background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc));
+  background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
+  background-repeat: repeat-x;
+}
+
+.well {
+  background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
+  background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5));
+  background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
+  background-repeat: repeat-x;
+  border-color: #dcdcdc;
+  -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
+  box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1);
+}
+
+/*# sourceMappingURL=bootstrap-theme.css.map */

File diff suppressed because it is too large
+ 20 - 0
pigx-visual/pigx-tx-manager/src/main/resources/static/static/bootstrap/css/bootstrap-theme.css.map


File diff suppressed because it is too large
+ 6 - 0
pigx-visual/pigx-tx-manager/src/main/resources/static/static/bootstrap/css/bootstrap-theme.min.css


File diff suppressed because it is too large
+ 17 - 0
pigx-visual/pigx-tx-manager/src/main/resources/static/static/bootstrap/css/bootstrap-theme.min.css.map


File diff suppressed because it is too large
+ 8198 - 0
pigx-visual/pigx-tx-manager/src/main/resources/static/static/bootstrap/css/bootstrap.css


File diff suppressed because it is too large
+ 142 - 0
pigx-visual/pigx-tx-manager/src/main/resources/static/static/bootstrap/css/bootstrap.css.map


File diff suppressed because it is too large
+ 6 - 0
pigx-visual/pigx-tx-manager/src/main/resources/static/static/bootstrap/css/bootstrap.min.css


File diff suppressed because it is too large
+ 143 - 0
pigx-visual/pigx-tx-manager/src/main/resources/static/static/bootstrap/css/bootstrap.min.css.map


BIN
pigx-visual/pigx-tx-manager/src/main/resources/static/static/bootstrap/fonts/glyphicons-halflings-regular.eot


File diff suppressed because it is too large
+ 543 - 0
pigx-visual/pigx-tx-manager/src/main/resources/static/static/bootstrap/fonts/glyphicons-halflings-regular.svg


BIN
pigx-visual/pigx-tx-manager/src/main/resources/static/static/bootstrap/fonts/glyphicons-halflings-regular.ttf


+ 0 - 0
pigx-visual/pigx-tx-manager/src/main/resources/static/static/bootstrap/fonts/glyphicons-halflings-regular.woff


Some files were not shown because too many files changed in this diff