This commit is contained in:
Administrator 2019-04-17 12:49:11 +08:00
parent 61abd53f1f
commit 4473b28a0b
61 changed files with 942 additions and 744 deletions

11
pom.xml
View File

@ -3,7 +3,6 @@
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>
<groupId>org.dromara</groupId>
<artifactId>raincat</artifactId>
<packaging>pom</packaging>
@ -45,10 +44,10 @@
<module>raincat-dubbo</module>
<module>raincat-springcloud</module>
<module>raincat-common</module>
<module>raincat-sample</module>
<module>raincat-admin</module>
<module>raincat-motan</module>
<module>raincat-spring-boot-starter</module>
<module>raincat-annotation</module>
</modules>
<developers>
@ -77,7 +76,7 @@
<jdk.version>1.8</jdk.version>
<spring.version>5.0.7.RELEASE</spring.version>
<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
<dubbo.version>2.5.3</dubbo.version>
<dubbo.version>2.6.2</dubbo.version>
<mongo.driver.version>3.5.0</mongo.driver.version>
<mysql-connector-java>5.1.40</mysql-connector-java>
<commons-lang3.version>3.3.2</commons-lang3.version>
@ -107,6 +106,12 @@
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>raincat-annotation</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>raincat-common</artifactId>

View File

@ -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">
<parent>
<artifactId>raincat</artifactId>
<groupId>org.dromara</groupId>
<version>2.0.1-RELEASE</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>raincat-annotation</artifactId>
<build>
<finalName>raincat-annotation</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -16,7 +16,7 @@
*
*/
package org.dromara.raincat.common.enums;
package org.dromara.raincat.annotation;
/**
* PropagationEnum.

View File

@ -0,0 +1,42 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dromara.raincat.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* The interface Hmily spi.
*
* @author xiaoyu
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface RaincatSPI {
/**
* Value string.
*
* @return the string
*/
String value() default "";
}

View File

@ -16,9 +16,7 @@
*
*/
package org.dromara.raincat.core.annotation;
import org.dromara.raincat.common.enums.PropagationEnum;
package org.dromara.raincat.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@ -26,29 +24,31 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 二阶段分布式事务注解.
* The interface Tx transaction.
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface TxTransaction {
/**
* 事务传播.
* @return {@linkplain PropagationEnum}
* Propagation propagation enum.
*
* @return the propagation enum
*/
PropagationEnum propagation() default PropagationEnum.PROPAGATION_REQUIRES_NEW;
/**
* 事务等待的最大时间 单位秒.
* Wait max time int.
*
* @return 多少秒
* @return the int
*/
int waitMaxTime() default 60;
/**
* 事务管理器名称
* Transaction manager string.
*
* @return 如果为空则取默认的
* @return the string
*/
String transactionManager() default "";
}

View File

@ -14,9 +14,8 @@
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
<groupId>org.dromara</groupId>
<artifactId>raincat-annotation</artifactId>
</dependency>
<dependency>

View File

@ -20,7 +20,7 @@ package org.dromara.raincat.common.bean;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.dromara.raincat.common.enums.PropagationEnum;
import org.dromara.raincat.annotation.PropagationEnum;
/**
* TxTransactionInfo.

View File

@ -0,0 +1,49 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.dromara.raincat.common.holder;
import java.util.Collection;
/**
* The type Collection utils.
*
* @author xiaoyu(Myth)
*/
public class CollectionUtils {
/**
* Is empty boolean.
*
* @param coll the coll
* @return the boolean
*/
public static boolean isEmpty(Collection coll) {
return coll == null || coll.isEmpty();
}
/**
* Is not empty boolean.
*
* @param coll the coll
* @return the boolean
*/
public static boolean isNotEmpty(Collection coll) {
return !isEmpty(coll);
}
}

View File

@ -1,44 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.dromara.raincat.common.holder;
import java.util.Iterator;
import java.util.ServiceLoader;
/**
* ServiceBootstrap.
* @author xiaoyu
*/
public class ServiceBootstrap {
public static <S> S loadFirst(final Class<S> clazz) {
final ServiceLoader<S> loader = loadAll(clazz);
final Iterator<S> iterator = loader.iterator();
if (!iterator.hasNext()) {
throw new IllegalStateException(String.format(
"No implementation defined in /META-INF/services/%s, please check whether the file exists and has the right implementation class!",
clazz.getName()));
}
return iterator.next();
}
public static <S> ServiceLoader<S> loadAll(final Class<S> clazz) {
return ServiceLoader.load(clazz);
}
}

View File

@ -0,0 +1,80 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dromara.raincat.common.holder.extension;
import org.dromara.raincat.annotation.RaincatSPI;
import org.dromara.raincat.common.exception.TransactionRuntimeException;
import java.util.Objects;
import java.util.ServiceLoader;
import java.util.stream.StreamSupport;
/**
* The type Extension loader.
*
* @author xiaoyu
*/
public final class ExtensionLoader<T> {
private Class<T> type;
private ExtensionLoader(final Class<T> type) {
this.type = type;
}
private static <T> boolean withExtensionAnnotation(final Class<T> type) {
return type.isAnnotationPresent(RaincatSPI.class);
}
/**
* Gets extension loader.
*
* @param <T> the type parameter
* @param type the type
* @return the extension loader
*/
public static <T> ExtensionLoader<T> getExtensionLoader(final Class<T> type) {
if (type == null) {
throw new TransactionRuntimeException("type == null");
}
if (!type.isInterface()) {
throw new TransactionRuntimeException("Extension type(" + type + ") not interface!");
}
if (!withExtensionAnnotation(type)) {
throw new TransactionRuntimeException("type" + type.getName() + "not exist");
}
return new ExtensionLoader<>(type);
}
/**
* Gets activate extension.
*
* @param value the value
* @return the activate extension
*/
public T getActivateExtension(final String value) {
ServiceLoader<T> loader = ServiceBootstrap.loadAll(type);
return StreamSupport.stream(loader.spliterator(), false)
.filter(e -> Objects.equals(e.getClass()
.getAnnotation(RaincatSPI.class).value(), value))
.findFirst().orElseThrow(() -> new TransactionRuntimeException("Please check your configuration"));
}
}

View File

@ -0,0 +1,59 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dromara.raincat.common.holder.extension;
import java.util.Iterator;
import java.util.ServiceLoader;
/**
* ServiceBootstrap.
*
* @author xiaoyu
*/
public class ServiceBootstrap {
/**
* Load first s.
*
* @param <S> the type parameter
* @param clazz the clazz
* @return the s
*/
public static <S> S loadFirst(final Class<S> clazz) {
final ServiceLoader<S> loader = loadAll(clazz);
final Iterator<S> iterator = loader.iterator();
if (!iterator.hasNext()) {
throw new IllegalStateException(String.format(
"No implementation defined in /META-INF/services/%s, please check whether the file exists and has the right implementation class!",
clazz.getName()));
}
return iterator.next();
}
/**
* Load all service loader.
*
* @param <S> the type parameter
* @param clazz the clazz
* @return the service loader
*/
public static <S> ServiceLoader<S> loadAll(final Class<S> clazz) {
return ServiceLoader.load(clazz);
}
}

View File

@ -19,6 +19,7 @@ package org.dromara.raincat.common.serializer;
import com.caucho.hessian.io.Hessian2Input;
import com.caucho.hessian.io.Hessian2Output;
import org.dromara.raincat.annotation.RaincatSPI;
import org.dromara.raincat.common.enums.SerializeProtocolEnum;
import org.dromara.raincat.common.exception.TransactionException;
@ -31,6 +32,7 @@ import java.io.IOException;
* @author xiaoyu
*/
@SuppressWarnings("unchecked")
@RaincatSPI("hessian")
public class HessianSerializer implements ObjectSerializer {
@Override

View File

@ -17,6 +17,7 @@
package org.dromara.raincat.common.serializer;
import org.dromara.raincat.annotation.RaincatSPI;
import org.dromara.raincat.common.enums.SerializeProtocolEnum;
import org.dromara.raincat.common.exception.TransactionException;
@ -33,6 +34,7 @@ import java.io.ObjectOutputStream;
* @author xiaoyu
*/
@SuppressWarnings("unchecked")
@RaincatSPI("jdk")
public class JavaSerializer implements ObjectSerializer {
@Override
@ -54,14 +56,4 @@ public class JavaSerializer implements ObjectSerializer {
throw new TransactionException("java deSerialize error " + e.getMessage());
}
}
/**
* 设置scheme.
*
* @return scheme 命名
*/
@Override
public String getScheme() {
return SerializeProtocolEnum.JDK.getSerializeProtocol();
}
}

View File

@ -20,7 +20,7 @@ package org.dromara.raincat.common.serializer;
import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import org.dromara.raincat.common.enums.SerializeProtocolEnum;
import org.dromara.raincat.annotation.RaincatSPI;
import org.dromara.raincat.common.exception.TransactionException;
import java.io.ByteArrayInputStream;
@ -29,15 +29,16 @@ import java.io.IOException;
/**
* KryoSerializer.
*
* @author xiaoyu
*/
@RaincatSPI("kryo")
public class KryoSerializer implements ObjectSerializer {
@Override
public byte[] serialize(final Object obj) throws TransactionException {
byte[] bytes;
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); Output output = new Output(outputStream)) {
//获取kryo对象
Kryo kryo = new Kryo();
kryo.writeObject(output, obj);
bytes = output.toBytes();
@ -61,14 +62,4 @@ public class KryoSerializer implements ObjectSerializer {
}
return object;
}
/**
* 设置scheme.
*
* @return scheme 命名
*/
@Override
public String getScheme() {
return SerializeProtocolEnum.KRYO.getSerializeProtocol();
}
}

View File

@ -18,39 +18,35 @@
package org.dromara.raincat.common.serializer;
import org.dromara.raincat.annotation.RaincatSPI;
import org.dromara.raincat.common.exception.TransactionException;
/**
* ObjectSerializer.
*
* @author xiaoyu
*/
@RaincatSPI
public interface ObjectSerializer {
/**
* 序列化对象.
* Serialize byte [ ].
*
* @param obj 需要序更列化的对象
* @return byte []
* @throws TransactionException 异常信息
* @param obj the obj
* @return the byte [ ]
* @throws TransactionException the transaction exception
*/
byte[] serialize(Object obj) throws TransactionException;
/**
* 反序列化对象.
* De serialize t.
*
* @param param 需要反序列化的byte []
* @param clazz java对象
* @param <T> 泛型支持
* @return 对象
* @throws TransactionException 异常信息
* @param <T> the type parameter
* @param param the param
* @param clazz the clazz
* @return the t
* @throws TransactionException the transaction exception
*/
<T> T deSerialize(byte[] param, Class<T> clazz) throws TransactionException;
/**
* 设置scheme.
*
* @return scheme 命名
*/
String getScheme();
}

View File

@ -20,7 +20,7 @@ package org.dromara.raincat.common.serializer;
import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtostuffIOUtil;
import com.dyuproject.protostuff.Schema;
import org.dromara.raincat.common.enums.SerializeProtocolEnum;
import org.dromara.raincat.annotation.RaincatSPI;
import org.dromara.raincat.common.exception.TransactionException;
import org.objenesis.Objenesis;
import org.objenesis.ObjenesisStd;
@ -31,9 +31,11 @@ import java.io.IOException;
/**
* ProtostuffSerializer.
*
* @author xiaoyu
*/
@SuppressWarnings("unchecked")
@RaincatSPI("protostuff")
public class ProtostuffSerializer implements ObjectSerializer {
private static final SchemaCache CACHED_SCHEMA = SchemaCache.getInstance();
@ -71,14 +73,5 @@ public class ProtostuffSerializer implements ObjectSerializer {
throw new TransactionException(e.getMessage(), e);
}
}
/**
* 设置scheme.
* @return scheme 命名
*/
@Override
public String getScheme() {
return SerializeProtocolEnum.PROTOSTUFF.getSerializeProtocol();
}
}

View File

@ -1,112 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.dromara.raincat.common.holder.httpclient;
import com.google.common.collect.Lists;
import com.google.gson.Gson;
import org.dromara.raincat.common.holder.IdWorkerUtils;
import org.dromara.raincat.common.netty.bean.TxTransactionItem;
import org.junit.Test;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
public class OkHttpToolsTest {
private static final Gson GSON = new Gson();
@Test
public void post() throws Exception {
List<TxTransactionItem> itemList = Lists.newArrayList();
TxTransactionItem txTransactionItem = new TxTransactionItem();
txTransactionItem.setTaskKey(IdWorkerUtils.getInstance().createTaskKey());
itemList.add(txTransactionItem);
OkHttpTools.getInstance().post("http://192.168.1.66:8761/tx/manager/httpExecute",GSON.toJson(itemList));
}
@Test
public void test01(){
MyThread myThread = null;
for (int i=0;i<50;i++){
MyThread m = new MyThread("name"+i,myThread);
m.setDaemon(true);
m.start();
myThread = m;
}
System.out.println("完成");
}
@Test
public void test02(){
AtomicInteger atomicInteger = new AtomicInteger();
for (int i=0;i<50;i++){
SortThread m = new SortThread("name"+i,atomicInteger,i);
m.setDaemon(true);
m.start();
}
System.out.println("完成");
}
class SortThread extends Thread{
AtomicInteger atomicInteger ;
Integer order ;
public SortThread(String name,AtomicInteger atomicInteger,int order){
super(name);
this.atomicInteger = atomicInteger;
this.order = order;
}
@Override
public void run() {
while (true) {
System.out.println(Thread.currentThread().getName() + " " +atomicInteger.get() + " "+order);
if (atomicInteger.get() == order) {
System.out.println(Thread.currentThread().getName() + " 执行跳槽 " + order);
atomicInteger.incrementAndGet();
break;
}
}
}
}
class MyThread extends Thread{
Thread thread ;
public MyThread(String name,Thread thread){
super(name);
this.thread = thread;
}
@Override
public void run() {
if(thread != null)
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" 执行。。。。。。");
}
}
}

View File

@ -1,92 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.dromara.raincat.common.holder.httpclient;
import org.dromara.raincat.common.enums.NettyMessageActionEnum;
import org.dromara.raincat.common.enums.TransactionStatusEnum;
import org.dromara.raincat.common.holder.IdWorkerUtils;
import org.dromara.raincat.common.netty.bean.HeartBeat;
import org.dromara.raincat.common.netty.bean.TxTransactionGroup;
import org.dromara.raincat.common.netty.bean.TxTransactionItem;
import org.dromara.raincat.common.netty.serizlize.kryo.KryoPoolFactory;
import org.dromara.raincat.common.netty.serizlize.kryo.KryoSerialize;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* @author xiaoyu
*/
public class SerializeTest {
private static final int MAX=1000;
public static void main(String[] args) throws IOException {
final long start = System.currentTimeMillis();
for (int i = 0; i <MAX ; i++) {
KryoSerialize kryoSerialization = new KryoSerialize(KryoPoolFactory.getKryoPoolInstance());
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
String groupId = IdWorkerUtils.getInstance().createGroupId();
//创建事务组信息
TxTransactionGroup txTransactionGroup = new TxTransactionGroup();
txTransactionGroup.setId(groupId);
List<TxTransactionItem> items = new ArrayList<>(2);
//tmManager 用redis hash 结构来存储 整个事务组的状态做为hash结构的第一条数据
TxTransactionItem groupItem = new TxTransactionItem();
//整个事务组状态为开始
groupItem.setStatus(TransactionStatusEnum.BEGIN.getCode());
//设置事务id为组的id 即为 hashKey
groupItem.setTransId(groupId);
groupItem.setTaskKey(groupId);
items.add(groupItem);
TxTransactionItem item = new TxTransactionItem();
item.setTaskKey(IdWorkerUtils.getInstance().createTaskKey());
item.setTransId(IdWorkerUtils.getInstance().createUUID());
item.setStatus(TransactionStatusEnum.BEGIN.getCode());
items.add(item);
txTransactionGroup.setItemList(items);
HeartBeat heartBeat = new HeartBeat();
heartBeat.setAction(NettyMessageActionEnum.HEART.getCode());
heartBeat.setTxTransactionGroup(txTransactionGroup);
kryoSerialization.serialize(byteArrayOutputStream, heartBeat);
byte[] body = byteArrayOutputStream.toByteArray();
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body);
final HeartBeat heartBeat1 = (HeartBeat)
kryoSerialization.deserialize(byteArrayInputStream);
}
final long end = System.currentTimeMillis();
System.out.println((end-start)/1000);
}
}

View File

@ -1,26 +0,0 @@
package org.dromara.raincat.common.holder.httpclient;
/**
* <p>Description: .</p>
*
* @author xiaoyu(Myth)
* @version 1.0
* @date 2018/2/5 10:53
* @since JDK 1.8
*/
public class ThreadLocalMapTest {
public static void main(String[] args) {
ThreadLocal A = new ThreadLocal<String>();
ThreadLocal B = new ThreadLocal<String>();
for(int i = 0 ;i<10 ;i++){
A.set("3");
B.set("4");
}
}
}

View File

@ -6,7 +6,6 @@
<artifactId>raincat</artifactId>
<groupId>org.dromara</groupId>
<version>2.0.1-RELEASE</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -21,75 +20,12 @@
<groupId>org.dromara</groupId>
<artifactId>raincat-common</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<version>1.10.8</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<version>1.6.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.6.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
<groupId>com.caucho</groupId>
<artifactId>hessian</artifactId>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
@ -99,14 +35,90 @@
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-mongodb</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
</dependency>
</dependencies>
<build>
<finalName>raincat-core</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -18,7 +18,6 @@
package org.dromara.raincat.core.compensation.impl;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.reflect.MethodUtils;
import org.dromara.raincat.common.bean.TransactionInvocation;
import org.dromara.raincat.common.bean.TransactionRecover;
@ -26,6 +25,7 @@ import org.dromara.raincat.common.config.TxConfig;
import org.dromara.raincat.common.constant.CommonConstant;
import org.dromara.raincat.common.enums.CompensationOperationTypeEnum;
import org.dromara.raincat.common.enums.TransactionStatusEnum;
import org.dromara.raincat.common.holder.CollectionUtils;
import org.dromara.raincat.common.holder.LogUtil;
import org.dromara.raincat.common.netty.bean.TxTransactionGroup;
import org.dromara.raincat.common.netty.bean.TxTransactionItem;

View File

@ -25,6 +25,7 @@ import org.aspectj.lang.annotation.Pointcut;
/**
* AbstractTxTransactionAspect.
*
* @author xiaoyu
*/
@Aspect
@ -32,15 +33,30 @@ public abstract class AbstractTxTransactionAspect {
private TxTransactionInterceptor txTransactionInterceptor;
/**
* Sets tx transaction interceptor.
*
* @param txTransactionInterceptor the tx transaction interceptor
*/
public void setTxTransactionInterceptor(final TxTransactionInterceptor txTransactionInterceptor) {
this.txTransactionInterceptor = txTransactionInterceptor;
}
@Pointcut("@annotation(org.dromara.raincat.core.annotation.TxTransaction)")
/**
* Tx transaction interceptor.
*/
@Pointcut("@annotation(org.dromara.raincat.annotation.TxTransaction)")
public void txTransactionInterceptor() {
}
/**
* Intercept tx transaction object.
*
* @param proceedingJoinPoint the proceeding join point
* @return the object
* @throws Throwable the throwable
*/
@Around("txTransactionInterceptor()")
public Object interceptTxTransaction(final ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
return txTransactionInterceptor.interceptor(proceedingJoinPoint);
@ -48,7 +64,8 @@ public abstract class AbstractTxTransactionAspect {
/**
* spring bean order.
* @return order
*
* @return order order
*/
public abstract int getOrder();
}

View File

@ -0,0 +1,34 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dromara.raincat.core.mediator;
/**
* The interface Rpc acquire.
*
* @author xiaoyu(Myth)
*/
public interface RpcAcquire {
/**
* Acquire string.
*
* @param key the key
* @return the string
*/
String acquire(String key);
}

View File

@ -0,0 +1,61 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dromara.raincat.core.mediator;
import org.dromara.raincat.common.constant.CommonConstant;
import org.dromara.raincat.core.concurrent.threadlocal.TxTransactionLocal;
/**
* The type RpcMediator.
*
* @author xiaoyu(Myth)
*/
public class RpcMediator {
private static final RpcMediator RPC_MEDIATOR = new RpcMediator();
/**
* Gets instance.
*
* @return the instance
*/
public static RpcMediator getInstance() {
return RPC_MEDIATOR;
}
/**
* Transmit.
*
* @param rpcTransmit the rpc mediator
*/
public void transmit(final RpcTransmit rpcTransmit) {
rpcTransmit.transmit(CommonConstant.TX_TRANSACTION_GROUP,
TxTransactionLocal.getInstance().getTxGroupId());
}
/**
* Acquire hmily transaction context.
*
* @param rpcAcquire the rpc acquire
* @return the hmily transaction context
*/
public String acquire(RpcAcquire rpcAcquire) {
return rpcAcquire.acquire(CommonConstant.TX_TRANSACTION_GROUP);
}
}

View File

@ -0,0 +1,35 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dromara.raincat.core.mediator;
/**
* The interface Rpc mediator.
*
* @author xiaoyu(Myth)
*/
public interface RpcTransmit {
/**
* Transmit.
*
* @param key the key
* @param value the value
*/
void transmit(String key, String value);
}

View File

@ -25,10 +25,10 @@ import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.ReferenceCountUtil;
import io.netty.util.concurrent.ScheduledFuture;
import org.apache.commons.collections.CollectionUtils;
import org.dromara.raincat.common.config.TxConfig;
import org.dromara.raincat.common.enums.NettyMessageActionEnum;
import org.dromara.raincat.common.enums.NettyResultEnum;
import org.dromara.raincat.common.holder.CollectionUtils;
import org.dromara.raincat.common.holder.IdWorkerUtils;
import org.dromara.raincat.common.holder.LogUtil;
import org.dromara.raincat.common.netty.bean.HeartBeat;

View File

@ -22,18 +22,20 @@ import org.aspectj.lang.ProceedingJoinPoint;
/**
* AspectTransactionService.
*
* @author xiaoyu
*/
@FunctionalInterface
public interface AspectTransactionService {
/**
* 切面方法调用.
* Invoke object.
*
* @param transactionGroupId 事务组id
* @param point 切点
* @return Object
* @throws Throwable 异常信息
* @param transactionGroupId the transaction group id
* @param point the point
* @return the object
* @throws Throwable the throwable
*/
Object invoke(String transactionGroupId, ProceedingJoinPoint point) throws Throwable;
}

View File

@ -20,10 +20,10 @@ package org.dromara.raincat.core.service.impl;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
import org.dromara.raincat.annotation.PropagationEnum;
import org.dromara.raincat.annotation.TxTransaction;
import org.dromara.raincat.common.bean.TransactionInvocation;
import org.dromara.raincat.common.bean.TxTransactionInfo;
import org.dromara.raincat.common.enums.PropagationEnum;
import org.dromara.raincat.core.annotation.TxTransaction;
import org.dromara.raincat.core.concurrent.threadlocal.CompensationLocal;
import org.dromara.raincat.core.helper.SpringBeanUtils;
import org.dromara.raincat.core.service.AspectTransactionService;

View File

@ -19,11 +19,8 @@
package org.dromara.raincat.core.service.impl;
import org.dromara.raincat.common.config.TxConfig;
import org.dromara.raincat.common.enums.CompensationCacheTypeEnum;
import org.dromara.raincat.common.enums.SerializeProtocolEnum;
import org.dromara.raincat.common.exception.TransactionRuntimeException;
import org.dromara.raincat.common.holder.ServiceBootstrap;
import org.dromara.raincat.common.serializer.KryoSerializer;
import org.dromara.raincat.common.holder.extension.ExtensionLoader;
import org.dromara.raincat.common.serializer.ObjectSerializer;
import org.dromara.raincat.core.compensation.TxCompensationService;
import org.dromara.raincat.core.helper.SpringBeanUtils;
@ -31,14 +28,9 @@ import org.dromara.raincat.core.logo.RaincatLogo;
import org.dromara.raincat.core.netty.NettyClientService;
import org.dromara.raincat.core.service.InitService;
import org.dromara.raincat.core.spi.TransactionRecoverRepository;
import org.dromara.raincat.core.spi.repository.JdbcTransactionRecoverRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Objects;
import java.util.ServiceLoader;
import java.util.stream.StreamSupport;
/**
* tx transaction init.
*
@ -77,27 +69,12 @@ public class InitServiceImpl implements InitService {
* @param txConfig {@linkplain TxConfig}
*/
private void loadSpi(final TxConfig txConfig) {
//spi serialize
final SerializeProtocolEnum serializeProtocolEnum
= SerializeProtocolEnum.acquireSerializeProtocol(txConfig.getSerializer());
final ServiceLoader<ObjectSerializer> objectSerializers
= ServiceBootstrap.loadAll(ObjectSerializer.class);
final ObjectSerializer serializer =
StreamSupport.stream(objectSerializers.spliterator(), false)
.filter(s -> Objects.equals(s.getScheme(), serializeProtocolEnum.getSerializeProtocol()))
.findFirst().orElse(new KryoSerializer());
//spi RecoverRepository support
final CompensationCacheTypeEnum compensationCacheTypeEnum
= CompensationCacheTypeEnum.acquireCompensationCacheType(txConfig.getCompensationCacheType());
final ServiceLoader<TransactionRecoverRepository> recoverRepositories
= ServiceBootstrap.loadAll(TransactionRecoverRepository.class);
final TransactionRecoverRepository repository =
StreamSupport.stream(recoverRepositories.spliterator(), false)
.filter(r -> Objects.equals(r.getScheme(), compensationCacheTypeEnum.getCompensationCacheType()))
.findFirst().orElse(new JdbcTransactionRecoverRepository());
//将compensationCache实现注入到spring容器
//spi serialize
final ObjectSerializer serializer = ExtensionLoader.getExtensionLoader(ObjectSerializer.class)
.getActivateExtension(txConfig.getSerializer());
//spi repository
final TransactionRecoverRepository repository = ExtensionLoader.getExtensionLoader(TransactionRecoverRepository.class)
.getActivateExtension(txConfig.getCompensationCacheType());
repository.setSerializer(serializer);
SpringBeanUtils.getInstance().registerBean(TransactionRecoverRepository.class.getName(), repository);
}

View File

@ -20,11 +20,11 @@ package org.dromara.raincat.core.service.impl;
import com.google.common.collect.Lists;
import com.google.gson.reflect.TypeToken;
import org.apache.commons.collections.CollectionUtils;
import org.dromara.raincat.common.config.TxConfig;
import org.dromara.raincat.common.constant.CommonConstant;
import org.dromara.raincat.common.entity.TxManagerServer;
import org.dromara.raincat.common.entity.TxManagerServiceDTO;
import org.dromara.raincat.common.holder.CollectionUtils;
import org.dromara.raincat.common.holder.LogUtil;
import org.dromara.raincat.common.holder.httpclient.OkHttpTools;
import org.dromara.raincat.core.concurrent.threadpool.TxTransactionThreadFactory;

View File

@ -18,6 +18,7 @@
package org.dromara.raincat.core.spi;
import org.dromara.raincat.annotation.RaincatSPI;
import org.dromara.raincat.common.bean.TransactionRecover;
import org.dromara.raincat.common.config.TxConfig;
import org.dromara.raincat.common.exception.TransactionRuntimeException;
@ -30,6 +31,7 @@ import java.util.List;
* TransactionRecoverRepository.
* @author xiaoyu
*/
@RaincatSPI
public interface TransactionRecoverRepository {
int ROWS = 1;
@ -97,14 +99,6 @@ public interface TransactionRecoverRepository {
*/
void init(String appName, TxConfig txConfig) throws Exception;
/**
* get scheme.
*
* @return scheme
*/
String getScheme();
/**
* set objectSerializer spi.
*

View File

@ -19,10 +19,10 @@
package org.dromara.raincat.core.spi.repository;
import com.google.common.collect.Lists;
import org.dromara.raincat.annotation.RaincatSPI;
import org.dromara.raincat.common.bean.TransactionRecover;
import org.dromara.raincat.common.config.TxConfig;
import org.dromara.raincat.common.constant.CommonConstant;
import org.dromara.raincat.common.enums.CompensationCacheTypeEnum;
import org.dromara.raincat.common.enums.CompensationOperationTypeEnum;
import org.dromara.raincat.common.exception.TransactionRuntimeException;
import org.dromara.raincat.common.holder.RepositoryPathUtils;
@ -44,7 +44,8 @@ import java.util.stream.Collectors;
*
* @author xiaoyu
*/
@SuppressWarnings("unchecked")
@SuppressWarnings("all")
@RaincatSPI("file")
public class FileTransactionRecoverRepository implements TransactionRecoverRepository {
private static volatile boolean initialized;
@ -140,11 +141,6 @@ public class FileTransactionRecoverRepository implements TransactionRecoverRepos
}
}
@Override
public String getScheme() {
return CompensationCacheTypeEnum.FILE.getCompensationCacheType();
}
private void writeFile(final TransactionRecover transaction) {
makeDir();
String file = getFullFileName(transaction.getId());

View File

@ -20,16 +20,16 @@ package org.dromara.raincat.core.spi.repository;
import com.alibaba.druid.pool.DruidDataSource;
import com.google.common.collect.Maps;
import org.apache.commons.collections.CollectionUtils;
import org.dromara.raincat.annotation.RaincatSPI;
import org.dromara.raincat.common.bean.TransactionInvocation;
import org.dromara.raincat.common.bean.TransactionRecover;
import org.dromara.raincat.common.config.TxConfig;
import org.dromara.raincat.common.config.TxDbConfig;
import org.dromara.raincat.common.constant.CommonConstant;
import org.dromara.raincat.common.enums.CompensationCacheTypeEnum;
import org.dromara.raincat.common.enums.CompensationOperationTypeEnum;
import org.dromara.raincat.common.exception.TransactionException;
import org.dromara.raincat.common.exception.TransactionRuntimeException;
import org.dromara.raincat.common.holder.CollectionUtils;
import org.dromara.raincat.common.holder.RepositoryPathUtils;
import org.dromara.raincat.common.serializer.ObjectSerializer;
import org.dromara.raincat.core.helper.SqlHelper;
@ -54,6 +54,7 @@ import java.util.stream.Collectors;
*
* @author xiaoyu
*/
@RaincatSPI("db")
public class JdbcTransactionRecoverRepository implements TransactionRecoverRepository {
private static final Logger LOGGER = LoggerFactory.getLogger(JdbcTransactionRecoverRepository.class);
@ -188,11 +189,6 @@ public class JdbcTransactionRecoverRepository implements TransactionRecoverRepos
executeUpdate(SqlHelper.buildCreateTableSql(tableName, txDbConfig.getDriverClassName()));
}
@Override
public String getScheme() {
return CompensationCacheTypeEnum.DB.getCompensationCacheType();
}
private int executeUpdate(final String sql, final Object... params) {
try {
try (Connection connection = dataSource.getConnection();

View File

@ -22,23 +22,23 @@ import com.google.common.base.Splitter;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.WriteResult;
import org.dromara.raincat.annotation.RaincatSPI;
import org.dromara.raincat.common.bean.TransactionInvocation;
import org.dromara.raincat.common.bean.TransactionRecover;
import org.dromara.raincat.common.bean.adapter.MongoAdapter;
import org.dromara.raincat.common.config.TxConfig;
import org.dromara.raincat.common.config.TxMongoConfig;
import org.dromara.raincat.common.constant.CommonConstant;
import org.dromara.raincat.common.enums.CompensationCacheTypeEnum;
import org.dromara.raincat.common.enums.CompensationOperationTypeEnum;
import org.dromara.raincat.common.enums.TransactionStatusEnum;
import org.dromara.raincat.common.exception.TransactionException;
import org.dromara.raincat.common.exception.TransactionRuntimeException;
import org.dromara.raincat.common.holder.Assert;
import org.dromara.raincat.common.holder.CollectionUtils;
import org.dromara.raincat.common.holder.LogUtil;
import org.dromara.raincat.common.holder.RepositoryPathUtils;
import org.dromara.raincat.common.serializer.ObjectSerializer;
import org.dromara.raincat.core.spi.TransactionRecoverRepository;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.mongodb.core.MongoClientFactoryBean;
@ -56,6 +56,7 @@ import java.util.stream.Collectors;
* mongo db impl.
* @author xiaoyu
*/
@RaincatSPI("mongo")
public class MongoTransactionRecoverRepository implements TransactionRecoverRepository {
private static final Logger LOGGER = LoggerFactory.getLogger(MongoTransactionRecoverRepository.class);
@ -181,6 +182,7 @@ public class MongoTransactionRecoverRepository implements TransactionRecoverRepo
}
@Override
@SuppressWarnings("unchecked")
public void init(final String appName, final TxConfig txConfig) {
collectionName = RepositoryPathUtils.buildMongoTableName(appName);
final TxMongoConfig txMongoConfig = txConfig.getTxMongoConfig();
@ -210,11 +212,6 @@ public class MongoTransactionRecoverRepository implements TransactionRecoverRepo
return clientFactoryBean;
}
@Override
public String getScheme() {
return CompensationCacheTypeEnum.MONGODB.getCompensationCacheType();
}
@Override
public void setSerializer(final ObjectSerializer objectSerializer) {
this.objectSerializer = objectSerializer;

View File

@ -21,11 +21,11 @@ package org.dromara.raincat.core.spi.repository;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.dromara.raincat.annotation.RaincatSPI;
import org.dromara.raincat.common.bean.TransactionRecover;
import org.dromara.raincat.common.config.TxConfig;
import org.dromara.raincat.common.config.TxRedisConfig;
import org.dromara.raincat.common.constant.CommonConstant;
import org.dromara.raincat.common.enums.CompensationCacheTypeEnum;
import org.dromara.raincat.common.enums.CompensationOperationTypeEnum;
import org.dromara.raincat.common.exception.TransactionIoException;
import org.dromara.raincat.common.exception.TransactionRuntimeException;
@ -58,6 +58,7 @@ import java.util.stream.Collectors;
*
* @author xiaoyu
*/
@RaincatSPI("redis")
public class RedisTransactionRecoverRepository implements TransactionRecoverRepository {
private static final Logger LOGGER = LoggerFactory.getLogger(RedisTransactionRecoverRepository.class);
@ -157,11 +158,6 @@ public class RedisTransactionRecoverRepository implements TransactionRecoverRepo
}
}
@Override
public String getScheme() {
return CompensationCacheTypeEnum.REDIS.getCompensationCacheType();
}
@Override
public void setSerializer(final ObjectSerializer objectSerializer) {
this.objectSerializer = objectSerializer;

View File

@ -19,7 +19,6 @@
package org.dromara.raincat.core.spi.repository;
import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
@ -27,15 +26,16 @@ import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.dromara.raincat.annotation.RaincatSPI;
import org.dromara.raincat.common.bean.TransactionRecover;
import org.dromara.raincat.common.config.TxConfig;
import org.dromara.raincat.common.config.TxZookeeperConfig;
import org.dromara.raincat.common.constant.CommonConstant;
import org.dromara.raincat.common.enums.CompensationCacheTypeEnum;
import org.dromara.raincat.common.enums.CompensationOperationTypeEnum;
import org.dromara.raincat.common.exception.TransactionException;
import org.dromara.raincat.common.exception.TransactionIoException;
import org.dromara.raincat.common.exception.TransactionRuntimeException;
import org.dromara.raincat.common.holder.CollectionUtils;
import org.dromara.raincat.common.holder.LogUtil;
import org.dromara.raincat.common.holder.RepositoryPathUtils;
import org.dromara.raincat.common.holder.TransactionRecoverUtils;
@ -54,6 +54,7 @@ import java.util.stream.Collectors;
*
* @author xiaoyu
*/
@RaincatSPI("zookeeper")
public class ZookeeperTransactionRecoverRepository implements TransactionRecoverRepository {
private static final Logger LOGGER = LoggerFactory.getLogger(ZookeeperTransactionRecoverRepository.class);
@ -189,11 +190,6 @@ public class ZookeeperTransactionRecoverRepository implements TransactionRecover
}
}
@Override
public String getScheme() {
return CompensationCacheTypeEnum.ZOOKEEPER.getCompensationCacheType();
}
@Override
public void setSerializer(final ObjectSerializer objectSerializer) {
this.objectSerializer = objectSerializer;

View File

@ -1,22 +0,0 @@
/*
*
* Copyright 2017-2018 549477611@qq.com(xiaoyu)
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.dromara.raincat.core;
public class AtomicReferenceTest {
}

View File

@ -1,22 +0,0 @@
package org.dromara.raincat.core.concurrent.task;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* @author xiaoyu(Myth)
*/
public class BlockTaskTest {
@Test
public void isNotify() {
BlockTask task1 = new BlockTask();
task1.signal();
System.out.println(task1.isNotify());
BlockTask task2 = new BlockTask();
System.out.println(task2.isNotify());
}
}

View File

@ -1,61 +0,0 @@
package org.dromara.raincat.core.mongodb;
import com.mongodb.MongoClient;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
import java.util.ArrayList;
import java.util.List;
public class MongoDbConnectDatabase {
public static void main(String[] args) {
try {
//连接到MongoDB服务 如果是远程连接可以替换localhost为服务器所在IP地址
//ServerAddress()两个参数分别为 服务器地址 端口
ServerAddress serverAddress = new ServerAddress("192.168.1.78", 27017);
List<ServerAddress> addrs = new ArrayList<>();
addrs.add(serverAddress);
//MongoCredential.createScramSha1Credential()三个参数分别为 用户名 数据库名称 密码
MongoCredential credential = MongoCredential.createScramSha1Credential("xiaoyu", "happylife", "123456".toCharArray());
List<MongoCredential> credentials = new ArrayList<>();
credentials.add(credential);
//通过连接认证获取MongoDB连接
MongoClient mongoClient = new MongoClient(addrs, credentials);
//连接到数据库
MongoDatabase mongoDatabase = mongoClient.getDatabase("happylife");
System.out.println("Connect to database successfully");
//获取集合 参数为集合名称
MongoCollection<Document> mongoCollection = mongoDatabase.getCollection("collectionName");
System.out.println("Collection mycol selected successfully");
//插入文档
/**
* 1. 创建文档 org.bson.Document 参数为key-value的格式
* 2. 创建文档集合List<Document>
* 3. 将文档集合插入数据库集合中 mongoCollection.insertMany(List<Document>) 插入单个文档可以用 mongoCollection.insertOne(Document)
* */
Document document = new Document("title", "MongoDB").
append("description", "database").
append("likes", 100).
append("by", "Fly");
List<Document> documents = new ArrayList<Document>();
documents.add(document);
mongoCollection.insertMany(documents);
System.out.println("Document inserted successfully");
} catch (Exception e) {
System.err.println(e.getClass().getName() + ": " + e.getMessage());
}
}
}

View File

@ -1,64 +0,0 @@
package org.dromara.raincat.core.spi;
import org.dromara.raincat.common.enums.CompensationCacheTypeEnum;
import org.dromara.raincat.common.enums.SerializeProtocolEnum;
import org.dromara.raincat.common.holder.ServiceBootstrap;
import org.dromara.raincat.common.serializer.ObjectSerializer;
import org.dromara.raincat.core.helper.SpringBeanUtils;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Objects;
import java.util.Optional;
import java.util.ServiceLoader;
import java.util.stream.StreamSupport;
public class ServiceBootstrapTest {
/**
* logger
*/
private static final Logger LOGGER = LoggerFactory.getLogger(ServiceBootstrapTest.class);
@Test
public void loadFirst() throws Exception {
final ObjectSerializer objectSerializer = ServiceBootstrap.loadFirst(ObjectSerializer.class);
LOGGER.info("加载的序列化名称为:{}", objectSerializer.getClass().getName());
}
@Test
public void loadAll() {
//spi serialize
final SerializeProtocolEnum serializeProtocolEnum =
SerializeProtocolEnum.HESSIAN;
final ServiceLoader<ObjectSerializer> objectSerializers = ServiceBootstrap.loadAll(ObjectSerializer.class);
final Optional<ObjectSerializer> serializer = StreamSupport.stream(objectSerializers.spliterator(), false)
.filter(objectSerializer ->
Objects.equals(objectSerializer.getScheme(), serializeProtocolEnum.getSerializeProtocol())).findFirst();
serializer.ifPresent(objectSerializer -> LOGGER.info("加载的序列化名称为:{}", objectSerializer.getClass().getName()));
//spi RecoverRepository support
final CompensationCacheTypeEnum compensationCacheTypeEnum = CompensationCacheTypeEnum.DB;
final ServiceLoader<TransactionRecoverRepository> recoverRepositories = ServiceBootstrap.loadAll(TransactionRecoverRepository.class);
final Optional<TransactionRecoverRepository> repositoryOptional = StreamSupport.stream(recoverRepositories.spliterator(), false)
.filter(recoverRepository ->
Objects.equals(recoverRepository.getScheme(), compensationCacheTypeEnum.getCompensationCacheType())).findFirst();
//将compensationCache实现注入到spring容器
repositoryOptional.ifPresent(repository -> {
serializer.ifPresent(repository::setSerializer);
SpringBeanUtils.getInstance().registerBean(TransactionRecoverRepository.class.getName(), repository);
});
}
}

View File

@ -1,4 +0,0 @@
com.raincat.common.serializer.KryoSerializer
com.raincat.common.serializer.ProtostuffSerializer
com.raincat.common.serializer.HessianSerializer
com.raincat.common.serializer.JavaSerializer

View File

@ -1,5 +0,0 @@
com.raincat.core.spi.repository.JdbcTransactionRecoverRepository
com.raincat.core.spi.repository.FileTransactionRecoverRepository
com.raincat.core.spi.repository.MongoTransactionRecoverRepository
com.raincat.core.spi.repository.RedisTransactionRecoverRepository
com.raincat.core.spi.repository.ZookeeperTransactionRecoverRepository

View File

@ -14,20 +14,25 @@
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>raincat-core</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>

View File

@ -28,6 +28,8 @@ import com.alibaba.dubbo.rpc.RpcContext;
import com.alibaba.dubbo.rpc.RpcException;
import org.dromara.raincat.common.constant.CommonConstant;
import org.dromara.raincat.core.concurrent.threadlocal.TxTransactionLocal;
import org.dromara.raincat.core.mediator.RpcMediator;
import org.dromara.raincat.core.mediator.RpcTransmit;
/**
* DubboTxTransactionFilter.
@ -39,8 +41,7 @@ public class DubboTxTransactionFilter implements Filter {
@Override
public Result invoke(final Invoker<?> invoker, final Invocation invocation) throws RpcException {
if (RpcContext.getContext().isConsumerSide()) {
RpcContext.getContext().setAttachment(CommonConstant.TX_TRANSACTION_GROUP,
TxTransactionLocal.getInstance().getTxGroupId());
RpcMediator.getInstance().transmit(RpcContext.getContext()::setAttachment);
}
return invoker.invoke(invocation);
}

View File

@ -19,15 +19,17 @@
package org.dromara.raincat.dubbo.interceptor;
import com.alibaba.dubbo.rpc.RpcContext;
import org.dromara.raincat.common.constant.CommonConstant;
import org.dromara.raincat.core.interceptor.TxTransactionInterceptor;
import org.dromara.raincat.core.service.AspectTransactionService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.dromara.raincat.core.interceptor.TxTransactionInterceptor;
import org.dromara.raincat.core.mediator.RpcMediator;
import org.dromara.raincat.core.service.AspectTransactionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* DubboTxTransactionInterceptor.
*
* @author xiaoyu
*/
@Component
@ -42,7 +44,8 @@ public class DubboTxTransactionInterceptor implements TxTransactionInterceptor {
@Override
public Object interceptor(final ProceedingJoinPoint pjp) throws Throwable {
String groupId = RpcContext.getContext().getAttachment(CommonConstant.TX_TRANSACTION_GROUP);
String groupId = RpcMediator.getInstance()
.acquire(RpcContext.getContext()::getAttachment);
return aspectTransactionService.invoke(groupId, pjp);
}

View File

@ -12,25 +12,31 @@
<artifactId>raincat-motan</artifactId>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-core</artifactId>
</dependency>
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-springsupport</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>raincat-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.weibo</groupId>
<artifactId>motan-springsupport</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<build>

View File

@ -28,6 +28,7 @@ import com.weibo.api.motan.rpc.Request;
import com.weibo.api.motan.rpc.Response;
import org.dromara.raincat.common.constant.CommonConstant;
import org.dromara.raincat.core.concurrent.threadlocal.TxTransactionLocal;
import org.dromara.raincat.core.mediator.RpcMediator;
/**
@ -41,7 +42,7 @@ public class MotanTxTransactionFilter implements Filter {
@Override
public Response filter(final Caller<?> caller, final Request request) {
request.setAttachment(CommonConstant.TX_TRANSACTION_GROUP, TxTransactionLocal.getInstance().getTxGroupId());
RpcMediator.getInstance().transmit(request::setAttachment);
return caller.call(request);
}
}

View File

@ -18,12 +18,12 @@
package org.dromara.raincat.motan.interceptor;
import org.dromara.raincat.common.constant.CommonConstant;
import org.dromara.raincat.core.interceptor.TxTransactionInterceptor;
import org.dromara.raincat.core.service.AspectTransactionService;
import com.weibo.api.motan.rpc.Request;
import com.weibo.api.motan.rpc.RpcContext;
import org.aspectj.lang.ProceedingJoinPoint;
import org.dromara.raincat.core.interceptor.TxTransactionInterceptor;
import org.dromara.raincat.core.mediator.RpcMediator;
import org.dromara.raincat.core.service.AspectTransactionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@ -32,6 +32,7 @@ import java.util.Objects;
/**
* MotanTxTransactionInterceptor.
*
* @author xiaoyu
*/
@Component
@ -51,7 +52,8 @@ public class MotanTxTransactionInterceptor implements TxTransactionInterceptor {
if (Objects.nonNull(request)) {
final Map<String, String> attachments = request.getAttachments();
if (attachments != null && !attachments.isEmpty()) {
groupId = attachments.get(CommonConstant.TX_TRANSACTION_GROUP);
groupId = RpcMediator.getInstance().acquire(attachments::get);
}
}
return aspectTransactionService.invoke(groupId, pjp);

View File

@ -2,19 +2,108 @@
<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">
<parent>
<artifactId>raincat</artifactId>
<groupId>org.dromara</groupId>
<version>2.0.1-RELEASE</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<modelVersion>4.0.0</modelVersion>
<artifactId>raincat-sample</artifactId>
<groupId>org.dromara</groupId>
<version>2.0.1-RELEASE</version>
<packaging>pom</packaging>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
</parent>
<modules>
<module>raincat-dubbo-sample</module>
<module>raincat-springcloud-sample</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jdk.version>1.8</jdk.version>
<raincat.version>2.0.1-RELEASE</raincat.version>
<spring-cloud.version>Dalston.SR1</spring-cloud.version>
<springfox.version>2.6.1</springfox.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>raincat-annotation</artifactId>
<version>${raincat.version}</version>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>raincat-core</artifactId>
<version>${raincat.version}</version>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>raincat-dubbo</artifactId>
<version>${raincat.version}</version>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>raincat-springcloud</artifactId>
<version>${raincat.version}</version>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>raincat-spring-boot-starter-dubbo</artifactId>
<version>${raincat.version}</version>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>raincat-spring-boot-starter-springcloud</artifactId>
<version>${raincat.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${springfox.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-bean-validators</artifactId>
<version>${springfox.version}</version>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.9</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>${project.build.sourceEncoding}</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -21,8 +21,32 @@
<module>raincat-dubbo-sample-order</module>
</modules>
<properties>
<curator.version>4.0.1</curator.version>
<dubbo.version>2.6.5</dubbo.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-client</artifactId>
<version>${curator.version}</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>${curator.version}</version>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>raincat-dubbo-sample-consume</artifactId>

View File

@ -78,6 +78,7 @@
<artifactId>zkclient</artifactId>
<version>0.4</version>
</dependency>
<!-- zookeeper -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
@ -93,6 +94,7 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>

View File

@ -17,5 +17,21 @@
<module>raincat-springcloud-sample-wechat</module>
</modules>
<properties>
<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>

View File

@ -20,7 +20,7 @@ package org.dromara.raincat.springcloud.sample.pay.client;
import feign.Feign;
import feign.Request;
import feign.Retryer;
import org.dromara.raincat.springcloud.feign.RestTemplateInterceptor;
import org.dromara.raincat.springcloud.feign.RaincatFeignInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
@ -34,7 +34,7 @@ public class MyConfiguration {
@Bean
@Scope("prototype")
public Feign.Builder feignBuilder() {
return Feign.builder().requestInterceptor(new RestTemplateInterceptor());
return Feign.builder().requestInterceptor(new RaincatFeignInterceptor());
}
@Bean

View File

@ -23,11 +23,6 @@ import org.dromara.raincat.springcloud.sample.pay.client.WechatClient;
import org.dromara.raincat.springcloud.sample.pay.entiy.Pay;
import org.dromara.raincat.springcloud.sample.pay.mapper.PayMapper;
import org.dromara.raincat.springcloud.sample.pay.service.PayService;
import org.dromara.raincat.springcloud.sample.pay.client.AlipayClient;
import org.dromara.raincat.springcloud.sample.pay.client.WechatClient;
import org.dromara.raincat.springcloud.sample.pay.entiy.Pay;
import org.dromara.raincat.springcloud.sample.pay.mapper.PayMapper;
import org.dromara.raincat.springcloud.sample.pay.service.PayService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

View File

@ -12,37 +12,49 @@
<artifactId>raincat-springcloud</artifactId>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.dromara</groupId>
<artifactId>raincat-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-core</artifactId>
<version>8.18.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-loadbalancer</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<artifactId>spring-boot-starter-actuator</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>RELEASE</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>

View File

@ -16,9 +16,13 @@
*
*/
package org.dromara.raincat.springcloud.feign;
package org.dromara.raincat.springcloud.configuration;
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
import feign.RequestInterceptor;
import org.dromara.raincat.springcloud.feign.RaincatFeignInterceptor;
import org.dromara.raincat.springcloud.hystrix.RaincatHystrixConcurrencyStrategy;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@ -28,11 +32,27 @@ import org.springframework.context.annotation.Configuration;
* @author xiaoyu
*/
@Configuration
public class RestTemplateConfiguration {
public class RaincatFeignConfiguration {
/**
* Request interceptor request interceptor.
*
* @return the request interceptor
*/
@Bean
public RequestInterceptor requestInterceptor() {
return new RestTemplateInterceptor();
return new RaincatFeignInterceptor();
}
/**
* Hystrix concurrency strategy hystrix concurrency strategy.
*
* @return the hystrix concurrency strategy
*/
@Bean
@ConditionalOnProperty(name = "feign.hystrix.enabled")
public HystrixConcurrencyStrategy hystrixConcurrencyStrategy() {
return new RaincatHystrixConcurrencyStrategy();
}
}

View File

@ -20,18 +20,18 @@ package org.dromara.raincat.springcloud.feign;
import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.dromara.raincat.common.constant.CommonConstant;
import org.dromara.raincat.core.concurrent.threadlocal.TxTransactionLocal;
import org.dromara.raincat.core.mediator.RpcMediator;
/**
* RestTemplateInterceptor.
*
* @author xiaoyu
*/
public class RestTemplateInterceptor implements RequestInterceptor {
public class RaincatFeignInterceptor implements RequestInterceptor {
@Override
public void apply(final RequestTemplate requestTemplate) {
requestTemplate.header(CommonConstant.TX_TRANSACTION_GROUP, TxTransactionLocal.getInstance().getTxGroupId());
RpcMediator.getInstance().transmit(requestTemplate::header);
}
}

View File

@ -0,0 +1,107 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dromara.raincat.springcloud.hystrix;
import com.netflix.hystrix.HystrixThreadPoolKey;
import com.netflix.hystrix.HystrixThreadPoolProperties;
import com.netflix.hystrix.strategy.HystrixPlugins;
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariable;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariableLifecycle;
import com.netflix.hystrix.strategy.eventnotifier.HystrixEventNotifier;
import com.netflix.hystrix.strategy.executionhook.HystrixCommandExecutionHook;
import com.netflix.hystrix.strategy.metrics.HystrixMetricsPublisher;
import com.netflix.hystrix.strategy.properties.HystrixPropertiesStrategy;
import com.netflix.hystrix.strategy.properties.HystrixProperty;
import org.dromara.raincat.core.concurrent.threadlocal.TxTransactionLocal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* HmilyHystrixConcurrencyStrategy.
*
* @author xiaoyu
*/
public class RaincatHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {
private static final Logger LOGGER = LoggerFactory.getLogger(RaincatHystrixConcurrencyStrategy.class);
private HystrixConcurrencyStrategy delegate;
public RaincatHystrixConcurrencyStrategy() {
try {
this.delegate = HystrixPlugins.getInstance().getConcurrencyStrategy();
if (this.delegate instanceof RaincatHystrixConcurrencyStrategy) {
return;
}
HystrixCommandExecutionHook commandExecutionHook = HystrixPlugins
.getInstance().getCommandExecutionHook();
HystrixEventNotifier eventNotifier = HystrixPlugins.getInstance()
.getEventNotifier();
HystrixMetricsPublisher metricsPublisher = HystrixPlugins.getInstance()
.getMetricsPublisher();
HystrixPropertiesStrategy propertiesStrategy = HystrixPlugins.getInstance()
.getPropertiesStrategy();
LOGGER.debug("HystrixEventNotifier:{}, HystrixMetricsPublisher:{}, HystrixPropertiesStrategy:{}",
eventNotifier, metricsPublisher, propertiesStrategy);
HystrixPlugins.reset();
HystrixPlugins.getInstance().registerConcurrencyStrategy(this);
HystrixPlugins.getInstance()
.registerCommandExecutionHook(commandExecutionHook);
HystrixPlugins.getInstance().registerEventNotifier(eventNotifier);
HystrixPlugins.getInstance().registerMetricsPublisher(metricsPublisher);
HystrixPlugins.getInstance().registerPropertiesStrategy(propertiesStrategy);
} catch (Exception e) {
LOGGER.error("Failed to register Tracing Hystrix Concurrency Strategy", e);
}
}
@Override
public <T> Callable<T> wrapCallable(Callable<T> callable) {
final String groupId =TxTransactionLocal.getInstance().getTxGroupId();
return () -> {
TxTransactionLocal.getInstance().setTxGroupId(groupId);
return delegate.wrapCallable(callable).call();
};
}
@Override
public ThreadPoolExecutor getThreadPool(final HystrixThreadPoolKey threadPoolKey, HystrixProperty<Integer> corePoolSize, HystrixProperty<Integer> maximumPoolSize, HystrixProperty<Integer> keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
return this.delegate.getThreadPool(threadPoolKey, corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
@Override
public ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolProperties threadPoolProperties) {
return this.delegate.getThreadPool(threadPoolKey, threadPoolProperties);
}
@Override
public BlockingQueue<Runnable> getBlockingQueue(int maxQueueSize) {
return this.delegate.getBlockingQueue(maxQueueSize);
}
@Override
public <T> HystrixRequestVariable<T> getRequestVariable(HystrixRequestVariableLifecycle<T> rv) {
return this.delegate.getRequestVariable(rv);
}
}

View File

@ -26,6 +26,7 @@ import org.springframework.stereotype.Component;
/**
* SpringCloudTxTransactionAspect.
*
* @author xiaoyu
*/
@Aspect
@ -33,6 +34,11 @@ import org.springframework.stereotype.Component;
public class SpringCloudTxTransactionAspect extends AbstractTxTransactionAspect implements Ordered {
/**
* Instantiates a new Spring cloud tx transaction aspect.
*
* @param springCloudTxTransactionInterceptor the spring cloud tx transaction interceptor
*/
@Autowired
public SpringCloudTxTransactionAspect(final SpringCloudTxTransactionInterceptor springCloudTxTransactionInterceptor) {
this.setTxTransactionInterceptor(springCloudTxTransactionInterceptor);

View File

@ -20,10 +20,10 @@ package org.dromara.raincat.springcloud.interceptor;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.dromara.raincat.common.constant.CommonConstant;
import org.dromara.raincat.common.holder.LogUtil;
import org.dromara.raincat.core.concurrent.threadlocal.CompensationLocal;
import org.dromara.raincat.core.interceptor.TxTransactionInterceptor;
import org.dromara.raincat.core.mediator.RpcMediator;
import org.dromara.raincat.core.service.AspectTransactionService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -61,9 +61,9 @@ public class SpringCloudTxTransactionInterceptor implements TxTransactionInterce
try {
RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
groupId = request.getHeader(CommonConstant.TX_TRANSACTION_GROUP);
groupId = RpcMediator.getInstance().acquire(request::getHeader);
} catch (IllegalStateException e) {
LogUtil.error(LOGGER,"Not Http request ,can't get RequestContextHolder!", e::getMessage);
LogUtil.error(LOGGER, "Not Http request ,can't get RequestContextHolder!", e::getMessage);
}
}
return aspectTransactionService.invoke(groupId, pjp);

View File

@ -18,22 +18,32 @@
package org.dromara.raincat.springcloud.service;
import org.apache.commons.lang3.RandomUtils;
import org.dromara.raincat.core.service.RpcApplicationService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.Optional;
/**
* SpringCloudRpcApplicationServiceImpl.
*
* @author xiaoyu
*/
@Service("rpcApplicationService")
public class SpringCloudRpcApplicationServiceImpl implements RpcApplicationService {
private static final String DEFAULT_APPLICATION_NAME = "raincat-springCloud";
@Value("${spring.application.name}")
private String modelName;
private String appName;
@Override
public String findModelName() {
return modelName;
return Optional.ofNullable(appName).orElse(buildDefaultApplicationName());
}
private String buildDefaultApplicationName() {
return DEFAULT_APPLICATION_NAME + RandomUtils.nextInt(1, 10);
}
}